octocode-cli 1.2.8 → 1.2.10

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 (282) hide show
  1. package/README.md +45 -38
  2. package/out/octocode-cli.js +73 -11763
  3. package/package.json +35 -36
  4. package/skills/README.md +42 -114
  5. package/skills/{octocode-code-engineer → octocode-engineer}/.claude/settings.local.json +2 -1
  6. package/skills/octocode-engineer/README.md +99 -0
  7. package/skills/octocode-engineer/SKILL.md +413 -0
  8. package/skills/octocode-engineer/build.mjs +29 -0
  9. package/skills/{octocode-code-engineer → octocode-engineer}/eslint.config.mjs +3 -13
  10. package/skills/{octocode-code-engineer → octocode-engineer}/package.json +28 -27
  11. package/skills/octocode-engineer/references/ast-reference.md +166 -0
  12. package/skills/{octocode-code-engineer → octocode-engineer}/references/cli-reference.md +80 -6
  13. package/skills/octocode-engineer/references/externals.md +86 -0
  14. package/skills/{octocode-code-engineer → octocode-engineer}/references/output-files.md +46 -6
  15. package/skills/octocode-engineer/references/quality-indicators.md +202 -0
  16. package/skills/octocode-engineer/references/tool-workflows.md +298 -0
  17. package/skills/octocode-engineer/references/validation-playbooks.md +99 -0
  18. package/skills/octocode-engineer/scripts/ast/search.js +45 -0
  19. package/skills/octocode-engineer/scripts/ast/tree-search.js +27 -0
  20. package/skills/octocode-engineer/scripts/index.js +173 -0
  21. package/skills/octocode-engineer/scripts/run.js +179 -0
  22. package/skills/octocode-engineer/src/analysis/dependencies.ts +378 -0
  23. package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/discovery.test.ts +57 -0
  24. package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/discovery.ts +43 -0
  25. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/search.test.ts +113 -0
  26. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/search.ts +64 -1
  27. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-sitter.test.ts +118 -2
  28. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-sitter.ts +65 -3
  29. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/ts-analyzer.test.ts +281 -1
  30. package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/ts-analyzer.ts +173 -3
  31. package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/security.test.ts +73 -0
  32. package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/security.ts +62 -4
  33. package/skills/octocode-engineer/src/detector-gating.test.ts +59 -0
  34. package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/code-quality.ts +342 -0
  35. package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/index.ts +8 -0
  36. package/skills/{octocode-code-engineer → octocode-engineer}/src/index.test.ts +565 -11
  37. package/skills/octocode-engineer/src/index.ts +468 -0
  38. package/skills/octocode-engineer/src/pipeline/affected.test.ts +147 -0
  39. package/skills/octocode-engineer/src/pipeline/affected.ts +68 -0
  40. package/skills/octocode-engineer/src/pipeline/baseline.test.ts +276 -0
  41. package/skills/octocode-engineer/src/pipeline/baseline.ts +76 -0
  42. package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cli.test.ts +300 -53
  43. package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cli.ts +180 -36
  44. package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +264 -0
  45. package/skills/octocode-engineer/src/pipeline/config-loader.ts +109 -0
  46. package/skills/octocode-engineer/src/pipeline/create-options.ts +55 -0
  47. package/skills/octocode-engineer/src/pipeline/health-score.test.ts +65 -0
  48. package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/main.ts +130 -17
  49. package/skills/octocode-engineer/src/pipeline/progress.ts +51 -0
  50. package/skills/octocode-engineer/src/pipeline/reporters.test.ts +155 -0
  51. package/skills/octocode-engineer/src/pipeline/reporters.ts +64 -0
  52. package/skills/octocode-engineer/src/reporting/graph-features.test.ts +279 -0
  53. package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/output-contract.test.ts +6 -0
  54. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +1066 -0
  55. package/skills/octocode-engineer/src/reporting/summary-md.ts +1604 -0
  56. package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/writer.ts +136 -13
  57. package/skills/octocode-engineer/src/run.ts +78 -0
  58. package/skills/{octocode-code-engineer → octocode-engineer}/src/sanity.test.ts +1 -1
  59. package/skills/octocode-engineer/src/types/analysis.ts +25 -0
  60. package/skills/octocode-engineer/src/types/collectors.ts +134 -0
  61. package/skills/{octocode-code-engineer → octocode-engineer}/src/types/constants.ts +75 -41
  62. package/skills/octocode-engineer/src/types/core.ts +203 -0
  63. package/skills/octocode-engineer/src/types/dependency.ts +215 -0
  64. package/skills/octocode-engineer/src/types/file-entry.ts +108 -0
  65. package/skills/octocode-engineer/src/types/findings.ts +105 -0
  66. package/skills/{octocode-code-engineer → octocode-engineer}/src/types/index.ts +60 -30
  67. package/skills/octocode-engineer/src/types/tree-sitter.ts +38 -0
  68. package/skills/{octocode-code-engineer → octocode-engineer}/tsconfig.json +1 -0
  69. package/skills/octocode-research/.octocode/scan/.cache/analysis-cache.json +1 -0
  70. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/architecture.json +1 -0
  71. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/ast-trees.txt +5566 -0
  72. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/code-quality.json +1 -0
  73. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/dead-code.json +1 -0
  74. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/file-inventory.json +1 -0
  75. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/findings.json +1 -0
  76. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/graph.md +189 -0
  77. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/security.json +1 -0
  78. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/summary.json +1 -0
  79. package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/summary.md +265 -0
  80. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/architecture.json +1 -0
  81. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/ast-trees.txt +5555 -0
  82. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/code-quality.json +1 -0
  83. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/dead-code.json +1 -0
  84. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/file-inventory.json +1 -0
  85. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/findings.json +1 -0
  86. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/graph.md +190 -0
  87. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/security.json +1 -0
  88. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/summary.json +1 -0
  89. package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/summary.md +265 -0
  90. package/skills/octocode-research/CHANGELOG.md +60 -0
  91. package/skills/octocode-research/README.md +102 -388
  92. package/skills/octocode-research/SKILL.md +169 -498
  93. package/skills/octocode-research/package.json +19 -31
  94. package/skills/octocode-research/references/PARALLEL_AGENT_PROTOCOL.md +19 -0
  95. package/skills/octocode-research/references/SESSION_MANAGEMENT.md +38 -0
  96. package/skills/octocode-research/scripts/server-init.js +1 -1
  97. package/skills/octocode-research/scripts/server.d.ts +2 -1
  98. package/skills/octocode-research/scripts/server.js +329 -233
  99. package/skills/octocode-research/src/__tests__/integration/promptsRoutes.test.ts +180 -0
  100. package/skills/octocode-research/src/__tests__/integration/serverHttp.test.ts +221 -0
  101. package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +194 -0
  102. package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +501 -0
  103. package/skills/octocode-research/src/__tests__/unit/readiness.test.ts +61 -0
  104. package/skills/octocode-research/src/__tests__/unit/resilience.test.ts +192 -0
  105. package/skills/octocode-research/src/__tests__/unit/responseFactory.test.ts +172 -0
  106. package/skills/octocode-research/src/__tests__/unit/responseParser.test.ts +288 -0
  107. package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +509 -0
  108. package/skills/octocode-research/src/index.ts +4 -124
  109. package/skills/octocode-research/src/middleware/queryParser.ts +0 -26
  110. package/skills/octocode-research/src/routes/lsp.ts +58 -59
  111. package/skills/octocode-research/src/routes/package.ts +35 -65
  112. package/skills/octocode-research/src/routes/prompts.ts +3 -3
  113. package/skills/octocode-research/src/routes/tools.ts +8 -20
  114. package/skills/octocode-research/src/server-init.ts +30 -237
  115. package/skills/octocode-research/src/server.ts +50 -23
  116. package/skills/octocode-research/src/types/errorGuards.ts +9 -80
  117. package/skills/octocode-research/src/types/guards.ts +0 -28
  118. package/skills/octocode-research/src/types/mcp.ts +11 -66
  119. package/skills/octocode-research/src/types/responses.ts +11 -129
  120. package/skills/octocode-research/src/utils/circuitBreaker.ts +0 -21
  121. package/skills/octocode-research/src/utils/logger.ts +1 -97
  122. package/skills/octocode-research/src/utils/resilience.ts +2 -12
  123. package/skills/octocode-research/src/utils/responseFactory.ts +0 -42
  124. package/skills/octocode-research/src/utils/responseParser.ts +3 -25
  125. package/skills/octocode-research/src/utils/retry.ts +0 -63
  126. package/skills/octocode-research/src/utils/routeFactory.ts +1 -1
  127. package/skills/octocode-research/src/validation/httpPreprocess.ts +0 -3
  128. package/skills/octocode-research/src/validation/index.ts +0 -1
  129. package/skills/octocode-research/src/validation/schemas.ts +0 -63
  130. package/skills/octocode-research/src/validation/toolCallSchema.ts +3 -3
  131. package/skills/octocode-research/tsdown.config.ts +4 -0
  132. package/skills/octocode-research/vitest.config.ts +3 -0
  133. package/skills/octocode-code-engineer/.plan/VALIDATED_PLAN.md +0 -223
  134. package/skills/octocode-code-engineer/README.md +0 -178
  135. package/skills/octocode-code-engineer/SKILL.md +0 -418
  136. package/skills/octocode-code-engineer/minify-scripts.mjs +0 -32
  137. package/skills/octocode-code-engineer/references/agent-ast-reading-rfc.md +0 -95
  138. package/skills/octocode-code-engineer/references/architecture-techniques.md +0 -121
  139. package/skills/octocode-code-engineer/references/ast-search.md +0 -210
  140. package/skills/octocode-code-engineer/references/ast-tree-search.md +0 -151
  141. package/skills/octocode-code-engineer/references/concepts.md +0 -107
  142. package/skills/octocode-code-engineer/references/finding-categories.md +0 -128
  143. package/skills/octocode-code-engineer/references/improvement-roadmap.md +0 -304
  144. package/skills/octocode-code-engineer/references/playbooks.md +0 -204
  145. package/skills/octocode-code-engineer/references/present-results.md +0 -136
  146. package/skills/octocode-code-engineer/references/tool-workflows.md +0 -566
  147. package/skills/octocode-code-engineer/references/validate-investigate.md +0 -225
  148. package/skills/octocode-code-engineer/scripts/analysis/dependencies.js +0 -1
  149. package/skills/octocode-code-engineer/scripts/analysis/dependency-summary.js +0 -1
  150. package/skills/octocode-code-engineer/scripts/analysis/discovery.js +0 -1
  151. package/skills/octocode-code-engineer/scripts/analysis/graph-analytics.js +0 -1
  152. package/skills/octocode-code-engineer/scripts/analysis/semantic.js +0 -1
  153. package/skills/octocode-code-engineer/scripts/ast/helpers.js +0 -1
  154. package/skills/octocode-code-engineer/scripts/ast/metrics.js +0 -1
  155. package/skills/octocode-code-engineer/scripts/ast/search.js +0 -2
  156. package/skills/octocode-code-engineer/scripts/ast/tree-search.js +0 -2
  157. package/skills/octocode-code-engineer/scripts/ast/tree-sitter.js +0 -1
  158. package/skills/octocode-code-engineer/scripts/ast/ts-analyzer.js +0 -1
  159. package/skills/octocode-code-engineer/scripts/collectors/chains.js +0 -1
  160. package/skills/octocode-code-engineer/scripts/collectors/effects.js +0 -1
  161. package/skills/octocode-code-engineer/scripts/collectors/input-sources.js +0 -1
  162. package/skills/octocode-code-engineer/scripts/collectors/performance.js +0 -1
  163. package/skills/octocode-code-engineer/scripts/collectors/prototype-pollution.js +0 -1
  164. package/skills/octocode-code-engineer/scripts/collectors/security.js +0 -1
  165. package/skills/octocode-code-engineer/scripts/collectors/test-profile.js +0 -1
  166. package/skills/octocode-code-engineer/scripts/common/is-direct-run.js +0 -1
  167. package/skills/octocode-code-engineer/scripts/common/utils.js +0 -1
  168. package/skills/octocode-code-engineer/scripts/detectors/code-quality.js +0 -1
  169. package/skills/octocode-code-engineer/scripts/detectors/cohesion.js +0 -1
  170. package/skills/octocode-code-engineer/scripts/detectors/coupling.js +0 -1
  171. package/skills/octocode-code-engineer/scripts/detectors/cycle.js +0 -1
  172. package/skills/octocode-code-engineer/scripts/detectors/dead-code.js +0 -1
  173. package/skills/octocode-code-engineer/scripts/detectors/import-style.js +0 -1
  174. package/skills/octocode-code-engineer/scripts/detectors/index.js +0 -1
  175. package/skills/octocode-code-engineer/scripts/detectors/security.js +0 -1
  176. package/skills/octocode-code-engineer/scripts/detectors/semantic.js +0 -1
  177. package/skills/octocode-code-engineer/scripts/detectors/shared.js +0 -1
  178. package/skills/octocode-code-engineer/scripts/detectors/test-quality.js +0 -1
  179. package/skills/octocode-code-engineer/scripts/index.js +0 -1
  180. package/skills/octocode-code-engineer/scripts/pipeline/cache.js +0 -1
  181. package/skills/octocode-code-engineer/scripts/pipeline/cli.js +0 -1
  182. package/skills/octocode-code-engineer/scripts/pipeline/main.js +0 -2
  183. package/skills/octocode-code-engineer/scripts/reporting/analysis.js +0 -1
  184. package/skills/octocode-code-engineer/scripts/reporting/summary-md.js +0 -1
  185. package/skills/octocode-code-engineer/scripts/reporting/writer.js +0 -1
  186. package/skills/octocode-code-engineer/scripts/types/constants.js +0 -1
  187. package/skills/octocode-code-engineer/scripts/types/index.js +0 -1
  188. package/skills/octocode-code-engineer/scripts/types/interfaces.js +0 -1
  189. package/skills/octocode-code-engineer/src/analysis/dependencies.ts +0 -406
  190. package/skills/octocode-code-engineer/src/index.ts +0 -403
  191. package/skills/octocode-code-engineer/src/reporting/summary-md.test.ts +0 -421
  192. package/skills/octocode-code-engineer/src/reporting/summary-md.ts +0 -714
  193. package/skills/octocode-code-engineer/src/types/interfaces.ts +0 -682
  194. package/skills/octocode-research/src/types/toolTypes.ts +0 -33
  195. package/skills/octocode-research/src/utils/logEmoji.ts +0 -103
  196. /package/skills/{octocode-code-engineer → octocode-engineer}/.octocode/rfc/RFC-code-engineer-weakness-fixes.md +0 -0
  197. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/architecture.ts.html +0 -0
  198. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ast-helpers.ts.html +0 -0
  199. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ast-search.ts.html +0 -0
  200. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/base.css +0 -0
  201. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/block-navigation.js +0 -0
  202. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/cache.ts.html +0 -0
  203. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/cli.ts.html +0 -0
  204. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/clover.xml +0 -0
  205. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-effects.ts.html +0 -0
  206. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-input-sources.ts.html +0 -0
  207. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-performance.ts.html +0 -0
  208. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-prototype-pollution.ts.html +0 -0
  209. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-security.ts.html +0 -0
  210. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-test-profile.ts.html +0 -0
  211. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/coverage-final.json +0 -0
  212. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/dependencies.ts.html +0 -0
  213. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/dependency-summary.ts.html +0 -0
  214. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/discovery.ts.html +0 -0
  215. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/favicon.png +0 -0
  216. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/graph-analytics.ts.html +0 -0
  217. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/index.html +0 -0
  218. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/index.ts.html +0 -0
  219. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/metrics.ts.html +0 -0
  220. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/pipeline.ts.html +0 -0
  221. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/prettify.css +0 -0
  222. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/prettify.js +0 -0
  223. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/report-analysis.ts.html +0 -0
  224. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/report-writer.ts.html +0 -0
  225. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/security-detectors.ts.html +0 -0
  226. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/semantic-detectors.ts.html +0 -0
  227. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/semantic.ts.html +0 -0
  228. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/sort-arrow-sprite.png +0 -0
  229. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/sorter.js +0 -0
  230. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/summary-md.ts.html +0 -0
  231. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/test-quality-detectors.ts.html +0 -0
  232. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/tree-sitter-analyzer.ts.html +0 -0
  233. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ts-analyzer.ts.html +0 -0
  234. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/types.ts.html +0 -0
  235. /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/utils.ts.html +0 -0
  236. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependencies.test.ts +0 -0
  237. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependency-summary.test.ts +0 -0
  238. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependency-summary.ts +0 -0
  239. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/graph-analytics.test.ts +0 -0
  240. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/graph-analytics.ts +0 -0
  241. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/semantic.test.ts +0 -0
  242. /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/semantic.ts +0 -0
  243. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/helpers.test.ts +0 -0
  244. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/helpers.ts +0 -0
  245. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/metrics.test.ts +0 -0
  246. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/metrics.ts +0 -0
  247. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-search.test.ts +0 -0
  248. /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-search.ts +0 -0
  249. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/chains.ts +0 -0
  250. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/effects.test.ts +0 -0
  251. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/effects.ts +0 -0
  252. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/input-sources.test.ts +0 -0
  253. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/input-sources.ts +0 -0
  254. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/performance.test.ts +0 -0
  255. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/performance.ts +0 -0
  256. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/prototype-pollution.test.ts +0 -0
  257. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/prototype-pollution.ts +0 -0
  258. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/test-profile.test.ts +0 -0
  259. /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/test-profile.ts +0 -0
  260. /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/is-direct-run.test.ts +0 -0
  261. /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/is-direct-run.ts +0 -0
  262. /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/utils.test.ts +0 -0
  263. /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/utils.ts +0 -0
  264. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/cohesion.ts +0 -0
  265. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/coupling.ts +0 -0
  266. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/cycle.ts +0 -0
  267. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/dead-code.ts +0 -0
  268. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/import-style.ts +0 -0
  269. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/index.test.ts +0 -0
  270. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/security.test.ts +0 -0
  271. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/security.ts +0 -0
  272. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/semantic.ts +0 -0
  273. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/shared.ts +0 -0
  274. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/test-quality.test.ts +0 -0
  275. /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/test-quality.ts +0 -0
  276. /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cache.test.ts +0 -0
  277. /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cache.ts +0 -0
  278. /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/main.test.ts +0 -0
  279. /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline.test.ts +0 -0
  280. /package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/analysis.test.ts +0 -0
  281. /package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/analysis.ts +0 -0
  282. /package/skills/{octocode-code-engineer → octocode-engineer}/vitest.config.ts +0 -0
@@ -1,175 +1,37 @@
1
1
  /**
2
- * Server Init Script
2
+ * Server Init Script — Detached Daemon Launcher
3
3
  *
4
- * Handles server initialization with mutex lock:
5
- * 1. Acquires atomic lock to prevent concurrent startups
6
- * 2. Checks if server is running (health check)
7
- * 3. Starts server if not running
8
- * 4. Waits for status "ok"
9
- * 5. Outputs "ok" on success
4
+ * 1. Checks if server is already running (health check)
5
+ * 2. If running prints "ok" and exits
6
+ * 3. If not → starts server as **detached** process, waits for health, prints "ok", exits
10
7
  *
11
- * Improvements:
12
- * - Atomic lock using O_CREAT | O_EXCL | O_WRONLY (no race condition)
13
- * - Exponential backoff retry for lock acquisition
14
- * - Environment variable configuration
15
- * - Spawn error handling
16
- * - Better health check error logging
8
+ * Lifecycle: The server runs as an independent daemon (detached, unref'd).
9
+ * No client owns the server it self-terminates after 30 minutes of idle.
10
+ * Every invocation of this script exits after confirming the server is healthy.
17
11
  *
18
12
  * Usage: npm run server-init
19
13
  * Exit codes: 0 = success, 1 = error
20
14
  */
21
15
 
22
16
  import { spawn } from 'child_process';
23
- import {
24
- existsSync,
25
- mkdirSync,
26
- unlinkSync,
27
- readFileSync,
28
- constants,
29
- openSync,
30
- writeSync,
31
- closeSync,
32
- statSync,
33
- } from 'fs';
34
17
  import { join } from 'path';
35
- import { homedir } from 'os';
36
18
 
37
19
  // =============================================================================
38
20
  // Configuration (Environment Variables)
39
21
  // =============================================================================
40
22
 
41
- const PORT = parseInt(process.env.OCTOCODE_PORT || '1987', 10);
42
- const HEALTH_URL = `http://localhost:${PORT}/health`;
43
- const LOCK_DIR = join(homedir(), '.octocode');
44
- const LOCK_FILE = join(LOCK_DIR, 'server-init.lock');
45
- const LOCK_TIMEOUT_MS = parseInt(process.env.OCTOCODE_LOCK_TIMEOUT || '60000', 10);
23
+ const PORT = parseInt(process.env.OCTOCODE_RESEARCH_PORT || process.env.OCTOCODE_PORT || '1987', 10);
24
+ const HOST = process.env.OCTOCODE_RESEARCH_HOST || 'localhost';
25
+ const HEALTH_URL = `http://${HOST}:${PORT}/health`;
46
26
  const MAX_WAIT_MS = parseInt(process.env.OCTOCODE_INIT_TIMEOUT || '30000', 10);
47
27
  const POLL_INTERVAL_MS = parseInt(process.env.OCTOCODE_POLL_INTERVAL || '500', 10);
48
28
 
49
- interface LockData {
50
- pid: number;
51
- timestamp: number;
52
- }
53
-
54
29
  interface HealthResponse {
55
30
  status: 'ok' | 'initializing' | string;
56
31
  }
57
32
 
58
33
  // =============================================================================
59
- // Atomic Mutex Lock (Based on Snyk pattern - O_EXCL for atomic creation)
60
- // =============================================================================
61
-
62
- function ensureLockDir(): void {
63
- if (!existsSync(LOCK_DIR)) {
64
- mkdirSync(LOCK_DIR, { recursive: true });
65
- }
66
- }
67
-
68
- function isLockStale(lockPath: string): boolean {
69
- if (!existsSync(lockPath)) return true;
70
-
71
- try {
72
- const content = readFileSync(lockPath, 'utf-8');
73
- if (content && content.trim().length > 0) {
74
- const data: LockData = JSON.parse(content);
75
-
76
- // Check timestamp
77
- if (Date.now() - data.timestamp > LOCK_TIMEOUT_MS) {
78
- return true;
79
- }
80
-
81
- // Check if process exists
82
- try {
83
- process.kill(data.pid, 0);
84
- return false; // Process exists, lock is valid
85
- } catch {
86
- return true; // Process doesn't exist
87
- }
88
- }
89
- } catch {
90
- // Fall back to mtime check
91
- }
92
-
93
- // Fallback: check file modification time
94
- try {
95
- const stats = statSync(lockPath);
96
- return Date.now() - stats.mtimeMs > LOCK_TIMEOUT_MS;
97
- } catch {
98
- return true;
99
- }
100
- }
101
-
102
- function safeUnlink(filePath: string): void {
103
- try {
104
- if (existsSync(filePath)) {
105
- unlinkSync(filePath);
106
- }
107
- } catch {
108
- // Ignore errors
109
- }
110
- }
111
-
112
- async function acquireLock(): Promise<boolean> {
113
- ensureLockDir();
114
-
115
- // Only retry for stale lock removal race condition, not for valid locks
116
- const STALE_RETRY_LIMIT = 3;
117
-
118
- for (let attempt = 0; attempt < STALE_RETRY_LIMIT; attempt++) {
119
- try {
120
- // Atomic create - fails with EEXIST if file exists
121
- const fd = openSync(LOCK_FILE, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);
122
-
123
- const lockData: LockData = {
124
- pid: process.pid,
125
- timestamp: Date.now(),
126
- };
127
-
128
- writeSync(fd, JSON.stringify(lockData));
129
- closeSync(fd);
130
- return true;
131
- } catch (err: unknown) {
132
- const nodeErr = err as NodeJS.ErrnoException;
133
-
134
- if (nodeErr.code === 'EEXIST') {
135
- // Lock exists - check if stale
136
- if (isLockStale(LOCK_FILE)) {
137
- safeUnlink(LOCK_FILE);
138
- // Small delay to avoid tight loop on stale lock race
139
- await new Promise((r) => setTimeout(r, 50));
140
- continue; // Retry after removing stale lock
141
- }
142
-
143
- // Lock is VALID - another process is starting server
144
- // Don't retry, let caller fall back to waiting for server
145
- return false;
146
- } else {
147
- // Unexpected error
148
- console.error(`[server-init] Lock error: ${nodeErr.message}`);
149
- return false;
150
- }
151
- }
152
- }
153
-
154
- return false; // Failed after stale lock retries
155
- }
156
-
157
- function releaseLock(): void {
158
- try {
159
- if (existsSync(LOCK_FILE)) {
160
- const data: LockData = JSON.parse(readFileSync(LOCK_FILE, 'utf-8'));
161
- // Only release if we own the lock
162
- if (data.pid === process.pid) {
163
- unlinkSync(LOCK_FILE);
164
- }
165
- }
166
- } catch {
167
- // Ignore errors during cleanup
168
- }
169
- }
170
-
171
- // =============================================================================
172
- // Health Check (Improved error handling)
34
+ // Health Check
173
35
  // =============================================================================
174
36
 
175
37
  async function checkHealth(): Promise<HealthResponse | null> {
@@ -184,7 +46,6 @@ async function checkHealth(): Promise<HealthResponse | null> {
184
46
 
185
47
  return (await response.json()) as HealthResponse;
186
48
  } catch (error: unknown) {
187
- // Only log unexpected errors, not connection refused (expected when server down)
188
49
  if (error instanceof Error && !error.message.includes('ECONNREFUSED')) {
189
50
  console.error(`[server-init] Health check error: ${error.message}`);
190
51
  }
@@ -193,7 +54,7 @@ async function checkHealth(): Promise<HealthResponse | null> {
193
54
  }
194
55
 
195
56
  // =============================================================================
196
- // Server Start (Improved with error handling)
57
+ // Server Start — detached daemon (survives parent exit)
197
58
  // =============================================================================
198
59
 
199
60
  function startServer(): Promise<void> {
@@ -202,21 +63,20 @@ function startServer(): Promise<void> {
202
63
  const serverScript = join(scriptDir, 'server.js');
203
64
 
204
65
  const child = spawn('node', [serverScript], {
205
- detached: true,
206
66
  stdio: 'ignore',
207
67
  cwd: scriptDir,
68
+ detached: true,
208
69
  });
209
70
 
210
- // Handle spawn errors (e.g., ENOENT if node not found)
211
71
  child.on('error', (err) => {
212
72
  console.error(`[server-init] Failed to start server: ${err.message}`);
213
73
  reject(err);
214
74
  });
215
75
 
216
- // Give a small window for immediate spawn errors
76
+ child.unref();
77
+
217
78
  setTimeout(() => {
218
- child.unref();
219
- console.log(`[server-init] Started server process (pid: ${child.pid})`);
79
+ console.log(`[server-init] Spawned detached server process (pid: ${child.pid})`);
220
80
  resolve();
221
81
  }, 100);
222
82
  });
@@ -242,7 +102,6 @@ async function waitForReady(): Promise<boolean> {
242
102
  }
243
103
 
244
104
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
245
- // Gradual backoff up to 2s
246
105
  pollInterval = Math.min(pollInterval * 1.5, 2000);
247
106
  }
248
107
 
@@ -254,19 +113,15 @@ async function waitForReady(): Promise<boolean> {
254
113
  // =============================================================================
255
114
 
256
115
  async function main(): Promise<void> {
257
- // ==========================================================================
258
- // FAST PATH: Check if server is already running (no lock needed)
259
- // ==========================================================================
116
+ // Fast path: server already running → exit immediately
260
117
  const initialHealth = await checkHealth();
261
118
 
262
119
  if (initialHealth?.status === 'ok') {
263
- // Server is running - immediate success, no lock needed
264
120
  console.log('ok');
265
121
  process.exit(0);
266
122
  }
267
123
 
268
124
  if (initialHealth?.status === 'initializing') {
269
- // Server is starting - just wait for it, no lock needed
270
125
  console.log('[server-init] Server is initializing, waiting...');
271
126
  const ready = await waitForReady();
272
127
  if (ready) {
@@ -278,86 +133,24 @@ async function main(): Promise<void> {
278
133
  }
279
134
  }
280
135
 
281
- // ==========================================================================
282
- // SLOW PATH: Server not running - need lock to start it
283
- // ==========================================================================
284
- const lockAcquired = await acquireLock();
285
-
286
- if (!lockAcquired) {
287
- // Another process is starting the server - wait for it
288
- console.log('[server-init] Another process is starting server, waiting...');
289
- const ready = await waitForReady();
290
- if (ready) {
291
- console.log('ok');
292
- process.exit(0);
293
- } else {
294
- console.error('[server-init] ERROR: Timeout waiting for server');
295
- process.exit(1);
296
- }
297
- }
136
+ // Server not running — start it (detached)
137
+ console.log('[server-init] Server not running, starting detached daemon...');
298
138
 
299
139
  try {
300
- // Double-check health after acquiring lock (another process may have started it)
301
- const health = await checkHealth();
302
-
303
- if (health?.status === 'ok') {
304
- console.log('ok');
305
- releaseLock();
306
- process.exit(0);
307
- }
308
-
309
- if (health?.status === 'initializing') {
310
- console.log('[server-init] Server is initializing, waiting...');
311
- const ready = await waitForReady();
312
- if (ready) {
313
- console.log('ok');
314
- releaseLock();
315
- process.exit(0);
316
- } else {
317
- console.error('[server-init] ERROR: Server stuck in initializing state');
318
- releaseLock();
319
- process.exit(1);
320
- }
321
- }
322
-
323
- // Server not running - start it
324
- console.log('[server-init] Server not running, starting...');
325
-
326
- try {
327
- await startServer();
328
- } catch {
329
- console.error('[server-init] ERROR: Failed to spawn server process');
330
- releaseLock();
331
- process.exit(1);
332
- }
333
-
334
- // Wait for server to be ready
335
- const ready = await waitForReady();
336
- if (ready) {
337
- console.log('ok');
338
- releaseLock();
339
- process.exit(0);
340
- } else {
341
- console.error('[server-init] ERROR: Server failed to start within timeout');
342
- releaseLock();
343
- process.exit(1);
344
- }
345
- } catch (error) {
346
- console.error('[server-init] ERROR:', error instanceof Error ? error.message : error);
347
- releaseLock();
140
+ await startServer();
141
+ } catch {
142
+ console.error('[server-init] ERROR: Failed to spawn server process');
348
143
  process.exit(1);
349
144
  }
350
- }
351
145
 
352
- // Cleanup on exit
353
- process.on('SIGINT', () => {
354
- releaseLock();
355
- process.exit(130);
356
- });
146
+ const ready = await waitForReady();
147
+ if (!ready) {
148
+ console.error('[server-init] ERROR: Server failed to start within timeout');
149
+ process.exit(1);
150
+ }
357
151
 
358
- process.on('SIGTERM', () => {
359
- releaseLock();
360
- process.exit(143);
361
- });
152
+ console.log('ok');
153
+ process.exit(0);
154
+ }
362
155
 
363
156
  main();
@@ -1,5 +1,8 @@
1
1
  import express, { type Express, type Request, type Response, type NextFunction } from 'express';
2
2
  import type { Server } from 'http';
3
+ import { writeFileSync, unlinkSync, mkdirSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { homedir } from 'os';
3
6
  import { toolsRoutes } from './routes/tools.js';
4
7
  import { promptsRoutes } from './routes/prompts.js';
5
8
  import { errorHandler } from './middleware/errorHandler.js';
@@ -12,6 +15,8 @@ import { agentLog, successLog, errorLog, dimLog, warnLog } from './utils/colors.
12
15
  import { fireAndForgetWithTimeout } from './utils/asyncTimeout.js';
13
16
  import { errorQueue } from './utils/errorQueue.js';
14
17
 
18
+ declare const __PACKAGE_VERSION__: string;
19
+
15
20
  const HOST = process.env.OCTOCODE_RESEARCH_HOST || 'localhost';
16
21
 
17
22
  const getPort = (raw?: string): number => {
@@ -31,7 +36,7 @@ const getPort = (raw?: string): number => {
31
36
  return port;
32
37
  };
33
38
 
34
- const PORT = getPort(process.env.OCTOCODE_RESEARCH_PORT);
39
+ const PORT = getPort(process.env.OCTOCODE_RESEARCH_PORT || process.env.OCTOCODE_PORT);
35
40
 
36
41
  const MAX_IDLE_TIME_MS = 30 * 60 * 1000; // 30 minutes idle before restart
37
42
  const IDLE_CHECK_INTERVAL_MS = 120 * 1000; // Check every 2 minute
@@ -41,6 +46,27 @@ let lastRequestTime: number = Date.now();
41
46
  let idleCheckInterval: NodeJS.Timeout | null = null;
42
47
  let isShuttingDown = false;
43
48
 
49
+ // PID file for daemon lifecycle management
50
+ const OCTOCODE_DIR = process.env.OCTOCODE_HOME || join(homedir(), '.octocode');
51
+ export const PID_FILE = join(OCTOCODE_DIR, `research-server-${PORT}.pid`);
52
+
53
+ function writePidFile(): void {
54
+ try {
55
+ mkdirSync(OCTOCODE_DIR, { recursive: true, mode: 0o700 });
56
+ writeFileSync(PID_FILE, String(process.pid), { mode: 0o600 });
57
+ } catch {
58
+ // Non-fatal — server works without PID file
59
+ }
60
+ }
61
+
62
+ function removePidFile(): void {
63
+ try {
64
+ unlinkSync(PID_FILE);
65
+ } catch {
66
+ // Already removed or never written
67
+ }
68
+ }
69
+
44
70
  /**
45
71
  * Check if server has been idle and should restart
46
72
  */
@@ -52,7 +78,6 @@ function checkIdleRestart(): void {
52
78
  console.log(warnLog(`⚠️ Server idle for ${idleSeconds}s (>${MAX_IDLE_TIME_MS / 1000}s). Initiating restart...`));
53
79
  gracefulShutdown('IDLE_TIMEOUT');
54
80
  } else if (idleTime > MAX_IDLE_TIME_MS / 2) {
55
- // Log warning at 50% threshold (30 minutes)
56
81
  console.log(dimLog(`⏰ Idle: ${idleSeconds}s / ${MAX_IDLE_TIME_MS / 1000}s`));
57
82
  }
58
83
  }
@@ -110,9 +135,10 @@ export async function createServer(): Promise<Express> {
110
135
  status: initialized ? 'ok' : 'initializing',
111
136
  host: HOST,
112
137
  port: PORT,
113
- version: '2.2.0',
138
+ version: __PACKAGE_VERSION__,
114
139
  uptime: Math.floor(process.uptime()),
115
- processManager: 'pm2',
140
+ processManager: 'self (detached daemon)',
141
+ pid: process.pid,
116
142
  // Idle tracking info
117
143
  idle: {
118
144
  currentMs: idleTimeMs,
@@ -150,11 +176,13 @@ export async function createServer(): Promise<Express> {
150
176
  code: 'NOT_FOUND',
151
177
  availableRoutes: [
152
178
  'GET /health',
179
+ 'GET /tools/initContext',
153
180
  'GET /tools/list',
181
+ 'GET /tools/info',
154
182
  'GET /tools/info/:toolName',
183
+ 'GET /tools/metadata',
155
184
  'GET /tools/schemas',
156
185
  'GET /tools/system',
157
- 'GET /tools/initContext',
158
186
  'POST /tools/call/:toolName',
159
187
  'GET /prompts/list',
160
188
  'GET /prompts/info/:promptName',
@@ -170,11 +198,11 @@ export async function createServer(): Promise<Express> {
170
198
  }
171
199
 
172
200
  /**
173
- * Graceful shutdown handler for PM2
174
- * PM2 sends SIGINT, we clean up and exit (PM2 handles restart)
201
+ * Graceful shutdown handler.
202
+ * Triggered by SIGTERM, SIGINT, or idle timeout. Cleans up all resources
203
+ * including PID file, circuit breakers, and HTTP connections.
175
204
  */
176
205
  function gracefulShutdown(signal: string): void {
177
- // Prevent double-shutdown (e.g., SIGINT + SIGTERM in quick succession)
178
206
  if (isShuttingDown) {
179
207
  console.log(dimLog(`Already shutting down, ignoring ${signal}`));
180
208
  return;
@@ -183,25 +211,27 @@ function gracefulShutdown(signal: string): void {
183
211
 
184
212
  console.log(agentLog(`\n🛑 Received ${signal}. Starting graceful shutdown...`));
185
213
 
186
- // Force exit safety net (PM2 kill_timeout is 120s, we exit at 110s)
187
- const FORCE_EXIT_TIMEOUT_MS = 110 * 1000;
214
+ const FORCE_EXIT_TIMEOUT_MS = 30 * 1000;
188
215
  setTimeout(() => {
189
216
  console.log(warnLog('⚠️ Force exiting due to drain timeout'));
190
217
  process.exit(1);
191
218
  }, FORCE_EXIT_TIMEOUT_MS).unref();
192
219
 
193
- // 1. Stop idle check interval first
220
+ // 1. Remove PID file immediately
221
+ removePidFile();
222
+
223
+ // 2. Stop idle check interval
194
224
  stopIdleCheck();
195
225
 
196
- // 2. Stop circuit cleanup interval
226
+ // 3. Stop circuit cleanup interval
197
227
  stopCircuitCleanup();
198
228
  console.log(successLog('✅ Circuit cleanup interval stopped'));
199
229
 
200
- // 3. Clear circuit breakers
230
+ // 4. Clear circuit breakers
201
231
  clearAllCircuits();
202
232
  console.log(successLog('✅ Circuit breakers cleared'));
203
233
 
204
- // 4. Close HTTP server (waits for connections to drain)
234
+ // 5. Close HTTP server (waits for connections to drain)
205
235
  if (server) {
206
236
  console.log(dimLog('⏳ Waiting for connections to drain...'));
207
237
  server.close((err) => {
@@ -210,7 +240,7 @@ function gracefulShutdown(signal: string): void {
210
240
  process.exit(1);
211
241
  }
212
242
  console.log(successLog('✅ HTTP server closed'));
213
- process.exit(0); // PM2 handles restart
243
+ process.exit(0);
214
244
  });
215
245
  } else {
216
246
  process.exit(0);
@@ -223,7 +253,8 @@ export async function startServer(): Promise<void> {
223
253
  await new Promise<void>((resolve) => {
224
254
  const httpServer = app.listen(PORT, HOST, () => {
225
255
  server = httpServer;
226
- console.log(agentLog(`🔍 Octocode Research Server running on http://${HOST}:${PORT}`));
256
+ writePidFile();
257
+ console.log(agentLog(`🔍 Octocode Research Server running on http://${HOST}:${PORT} (pid: ${process.pid})`));
227
258
  console.log(dimLog(`⏳ initializing context...`));
228
259
 
229
260
  // Start background initialization (Warm Start)
@@ -244,18 +275,14 @@ export async function startServer(): Promise<void> {
244
275
  console.log(dimLog(` GET /tools/initContext - System prompt + schemas (LOAD FIRST)`));
245
276
  console.log(dimLog(` GET /tools/system - System prompt only`));
246
277
  console.log(dimLog(` GET /tools/list - List all tools`));
278
+ console.log(dimLog(` GET /tools/info - All tools with details`));
247
279
  console.log(dimLog(` GET /tools/info/:toolName - Tool schema (BEFORE calling)`));
280
+ console.log(dimLog(` GET /tools/metadata - Raw MCP metadata`));
248
281
  console.log(dimLog(` GET /tools/schemas - All tools schemas`));
249
282
  console.log(dimLog(` POST /tools/call/:toolName - Execute tool`));
250
283
  console.log(dimLog(` GET /prompts/list - List prompts`));
251
284
  console.log(dimLog(` GET /prompts/info/:name - Get prompt content`));
252
285
 
253
- // Signal PM2 that we're ready
254
- if (process.send) {
255
- process.send('ready');
256
- console.log(dimLog('📡 PM2 ready signal sent'));
257
- }
258
-
259
286
  // Log session initialization after server is ready
260
287
  fireAndForgetWithTimeout(
261
288
  () => logSessionInit(),
@@ -272,7 +299,7 @@ export async function startServer(): Promise<void> {
272
299
  });
273
300
  }
274
301
 
275
- // Signal handlers - PM2 sends SIGINT for graceful shutdown
302
+ // Signal handlers server is a detached daemon, handles its own signals
276
303
  process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
277
304
  process.on('SIGINT', () => gracefulShutdown('SIGINT'));
278
305
 
@@ -8,40 +8,20 @@
8
8
  */
9
9
 
10
10
  // =============================================================================
11
- // Error Interfaces
11
+ // Internal Interfaces & Guards
12
12
  // =============================================================================
13
13
 
14
- /**
15
- * Error with HTTP status code (e.g., from API responses)
16
- */
17
- export interface ErrorWithStatus {
14
+ interface ErrorWithStatus {
18
15
  status: number;
19
16
  message?: string;
20
17
  }
21
18
 
22
- /**
23
- * Error with error code (e.g., Node.js system errors)
24
- */
25
- export interface ErrorWithCode {
19
+ interface ErrorWithCode {
26
20
  code: string;
27
21
  message?: string;
28
22
  }
29
23
 
30
- /**
31
- * Error with headers (e.g., rate limit responses)
32
- */
33
- export interface ErrorWithHeaders {
34
- headers: Record<string, string>;
35
- }
36
-
37
- // =============================================================================
38
- // Type Guards
39
- // =============================================================================
40
-
41
- /**
42
- * Check if error has a status property (number)
43
- */
44
- export function isErrorWithStatus(err: unknown): err is ErrorWithStatus {
24
+ function isErrorWithStatus(err: unknown): err is ErrorWithStatus {
45
25
  return (
46
26
  err !== null &&
47
27
  typeof err === 'object' &&
@@ -50,10 +30,7 @@ export function isErrorWithStatus(err: unknown): err is ErrorWithStatus {
50
30
  );
51
31
  }
52
32
 
53
- /**
54
- * Check if error has a code property (string)
55
- */
56
- export function isErrorWithCode(err: unknown): err is ErrorWithCode {
33
+ function isErrorWithCode(err: unknown): err is ErrorWithCode {
57
34
  return (
58
35
  err !== null &&
59
36
  typeof err === 'object' &&
@@ -62,10 +39,7 @@ export function isErrorWithCode(err: unknown): err is ErrorWithCode {
62
39
  );
63
40
  }
64
41
 
65
- /**
66
- * Check if error has a message property (string)
67
- */
68
- export function hasMessage(err: unknown): err is { message: string } {
42
+ function hasMessage(err: unknown): err is { message: string } {
69
43
  return (
70
44
  err !== null &&
71
45
  typeof err === 'object' &&
@@ -74,77 +48,32 @@ export function hasMessage(err: unknown): err is { message: string } {
74
48
  );
75
49
  }
76
50
 
77
- /**
78
- * Check if error has headers property (object)
79
- */
80
- export function hasHeaders(err: unknown): err is ErrorWithHeaders {
81
- return (
82
- err !== null &&
83
- typeof err === 'object' &&
84
- 'headers' in err &&
85
- typeof (err as { headers: unknown }).headers === 'object' &&
86
- (err as ErrorWithHeaders).headers !== null
87
- );
88
- }
89
-
90
51
  // =============================================================================
91
- // Safe Property Accessors
52
+ // Public API
92
53
  // =============================================================================
93
54
 
94
- /**
95
- * Safely get status from error (undefined if not present)
96
- */
97
55
  export function getErrorStatus(err: unknown): number | undefined {
98
56
  return isErrorWithStatus(err) ? err.status : undefined;
99
57
  }
100
58
 
101
- /**
102
- * Safely get code from error (undefined if not present)
103
- */
104
- export function getErrorCode(err: unknown): string | undefined {
59
+ function getErrorCode(err: unknown): string | undefined {
105
60
  return isErrorWithCode(err) ? err.code : undefined;
106
61
  }
107
62
 
108
- /**
109
- * Safely get message from error (undefined if not present)
110
- */
111
- export function getErrorMessage(err: unknown): string | undefined {
63
+ function getErrorMessage(err: unknown): string | undefined {
112
64
  return hasMessage(err) ? err.message : undefined;
113
65
  }
114
66
 
115
- /**
116
- * Safely get header value from error (undefined if not present)
117
- */
118
- export function getErrorHeader(err: unknown, header: string): string | undefined {
119
- if (hasHeaders(err)) {
120
- return err.headers[header];
121
- }
122
- return undefined;
123
- }
124
-
125
- // =============================================================================
126
- // Composite Checks
127
- // =============================================================================
128
-
129
- /**
130
- * Check if error status is in a given list
131
- */
132
67
  export function hasStatusIn(err: unknown, statuses: readonly number[]): boolean {
133
68
  const status = getErrorStatus(err);
134
69
  return status !== undefined && statuses.includes(status);
135
70
  }
136
71
 
137
- /**
138
- * Check if error code is in a given list
139
- */
140
72
  export function hasCodeIn(err: unknown, codes: readonly string[]): boolean {
141
73
  const code = getErrorCode(err);
142
74
  return code !== undefined && codes.includes(code);
143
75
  }
144
76
 
145
- /**
146
- * Check if error message matches any pattern
147
- */
148
77
  export function messageMatches(err: unknown, patterns: readonly RegExp[]): boolean {
149
78
  const message = getErrorMessage(err);
150
79
  return message !== undefined && patterns.some((p) => p.test(message));