oc-pilot 0.5.1 → 0.88.1

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 (481) hide show
  1. package/CHANGELOG.md +683 -0
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +588 -20
  4. package/README.ru.md +572 -10
  5. package/dist/cli.js +185 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cli.test.js +1211 -1
  8. package/dist/cli.test.js.map +1 -1
  9. package/dist/commands/anti-regression.js +97 -0
  10. package/dist/commands/anti-regression.js.map +1 -0
  11. package/dist/commands/arch-diff.js +80 -0
  12. package/dist/commands/arch-diff.js.map +1 -0
  13. package/dist/commands/authz.js +167 -0
  14. package/dist/commands/authz.js.map +1 -0
  15. package/dist/commands/autopsy.js +64 -0
  16. package/dist/commands/autopsy.js.map +1 -0
  17. package/dist/commands/bankruptcy.js +60 -0
  18. package/dist/commands/bankruptcy.js.map +1 -0
  19. package/dist/commands/battle.js +119 -0
  20. package/dist/commands/battle.js.map +1 -0
  21. package/dist/commands/boundaries.js +114 -0
  22. package/dist/commands/boundaries.js.map +1 -0
  23. package/dist/commands/bounty.js +56 -0
  24. package/dist/commands/bounty.js.map +1 -0
  25. package/dist/commands/brag.js +62 -0
  26. package/dist/commands/brag.js.map +1 -0
  27. package/dist/commands/cache.js +62 -0
  28. package/dist/commands/cache.js.map +1 -0
  29. package/dist/commands/cinema.js +61 -0
  30. package/dist/commands/cinema.js.map +1 -0
  31. package/dist/commands/cleanup.js +110 -0
  32. package/dist/commands/cleanup.js.map +1 -0
  33. package/dist/commands/commit.js +177 -0
  34. package/dist/commands/commit.js.map +1 -0
  35. package/dist/commands/commit.test.js +160 -0
  36. package/dist/commands/commit.test.js.map +1 -0
  37. package/dist/commands/compliance.js +121 -0
  38. package/dist/commands/compliance.js.map +1 -0
  39. package/dist/commands/contract-drift.js +97 -0
  40. package/dist/commands/contract-drift.js.map +1 -0
  41. package/dist/commands/coverage.js +137 -0
  42. package/dist/commands/coverage.js.map +1 -0
  43. package/dist/commands/day.js +116 -0
  44. package/dist/commands/day.js.map +1 -0
  45. package/dist/commands/day.test.js +45 -0
  46. package/dist/commands/day.test.js.map +1 -0
  47. package/dist/commands/deps.js +245 -0
  48. package/dist/commands/deps.js.map +1 -0
  49. package/dist/commands/docgen.js +4 -2
  50. package/dist/commands/docgen.js.map +1 -1
  51. package/dist/commands/doctor.js +146 -2
  52. package/dist/commands/doctor.js.map +1 -1
  53. package/dist/commands/doctor.test.js +69 -0
  54. package/dist/commands/doctor.test.js.map +1 -0
  55. package/dist/commands/echo.js +78 -0
  56. package/dist/commands/echo.js.map +1 -0
  57. package/dist/commands/ecosystem-verify.js +113 -0
  58. package/dist/commands/ecosystem-verify.js.map +1 -0
  59. package/dist/commands/env-sync.js +102 -0
  60. package/dist/commands/env-sync.js.map +1 -0
  61. package/dist/commands/explain.js +115 -0
  62. package/dist/commands/explain.js.map +1 -0
  63. package/dist/commands/fix.js +145 -3
  64. package/dist/commands/fix.js.map +1 -1
  65. package/dist/commands/flaky.js +111 -0
  66. package/dist/commands/flaky.js.map +1 -0
  67. package/dist/commands/fuzz.js +119 -0
  68. package/dist/commands/fuzz.js.map +1 -0
  69. package/dist/commands/hivemind.js +124 -0
  70. package/dist/commands/hivemind.js.map +1 -0
  71. package/dist/commands/impact.js +73 -0
  72. package/dist/commands/impact.js.map +1 -0
  73. package/dist/commands/init.js +73 -11
  74. package/dist/commands/init.js.map +1 -1
  75. package/dist/commands/init.test.js +138 -0
  76. package/dist/commands/init.test.js.map +1 -0
  77. package/dist/commands/install-hook.js +161 -0
  78. package/dist/commands/install-hook.js.map +1 -0
  79. package/dist/commands/install-hook.test.js +100 -0
  80. package/dist/commands/install-hook.test.js.map +1 -0
  81. package/dist/commands/invariants.js +103 -0
  82. package/dist/commands/invariants.js.map +1 -0
  83. package/dist/commands/mock-leak.js +97 -0
  84. package/dist/commands/mock-leak.js.map +1 -0
  85. package/dist/commands/mutate.js +99 -0
  86. package/dist/commands/mutate.js.map +1 -0
  87. package/dist/commands/pack.js +144 -0
  88. package/dist/commands/pack.js.map +1 -0
  89. package/dist/commands/preflight.js +137 -0
  90. package/dist/commands/preflight.js.map +1 -0
  91. package/dist/commands/query.js +57 -0
  92. package/dist/commands/query.js.map +1 -0
  93. package/dist/commands/ready.js +152 -0
  94. package/dist/commands/ready.js.map +1 -0
  95. package/dist/commands/receipt.js +289 -0
  96. package/dist/commands/receipt.js.map +1 -0
  97. package/dist/commands/replay.js +112 -0
  98. package/dist/commands/replay.js.map +1 -0
  99. package/dist/commands/replay.test.js +125 -0
  100. package/dist/commands/replay.test.js.map +1 -0
  101. package/dist/commands/restore.js +54 -0
  102. package/dist/commands/restore.js.map +1 -0
  103. package/dist/commands/review.js +263 -4
  104. package/dist/commands/review.js.map +1 -1
  105. package/dist/commands/review.test.js +160 -0
  106. package/dist/commands/review.test.js.map +1 -0
  107. package/dist/commands/reviewers.js +86 -0
  108. package/dist/commands/reviewers.js.map +1 -0
  109. package/dist/commands/roast.js +102 -0
  110. package/dist/commands/roast.js.map +1 -0
  111. package/dist/commands/sandbox.js +82 -0
  112. package/dist/commands/sandbox.js.map +1 -0
  113. package/dist/commands/sast.js +162 -0
  114. package/dist/commands/sast.js.map +1 -0
  115. package/dist/commands/scan.js +47 -12
  116. package/dist/commands/scan.js.map +1 -1
  117. package/dist/commands/slop.js +145 -0
  118. package/dist/commands/slop.js.map +1 -0
  119. package/dist/commands/slop.test.js +135 -0
  120. package/dist/commands/slop.test.js.map +1 -0
  121. package/dist/commands/stats.js +61 -0
  122. package/dist/commands/stats.js.map +1 -0
  123. package/dist/commands/test-gen.js +372 -0
  124. package/dist/commands/test-gen.js.map +1 -0
  125. package/dist/commands/test-guard.js +89 -0
  126. package/dist/commands/test-guard.js.map +1 -0
  127. package/dist/commands/test-plan.js +133 -0
  128. package/dist/commands/test-plan.js.map +1 -0
  129. package/dist/commands/zoom-symbol.js +52 -0
  130. package/dist/commands/zoom-symbol.js.map +1 -0
  131. package/dist/core/agent-rules.js +35 -0
  132. package/dist/core/agent-rules.js.map +1 -0
  133. package/dist/core/anthropic.test.js +116 -0
  134. package/dist/core/anthropic.test.js.map +1 -0
  135. package/dist/core/anti-regression.js +161 -0
  136. package/dist/core/anti-regression.js.map +1 -0
  137. package/dist/core/anti-regression.test.js +154 -0
  138. package/dist/core/anti-regression.test.js.map +1 -0
  139. package/dist/core/aql.js +220 -0
  140. package/dist/core/aql.js.map +1 -0
  141. package/dist/core/aql.test.js +64 -0
  142. package/dist/core/aql.test.js.map +1 -0
  143. package/dist/core/arch-diff.js +122 -0
  144. package/dist/core/arch-diff.js.map +1 -0
  145. package/dist/core/arch-diff.test.js +93 -0
  146. package/dist/core/arch-diff.test.js.map +1 -0
  147. package/dist/core/authz.js +292 -0
  148. package/dist/core/authz.js.map +1 -0
  149. package/dist/core/authz.test.js +115 -0
  150. package/dist/core/authz.test.js.map +1 -0
  151. package/dist/core/autopsy.js +230 -0
  152. package/dist/core/autopsy.js.map +1 -0
  153. package/dist/core/autopsy.test.js +106 -0
  154. package/dist/core/autopsy.test.js.map +1 -0
  155. package/dist/core/bankruptcy.js +232 -0
  156. package/dist/core/bankruptcy.js.map +1 -0
  157. package/dist/core/bankruptcy.test.js +91 -0
  158. package/dist/core/bankruptcy.test.js.map +1 -0
  159. package/dist/core/baseline.js +131 -0
  160. package/dist/core/baseline.js.map +1 -0
  161. package/dist/core/baseline.test.js +91 -0
  162. package/dist/core/baseline.test.js.map +1 -0
  163. package/dist/core/battle.js +213 -0
  164. package/dist/core/battle.js.map +1 -0
  165. package/dist/core/battle.test.js +116 -0
  166. package/dist/core/battle.test.js.map +1 -0
  167. package/dist/core/boundaries.js +200 -0
  168. package/dist/core/boundaries.js.map +1 -0
  169. package/dist/core/boundaries.test.js +62 -0
  170. package/dist/core/boundaries.test.js.map +1 -0
  171. package/dist/core/bounty.js +128 -0
  172. package/dist/core/bounty.js.map +1 -0
  173. package/dist/core/bounty.test.js +82 -0
  174. package/dist/core/bounty.test.js.map +1 -0
  175. package/dist/core/brag.js +174 -0
  176. package/dist/core/brag.js.map +1 -0
  177. package/dist/core/brag.test.js +43 -0
  178. package/dist/core/brag.test.js.map +1 -0
  179. package/dist/core/cache.js +189 -0
  180. package/dist/core/cache.js.map +1 -0
  181. package/dist/core/cache.test.js +159 -0
  182. package/dist/core/cache.test.js.map +1 -0
  183. package/dist/core/cinema.js +242 -0
  184. package/dist/core/cinema.js.map +1 -0
  185. package/dist/core/cinema.test.js +73 -0
  186. package/dist/core/cinema.test.js.map +1 -0
  187. package/dist/core/cleanup.js +107 -0
  188. package/dist/core/cleanup.js.map +1 -0
  189. package/dist/core/compliance.js +193 -0
  190. package/dist/core/compliance.js.map +1 -0
  191. package/dist/core/compliance.test.js +123 -0
  192. package/dist/core/compliance.test.js.map +1 -0
  193. package/dist/core/config.js +78 -0
  194. package/dist/core/config.js.map +1 -1
  195. package/dist/core/config.test.js +66 -0
  196. package/dist/core/config.test.js.map +1 -1
  197. package/dist/core/contract-drift.js +296 -0
  198. package/dist/core/contract-drift.js.map +1 -0
  199. package/dist/core/contract-drift.test.js +166 -0
  200. package/dist/core/contract-drift.test.js.map +1 -0
  201. package/dist/core/cost.test.js +103 -0
  202. package/dist/core/cost.test.js.map +1 -0
  203. package/dist/core/coverage.js +335 -0
  204. package/dist/core/coverage.js.map +1 -0
  205. package/dist/core/coverage.test.js +190 -0
  206. package/dist/core/coverage.test.js.map +1 -0
  207. package/dist/core/deps-fix.js +169 -0
  208. package/dist/core/deps-fix.js.map +1 -0
  209. package/dist/core/deps-fix.test.js +176 -0
  210. package/dist/core/deps-fix.test.js.map +1 -0
  211. package/dist/core/deps-health.js +353 -0
  212. package/dist/core/deps-health.js.map +1 -0
  213. package/dist/core/deps-health.test.js +230 -0
  214. package/dist/core/deps-health.test.js.map +1 -0
  215. package/dist/core/deps-why.js +260 -0
  216. package/dist/core/deps-why.js.map +1 -0
  217. package/dist/core/deps-why.test.js +175 -0
  218. package/dist/core/deps-why.test.js.map +1 -0
  219. package/dist/core/deps.js +179 -0
  220. package/dist/core/deps.js.map +1 -0
  221. package/dist/core/deps.test.js +88 -0
  222. package/dist/core/deps.test.js.map +1 -0
  223. package/dist/core/diff-source.js +4 -2
  224. package/dist/core/diff-source.js.map +1 -1
  225. package/dist/core/echo.js +151 -0
  226. package/dist/core/echo.js.map +1 -0
  227. package/dist/core/echo.test.js +90 -0
  228. package/dist/core/echo.test.js.map +1 -0
  229. package/dist/core/ecosystem-verify.js +331 -0
  230. package/dist/core/ecosystem-verify.js.map +1 -0
  231. package/dist/core/ecosystem-verify.test.js +158 -0
  232. package/dist/core/ecosystem-verify.test.js.map +1 -0
  233. package/dist/core/engine-preset.test.js +60 -0
  234. package/dist/core/engine-preset.test.js.map +1 -0
  235. package/dist/core/engine.js +278 -32
  236. package/dist/core/engine.js.map +1 -1
  237. package/dist/core/engine.test.js +63 -0
  238. package/dist/core/engine.test.js.map +1 -1
  239. package/dist/core/env-sync.js +122 -0
  240. package/dist/core/env-sync.js.map +1 -0
  241. package/dist/core/env-sync.test.js +99 -0
  242. package/dist/core/env-sync.test.js.map +1 -0
  243. package/dist/core/file-context.js +4 -2
  244. package/dist/core/file-context.js.map +1 -1
  245. package/dist/core/findings-baseline.js +60 -0
  246. package/dist/core/findings-baseline.js.map +1 -0
  247. package/dist/core/findings-baseline.test.js +77 -0
  248. package/dist/core/findings-baseline.test.js.map +1 -0
  249. package/dist/core/findings.js +68 -21
  250. package/dist/core/findings.js.map +1 -1
  251. package/dist/core/flaky.js +137 -0
  252. package/dist/core/flaky.js.map +1 -0
  253. package/dist/core/flaky.test.js +97 -0
  254. package/dist/core/flaky.test.js.map +1 -0
  255. package/dist/core/format.js +5 -3
  256. package/dist/core/format.js.map +1 -1
  257. package/dist/core/fuzz.js +306 -0
  258. package/dist/core/fuzz.js.map +1 -0
  259. package/dist/core/fuzz.test.js +121 -0
  260. package/dist/core/fuzz.test.js.map +1 -0
  261. package/dist/core/git.js +22 -0
  262. package/dist/core/git.js.map +1 -1
  263. package/dist/core/gitlab.js +176 -0
  264. package/dist/core/gitlab.js.map +1 -0
  265. package/dist/core/gitlab.test.js +199 -0
  266. package/dist/core/gitlab.test.js.map +1 -0
  267. package/dist/core/hivemind.js +250 -0
  268. package/dist/core/hivemind.js.map +1 -0
  269. package/dist/core/hivemind.test.js +79 -0
  270. package/dist/core/hivemind.test.js.map +1 -0
  271. package/dist/core/hologram.js +463 -0
  272. package/dist/core/hologram.js.map +1 -0
  273. package/dist/core/hologram.test.js +124 -0
  274. package/dist/core/hologram.test.js.map +1 -0
  275. package/dist/core/impact.js +240 -0
  276. package/dist/core/impact.js.map +1 -0
  277. package/dist/core/impact.test.js +105 -0
  278. package/dist/core/impact.test.js.map +1 -0
  279. package/dist/core/import-graph.js +170 -0
  280. package/dist/core/import-graph.js.map +1 -0
  281. package/dist/core/import-graph.test.js +52 -0
  282. package/dist/core/import-graph.test.js.map +1 -0
  283. package/dist/core/injection.js +55 -0
  284. package/dist/core/injection.js.map +1 -0
  285. package/dist/core/injection.test.js +45 -0
  286. package/dist/core/injection.test.js.map +1 -0
  287. package/dist/core/invariants.js +286 -0
  288. package/dist/core/invariants.js.map +1 -0
  289. package/dist/core/invariants.test.js +87 -0
  290. package/dist/core/invariants.test.js.map +1 -0
  291. package/dist/core/last-review.js +92 -0
  292. package/dist/core/last-review.js.map +1 -0
  293. package/dist/core/last-review.test.js +97 -0
  294. package/dist/core/last-review.test.js.map +1 -0
  295. package/dist/core/lockfile-support.test.js +112 -0
  296. package/dist/core/lockfile-support.test.js.map +1 -0
  297. package/dist/core/lockfile.js +284 -0
  298. package/dist/core/lockfile.js.map +1 -0
  299. package/dist/core/lockfile.test.js +203 -0
  300. package/dist/core/lockfile.test.js.map +1 -0
  301. package/dist/core/mock-leak.js +120 -0
  302. package/dist/core/mock-leak.js.map +1 -0
  303. package/dist/core/mock-leak.test.js +79 -0
  304. package/dist/core/mock-leak.test.js.map +1 -0
  305. package/dist/core/mutation.js +206 -0
  306. package/dist/core/mutation.js.map +1 -0
  307. package/dist/core/mutation.test.js +104 -0
  308. package/dist/core/mutation.test.js.map +1 -0
  309. package/dist/core/opencode.js +15 -2
  310. package/dist/core/opencode.js.map +1 -1
  311. package/dist/core/opencode.test.js +10 -1
  312. package/dist/core/opencode.test.js.map +1 -1
  313. package/dist/core/options.js +51 -3
  314. package/dist/core/options.js.map +1 -1
  315. package/dist/core/osv.js +202 -0
  316. package/dist/core/osv.js.map +1 -0
  317. package/dist/core/osv.test.js +173 -0
  318. package/dist/core/osv.test.js.map +1 -0
  319. package/dist/core/output-format.test.js +102 -0
  320. package/dist/core/output-format.test.js.map +1 -0
  321. package/dist/core/pack.js +212 -0
  322. package/dist/core/pack.js.map +1 -0
  323. package/dist/core/pack.test.js +129 -0
  324. package/dist/core/pack.test.js.map +1 -0
  325. package/dist/core/phantom.js +155 -0
  326. package/dist/core/phantom.js.map +1 -0
  327. package/dist/core/phantom.test.js +58 -0
  328. package/dist/core/phantom.test.js.map +1 -0
  329. package/dist/core/pr-comment.js +116 -0
  330. package/dist/core/pr-comment.js.map +1 -0
  331. package/dist/core/pr-comment.test.js +53 -0
  332. package/dist/core/pr-comment.test.js.map +1 -0
  333. package/dist/core/pr-review.js +160 -0
  334. package/dist/core/pr-review.js.map +1 -0
  335. package/dist/core/pr-review.test.js +62 -0
  336. package/dist/core/pr-review.test.js.map +1 -0
  337. package/dist/core/preflight-run.js +106 -0
  338. package/dist/core/preflight-run.js.map +1 -0
  339. package/dist/core/preflight.js +173 -0
  340. package/dist/core/preflight.js.map +1 -0
  341. package/dist/core/preflight.test.js +187 -0
  342. package/dist/core/preflight.test.js.map +1 -0
  343. package/dist/core/presets.js +408 -0
  344. package/dist/core/presets.js.map +1 -0
  345. package/dist/core/presets.test.js +79 -0
  346. package/dist/core/presets.test.js.map +1 -0
  347. package/dist/core/prompt.golden.test.js +74 -0
  348. package/dist/core/prompt.golden.test.js.map +1 -0
  349. package/dist/core/prompt.js +43 -4
  350. package/dist/core/prompt.js.map +1 -1
  351. package/dist/core/prompt.test.js +16 -0
  352. package/dist/core/prompt.test.js.map +1 -1
  353. package/dist/core/readiness-fix.js +111 -0
  354. package/dist/core/readiness-fix.js.map +1 -0
  355. package/dist/core/readiness-fix.test.js +99 -0
  356. package/dist/core/readiness-fix.test.js.map +1 -0
  357. package/dist/core/readiness.js +189 -0
  358. package/dist/core/readiness.js.map +1 -0
  359. package/dist/core/readiness.test.js +199 -0
  360. package/dist/core/readiness.test.js.map +1 -0
  361. package/dist/core/receipt.js +193 -0
  362. package/dist/core/receipt.js.map +1 -0
  363. package/dist/core/receipt.test.js +193 -0
  364. package/dist/core/receipt.test.js.map +1 -0
  365. package/dist/core/reviewers.js +179 -0
  366. package/dist/core/reviewers.js.map +1 -0
  367. package/dist/core/reviewers.test.js +105 -0
  368. package/dist/core/reviewers.test.js.map +1 -0
  369. package/dist/core/roast.js +27 -0
  370. package/dist/core/roast.js.map +1 -0
  371. package/dist/core/roast.test.js +19 -0
  372. package/dist/core/roast.test.js.map +1 -0
  373. package/dist/core/router.js +8 -0
  374. package/dist/core/router.js.map +1 -0
  375. package/dist/core/router.test.js +157 -0
  376. package/dist/core/router.test.js.map +1 -0
  377. package/dist/core/rules.js +2 -2
  378. package/dist/core/rules.js.map +1 -1
  379. package/dist/core/run.js +322 -20
  380. package/dist/core/run.js.map +1 -1
  381. package/dist/core/sarif.js +125 -0
  382. package/dist/core/sarif.js.map +1 -0
  383. package/dist/core/sarif.test.js +60 -0
  384. package/dist/core/sarif.test.js.map +1 -0
  385. package/dist/core/sast.js +324 -0
  386. package/dist/core/sast.js.map +1 -0
  387. package/dist/core/sast.test.js +105 -0
  388. package/dist/core/sast.test.js.map +1 -0
  389. package/dist/core/sbom.js +121 -0
  390. package/dist/core/sbom.js.map +1 -0
  391. package/dist/core/sbom.test.js +81 -0
  392. package/dist/core/sbom.test.js.map +1 -0
  393. package/dist/core/second-opinion.js +88 -0
  394. package/dist/core/second-opinion.js.map +1 -0
  395. package/dist/core/second-opinion.test.js +89 -0
  396. package/dist/core/second-opinion.test.js.map +1 -0
  397. package/dist/core/secrets.js +120 -5
  398. package/dist/core/secrets.js.map +1 -1
  399. package/dist/core/secrets.test.js +74 -1
  400. package/dist/core/secrets.test.js.map +1 -1
  401. package/dist/core/shadow.js +94 -0
  402. package/dist/core/shadow.js.map +1 -0
  403. package/dist/core/shadow.test.js +50 -0
  404. package/dist/core/shadow.test.js.map +1 -0
  405. package/dist/core/slicing.js +110 -0
  406. package/dist/core/slicing.js.map +1 -0
  407. package/dist/core/slicing.test.js +287 -0
  408. package/dist/core/slicing.test.js.map +1 -0
  409. package/dist/core/slop/churn.js +49 -0
  410. package/dist/core/slop/churn.js.map +1 -0
  411. package/dist/core/slop/collect.js +186 -0
  412. package/dist/core/slop/collect.js.map +1 -0
  413. package/dist/core/slop/dead-exports.js +101 -0
  414. package/dist/core/slop/dead-exports.js.map +1 -0
  415. package/dist/core/slop/duplicates.js +155 -0
  416. package/dist/core/slop/duplicates.js.map +1 -0
  417. package/dist/core/slop/index.js +72 -0
  418. package/dist/core/slop/index.js.map +1 -0
  419. package/dist/core/slop/model.js +2 -0
  420. package/dist/core/slop/model.js.map +1 -0
  421. package/dist/core/slop/score.js +185 -0
  422. package/dist/core/slop/score.js.map +1 -0
  423. package/dist/core/slop/slop.test.js +160 -0
  424. package/dist/core/slop/slop.test.js.map +1 -0
  425. package/dist/core/slop/source.js +129 -0
  426. package/dist/core/slop/source.js.map +1 -0
  427. package/dist/core/slop/test-debt.js +178 -0
  428. package/dist/core/slop/test-debt.js.map +1 -0
  429. package/dist/core/slop/test-debt.test.js +114 -0
  430. package/dist/core/slop/test-debt.test.js.map +1 -0
  431. package/dist/core/slop/todos.js +117 -0
  432. package/dist/core/slop/todos.js.map +1 -0
  433. package/dist/core/snapshot.js +214 -0
  434. package/dist/core/snapshot.js.map +1 -0
  435. package/dist/core/snapshot.test.js +101 -0
  436. package/dist/core/snapshot.test.js.map +1 -0
  437. package/dist/core/stats.js +119 -0
  438. package/dist/core/stats.js.map +1 -0
  439. package/dist/core/stats.test.js +86 -0
  440. package/dist/core/stats.test.js.map +1 -0
  441. package/dist/core/suppressions.js +96 -0
  442. package/dist/core/suppressions.js.map +1 -0
  443. package/dist/core/suppressions.test.js +90 -0
  444. package/dist/core/suppressions.test.js.map +1 -0
  445. package/dist/core/test-delta.js +53 -0
  446. package/dist/core/test-delta.js.map +1 -0
  447. package/dist/core/test-delta.test.js +41 -0
  448. package/dist/core/test-delta.test.js.map +1 -0
  449. package/dist/core/test-plan.js +212 -0
  450. package/dist/core/test-plan.js.map +1 -0
  451. package/dist/core/test-plan.test.js +94 -0
  452. package/dist/core/test-plan.test.js.map +1 -0
  453. package/dist/core/test-weakening.js +191 -0
  454. package/dist/core/test-weakening.js.map +1 -0
  455. package/dist/core/test-weakening.test.js +114 -0
  456. package/dist/core/test-weakening.test.js.map +1 -0
  457. package/dist/core/tree-scan.js +77 -0
  458. package/dist/core/tree-scan.js.map +1 -0
  459. package/dist/core/tree-scan.test.js +58 -0
  460. package/dist/core/tree-scan.test.js.map +1 -0
  461. package/dist/mcp-prompts.test.js +133 -0
  462. package/dist/mcp-prompts.test.js.map +1 -0
  463. package/dist/mcp.js +3303 -240
  464. package/dist/mcp.js.map +1 -1
  465. package/dist/mcp.test.js +1739 -1
  466. package/dist/mcp.test.js.map +1 -1
  467. package/dist/skills.test.js +221 -0
  468. package/dist/skills.test.js.map +1 -0
  469. package/dist/version.js +1 -1
  470. package/dist/version.js.map +1 -1
  471. package/docs/integrations.md +151 -7
  472. package/package.json +2 -1
  473. package/prompts/oc-pilot.en.md +8 -1
  474. package/prompts/oc-pilot.ru.md +8 -1
  475. package/server.json +2 -2
  476. package/skills/agent-self-review/SKILL.md +87 -0
  477. package/skills/commit-discipline/SKILL.md +86 -0
  478. package/skills/oc-pilot/SKILL.md +86 -0
  479. package/skills/secure-diff-gate/SKILL.md +101 -0
  480. package/skills/stack-review-packs/SKILL.md +76 -0
  481. package/skills/test-failure-triage/SKILL.md +88 -0
@@ -0,0 +1,230 @@
1
+ import { PilotError } from "./errors.js";
2
+ import { runGit } from "./git.js";
3
+ import { splitDiffBlocks } from "./diff.js";
4
+ import { analyzeMockLeaks } from "./mock-leak.js";
5
+ import { scanSource } from "./sast.js";
6
+ import { analyzeTestWeakness } from "./test-weakening.js";
7
+ import { isCodeFile, isGeneratedPath, isTestFile } from "./slop/source.js";
8
+ const RECORD = "\u001e";
9
+ const FIELD = "\u001f";
10
+ const SEVERITY_WEIGHT = { high: 5, medium: 3, low: 1 };
11
+ const SAST_WEIGHT = { high: 5, medium: 3, low: 1 };
12
+ function parseCommit(record) {
13
+ const [hash, shortHash, author, date, subject] = record.split(FIELD);
14
+ if (!hash || !shortHash || !date)
15
+ return undefined;
16
+ return {
17
+ hash,
18
+ shortHash,
19
+ author: author ?? "unknown",
20
+ date,
21
+ subject: subject ?? "(без темы)",
22
+ };
23
+ }
24
+ function readCommit(cwd, ref) {
25
+ const result = runGit(["show", "-s", `--format=%H${FIELD}%h${FIELD}%an${FIELD}%aI${FIELD}%s`, ref], cwd);
26
+ if (result.status !== 0) {
27
+ throw new PilotError(`Коммит не найден: ${ref}`, {
28
+ hint: "Укажите существующий ref, например HEAD или HEAD~1.",
29
+ exitCode: 2,
30
+ });
31
+ }
32
+ const commit = parseCommit(result.stdout.trim());
33
+ if (!commit) {
34
+ throw new PilotError(`Не удалось прочитать коммит: ${ref}`, { exitCode: 2 });
35
+ }
36
+ return commit;
37
+ }
38
+ function readDiff(cwd, ref) {
39
+ const result = runGit(["show", "--format=", "--no-color", "--unified=0", ref], cwd);
40
+ if (result.status !== 0) {
41
+ throw new PilotError(`Не удалось получить diff коммита ${ref}`, { exitCode: 2 });
42
+ }
43
+ return result.stdout;
44
+ }
45
+ /** Added line numbers per file, used to keep SAST findings inside the commit. */
46
+ export function addedLinesByFile(diff) {
47
+ const result = new Map();
48
+ for (const block of splitDiffBlocks(diff)) {
49
+ if (block.path === "(diff)" || block.path === "(unknown)")
50
+ continue;
51
+ const lines = new Set();
52
+ let newLine = 0;
53
+ for (const line of block.text.split("\n")) {
54
+ const hunk = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
55
+ if (hunk) {
56
+ newLine = Number(hunk[1]);
57
+ continue;
58
+ }
59
+ if (line.startsWith("+++") || line.startsWith("---"))
60
+ continue;
61
+ if (line.startsWith("+")) {
62
+ lines.add(newLine);
63
+ newLine += 1;
64
+ }
65
+ else if (line.startsWith(" ")) {
66
+ newLine += 1;
67
+ }
68
+ }
69
+ if (lines.size > 0)
70
+ result.set(block.path.replace(/\\/g, "/"), lines);
71
+ }
72
+ return result;
73
+ }
74
+ function diffStats(diff) {
75
+ let files = 0;
76
+ let additions = 0;
77
+ let deletions = 0;
78
+ for (const line of diff.split("\n")) {
79
+ if (line.startsWith("diff --git "))
80
+ files += 1;
81
+ else if (line.startsWith("+") && !line.startsWith("+++"))
82
+ additions += 1;
83
+ else if (line.startsWith("-") && !line.startsWith("---"))
84
+ deletions += 1;
85
+ }
86
+ return { files, additions, deletions };
87
+ }
88
+ function scanAddedFiles(cwd, ref, added) {
89
+ const signals = [];
90
+ for (const [file, lines] of added) {
91
+ if (!isCodeFile(file) || isTestFile(file) || isGeneratedPath(file))
92
+ continue;
93
+ const show = runGit(["show", `${ref}:${file}`], cwd);
94
+ if (show.status !== 0)
95
+ continue;
96
+ for (const finding of scanSource(file, show.stdout).findings) {
97
+ if (!lines.has(finding.line))
98
+ continue;
99
+ signals.push({
100
+ kind: "sast",
101
+ severity: finding.severity,
102
+ file,
103
+ line: finding.line,
104
+ detail: `${finding.rule}: ${finding.message}`,
105
+ });
106
+ }
107
+ }
108
+ return signals;
109
+ }
110
+ function timeline(cwd, ref, files, depth) {
111
+ if (files.length === 0)
112
+ return [];
113
+ const format = `--format=${RECORD}%H${FIELD}%h${FIELD}%an${FIELD}%aI${FIELD}%s`;
114
+ const before = runGit(["log", `-n${String(depth)}`, format, ref, "--", ...files], cwd);
115
+ const after = runGit(["log", `-n${String(depth)}`, format, `${ref}..HEAD`, "--", ...files], cwd);
116
+ const entries = [];
117
+ const targetHash = readCommit(cwd, ref).hash;
118
+ const push = (text, relation) => {
119
+ for (const record of text.split(RECORD)) {
120
+ const commit = parseCommit(record.trim());
121
+ if (!commit)
122
+ continue;
123
+ if (relation === "before" && commit.hash === targetHash) {
124
+ entries.push({ relation: "target", commit, files });
125
+ }
126
+ else {
127
+ entries.push({ relation, commit, files });
128
+ }
129
+ }
130
+ };
131
+ push(before.stdout, "before");
132
+ push(after.stdout, "after");
133
+ return entries;
134
+ }
135
+ /** Builds a deterministic post-mortem for one commit. */
136
+ export function analyzeAutopsy(cwd, ref, options = {}) {
137
+ const depth = Math.min(50, Math.max(1, options.depth ?? 5));
138
+ const commit = readCommit(cwd, ref);
139
+ const diff = readDiff(cwd, ref);
140
+ const added = addedLinesByFile(diff);
141
+ const changedFiles = [...added.keys()].sort();
142
+ const signals = [];
143
+ signals.push(...scanAddedFiles(cwd, ref, added));
144
+ for (const finding of analyzeTestWeakness(diff)) {
145
+ signals.push({
146
+ kind: "test-weakening",
147
+ severity: "high",
148
+ file: finding.file,
149
+ line: finding.line,
150
+ detail: `${finding.kind}: ${finding.detail}`,
151
+ });
152
+ }
153
+ for (const leak of analyzeMockLeaks(diff).findings) {
154
+ signals.push({
155
+ kind: "mock-leak",
156
+ severity: leak.severity,
157
+ file: leak.file,
158
+ line: leak.line,
159
+ detail: `${leak.kind}: ${leak.detail}`,
160
+ });
161
+ }
162
+ signals.sort((left, right) => left.file.localeCompare(right.file) || left.line - right.line || left.kind.localeCompare(right.kind));
163
+ const suspects = new Map();
164
+ for (const signal of signals) {
165
+ const entry = suspects.get(signal.file) ?? { file: signal.file, score: 0, reasons: [] };
166
+ entry.score += signal.kind === "sast" ? SAST_WEIGHT[signal.severity] : SEVERITY_WEIGHT[signal.severity];
167
+ entry.reasons.push(`${signal.kind}: ${signal.detail}`);
168
+ suspects.set(signal.file, entry);
169
+ }
170
+ const suspectList = [...suspects.values()]
171
+ .sort((left, right) => right.score - left.score || left.file.localeCompare(right.file))
172
+ .slice(0, 5);
173
+ const verdict = signals.some((signal) => signal.severity === "high")
174
+ ? "dangerous"
175
+ : signals.length > 0
176
+ ? "suspicious"
177
+ : "clean";
178
+ const summary = verdict === "dangerous"
179
+ ? `Коммит ${commit.shortHash} оставил ${String(signals.length)} риск(ов), включая high.`
180
+ : verdict === "suspicious"
181
+ ? `Коммит ${commit.shortHash} оставил ${String(signals.length)} риск(ов) без high.`
182
+ : `Коммит ${commit.shortHash} не оставил рискованных сигналов.`;
183
+ return {
184
+ commit,
185
+ stats: diffStats(diff),
186
+ changedFiles,
187
+ signals,
188
+ suspects: suspectList,
189
+ timeline: timeline(cwd, ref, changedFiles, depth),
190
+ verdict,
191
+ summary,
192
+ };
193
+ }
194
+ /** Detective-style Russian report. */
195
+ export function renderAutopsy(report) {
196
+ const lines = [
197
+ "ВСКРЫТИЕ КОММИТА",
198
+ `Коммит: ${report.commit.shortHash} ${report.commit.subject}`,
199
+ `Автор: ${report.commit.author}, ${report.commit.date}`,
200
+ `Изменено: ${String(report.stats.files)} файл(ов), +${String(report.stats.additions)} / -${String(report.stats.deletions)}.`,
201
+ `Вердикт: ${report.verdict}. ${report.summary}`,
202
+ ];
203
+ if (report.changedFiles.length > 0) {
204
+ lines.push("", "Затронутые файлы:");
205
+ for (const file of report.changedFiles)
206
+ lines.push(` ${file}`);
207
+ }
208
+ if (report.signals.length > 0) {
209
+ lines.push("", "Улики:");
210
+ for (const signal of report.signals.slice(0, 20)) {
211
+ lines.push(` ${signal.file}:${String(signal.line)} [${signal.kind}/${signal.severity}] ${signal.detail}`);
212
+ }
213
+ if (report.signals.length > 20)
214
+ lines.push(` …и ещё ${String(report.signals.length - 20)}`);
215
+ }
216
+ if (report.suspects.length > 0) {
217
+ lines.push("", "Подозреваемые:");
218
+ for (const suspect of report.suspects) {
219
+ lines.push(` ${suspect.file} (${String(suspect.score)} очков): ${suspect.reasons.slice(0, 3).join("; ")}`);
220
+ }
221
+ }
222
+ if (report.timeline.length > 0) {
223
+ lines.push("", "Хронология:");
224
+ for (const entry of report.timeline) {
225
+ lines.push(` ${entry.commit.shortHash} ${entry.commit.date.slice(0, 10)} [${entry.relation}] ${entry.commit.subject}`);
226
+ }
227
+ }
228
+ return `${lines.join("\n")}\n`;
229
+ }
230
+ //# sourceMappingURL=autopsy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autopsy.js","sourceRoot":"","sources":["../../src/core/autopsy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import test from "node:test";
7
+ import { analyzeAutopsy, renderAutopsy } from "./autopsy.js";
8
+ function git(args, cwd) {
9
+ const result = spawnSync("git", args, { cwd, encoding: "utf8" });
10
+ if (result.status !== 0) {
11
+ throw new Error(`git ${args.join(" ")} failed: ${result.stderr}`);
12
+ }
13
+ return result.stdout;
14
+ }
15
+ function makeRepo() {
16
+ const dir = mkdtempSync(join(tmpdir(), "oc-pilot-autopsy-"));
17
+ git(["init", "-q"], dir);
18
+ git(["config", "user.email", "test@example.com"], dir);
19
+ git(["config", "user.name", "Test"], dir);
20
+ git(["config", "core.autocrlf", "false"], dir);
21
+ mkdirSync(join(dir, "src"), { recursive: true });
22
+ return dir;
23
+ }
24
+ function commit(dir, message) {
25
+ git(["add", "."], dir);
26
+ git(["commit", "-m", message], dir);
27
+ return git(["rev-parse", "HEAD"], dir).trim();
28
+ }
29
+ test("analyzeAutopsy finds a dangerous command injection", () => {
30
+ const dir = makeRepo();
31
+ try {
32
+ writeFileSync(join(dir, "src", "app.js"), 'const { exec } = require("child_process");\nexec(req.query.cmd);\n', "utf8");
33
+ const hash = commit(dir, "add the debug command");
34
+ const report = analyzeAutopsy(dir, "HEAD");
35
+ assert.equal(report.commit.hash, hash);
36
+ assert.equal(report.verdict, "dangerous");
37
+ assert.ok(report.signals.some((signal) => signal.kind === "sast" && signal.file === "src/app.js"));
38
+ assert.equal(report.suspects[0]?.file, "src/app.js");
39
+ assert.match(report.summary, /high/);
40
+ assert.match(renderAutopsy(report), /ВСКРЫТИЕ КОММИТА/);
41
+ }
42
+ finally {
43
+ rmSync(dir, { recursive: true, force: true });
44
+ }
45
+ });
46
+ test("analyzeAutopsy flags a weakened test", () => {
47
+ const dir = makeRepo();
48
+ try {
49
+ writeFileSync(join(dir, "src", "app.ts"), "export const value = 1;\n", "utf8");
50
+ commit(dir, "add the value");
51
+ writeFileSync(join(dir, "src", "app.test.ts"), 'import { value } from "./app";\n\nit.skip("returns one", () => {\n expect(value).toBe(1);\n});\n', "utf8");
52
+ commit(dir, "skip the failing test");
53
+ const report = analyzeAutopsy(dir, "HEAD");
54
+ assert.ok(report.signals.some((signal) => signal.kind === "test-weakening"));
55
+ assert.equal(report.verdict, "dangerous");
56
+ }
57
+ finally {
58
+ rmSync(dir, { recursive: true, force: true });
59
+ }
60
+ });
61
+ test("analyzeAutopsy reports a clean commit", () => {
62
+ const dir = makeRepo();
63
+ try {
64
+ writeFileSync(join(dir, "src", "value.ts"), "export const value = 1;\n", "utf8");
65
+ commit(dir, "add a value");
66
+ const report = analyzeAutopsy(dir, "HEAD");
67
+ assert.equal(report.verdict, "clean");
68
+ assert.deepEqual(report.signals, []);
69
+ assert.deepEqual(report.suspects, []);
70
+ assert.match(report.summary, /не оставил рискованных сигналов/i);
71
+ }
72
+ finally {
73
+ rmSync(dir, { recursive: true, force: true });
74
+ }
75
+ });
76
+ test("analyzeAutopsy builds a before and after timeline", () => {
77
+ const dir = makeRepo();
78
+ try {
79
+ writeFileSync(join(dir, "src", "app.ts"), "export const value = 1;\n", "utf8");
80
+ commit(dir, "add the value");
81
+ writeFileSync(join(dir, "src", "app.ts"), "export const value = 2;\n", "utf8");
82
+ const target = commit(dir, "bump the value");
83
+ writeFileSync(join(dir, "src", "app.ts"), "export const value = 3;\n", "utf8");
84
+ commit(dir, "bump it again");
85
+ const report = analyzeAutopsy(dir, "HEAD~1", { depth: 5 });
86
+ assert.equal(report.commit.hash, target);
87
+ assert.ok(report.timeline.some((entry) => entry.relation === "target" && entry.commit.hash === target));
88
+ assert.ok(report.timeline.some((entry) => entry.relation === "after"));
89
+ assert.ok(report.timeline.some((entry) => entry.relation === "before"));
90
+ }
91
+ finally {
92
+ rmSync(dir, { recursive: true, force: true });
93
+ }
94
+ });
95
+ test("analyzeAutopsy rejects an unknown revision", () => {
96
+ const dir = makeRepo();
97
+ try {
98
+ writeFileSync(join(dir, "src", "app.ts"), "export const value = 1;\n", "utf8");
99
+ commit(dir, "add the value");
100
+ assert.throws(() => analyzeAutopsy(dir, "does-not-exist"), /does-not-exist|ревизи/i);
101
+ }
102
+ finally {
103
+ rmSync(dir, { recursive: true, force: true });
104
+ }
105
+ });
106
+ //# sourceMappingURL=autopsy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autopsy.test.js","sourceRoot":"","sources":["../../src/core/autopsy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ import { runGit } from "./git.js";
2
+ import { splitDiffBlocks } from "./diff.js";
3
+ import { scanSource } from "./sast.js";
4
+ import { analyzeTestWeakness } from "./test-weakening.js";
5
+ const DEFAULT_HISTORY_DAYS = 90;
6
+ const MIN_COMMITS = 10;
7
+ const MAX_COMMITS = 200;
8
+ const DAY_MS = 86_400_000;
9
+ const MOVING_WINDOW_DAYS = 14;
10
+ const INSUFFICIENT = "[INSUFFICIENT DATA: Need at least 10 commits to compute Slop Velocity]";
11
+ const WEIGHTS = {
12
+ testWeakening: 0.35,
13
+ security: 0.3,
14
+ slop: 0.15,
15
+ todos: 0.1,
16
+ churn: 0.1,
17
+ };
18
+ function clamp01(value) {
19
+ return Math.max(0, Math.min(1, value));
20
+ }
21
+ /** Parses 30d, 2w, 3m or a plain number of days. */
22
+ export function parseHistoryWindow(raw) {
23
+ if (raw === undefined || raw.trim() === "")
24
+ return DEFAULT_HISTORY_DAYS;
25
+ const match = /^(\d+(?:\.\d+)?)([dwm])?$/i.exec(raw.trim());
26
+ if (!match?.[1])
27
+ return DEFAULT_HISTORY_DAYS;
28
+ const value = Number(match[1]);
29
+ const unit = match[2]?.toLowerCase() ?? "d";
30
+ const days = unit === "w" ? value * 7 : unit === "m" ? value * 30 : value;
31
+ return Math.max(1, Math.min(3650, Math.round(days)));
32
+ }
33
+ function dayOf(iso) {
34
+ const date = new Date(iso);
35
+ return Number.isNaN(date.getTime()) ? iso.slice(0, 10) : date.toISOString().slice(0, 10);
36
+ }
37
+ function dayNumber(day) {
38
+ const time = new Date(`${day}T00:00:00.000Z`).getTime();
39
+ return Number.isNaN(time) ? 0 : Math.floor(time / DAY_MS);
40
+ }
41
+ function metricsOf(diff) {
42
+ let todos = 0;
43
+ let churn = 0;
44
+ let sastHigh = 0;
45
+ let sastMedium = 0;
46
+ for (const block of splitDiffBlocks(diff)) {
47
+ if (block.path === "(diff)" || block.path === "(unknown)")
48
+ continue;
49
+ const added = [];
50
+ for (const line of block.text.split("\n")) {
51
+ if (line.startsWith("+") && !line.startsWith("+++")) {
52
+ added.push(line.slice(1));
53
+ churn += 1;
54
+ if (/\b(?:TODO|FIXME|HACK)\b/.test(line))
55
+ todos += 1;
56
+ }
57
+ else if (line.startsWith("-") && !line.startsWith("---")) {
58
+ churn += 1;
59
+ }
60
+ }
61
+ if (added.length === 0)
62
+ continue;
63
+ for (const finding of scanSource(block.path, added.join("\n")).findings) {
64
+ if (finding.severity === "high")
65
+ sastHigh += 1;
66
+ else if (finding.severity === "medium")
67
+ sastMedium += 1;
68
+ }
69
+ }
70
+ const weakness = analyzeTestWeakness(diff).length;
71
+ const slopProxy = Math.min(100, todos * 5 + weakness * 20 + sastHigh * 25 + sastMedium * 10 + churn / 100);
72
+ const score = Math.round(100 *
73
+ (WEIGHTS.testWeakening * clamp01(weakness / 3) +
74
+ WEIGHTS.security * clamp01(sastHigh / 2 + sastMedium / 5) +
75
+ WEIGHTS.slop * clamp01(slopProxy / 100) +
76
+ WEIGHTS.todos * clamp01(todos / 5) +
77
+ WEIGHTS.churn * clamp01(churn / 2000)));
78
+ return { weakness, sastHigh, sastMedium, todos, churn, score };
79
+ }
80
+ function readCommits(cwd, sinceDays) {
81
+ const since = new Date(Date.now() - sinceDays * DAY_MS).toISOString();
82
+ const log = runGit(["log", `--since=${since}`, `--max-count=${String(MAX_COMMITS)}`, "--pretty=format:%H%x1f%aI"], cwd);
83
+ if (log.status !== 0)
84
+ return [];
85
+ const rows = log.stdout
86
+ .split(/\r?\n/)
87
+ .map((line) => line.trim())
88
+ .filter((line) => line.length > 0)
89
+ .map((line) => {
90
+ const [hash, at] = line.split("\u001f");
91
+ return { hash: hash ?? "", at: at ?? "" };
92
+ })
93
+ .filter((row) => row.hash && row.at)
94
+ .reverse();
95
+ const commits = [];
96
+ for (const row of rows) {
97
+ const diff = runGit(["show", "--format=", "--no-color", "--unified=0", row.hash], cwd);
98
+ if (diff.status !== 0)
99
+ continue;
100
+ commits.push({ hash: row.hash, date: dayOf(row.at), ...metricsOf(diff.stdout) });
101
+ }
102
+ return commits;
103
+ }
104
+ function dailyPoints(commits) {
105
+ const byDay = new Map();
106
+ for (const commit of commits) {
107
+ const entry = byDay.get(commit.date) ?? { total: 0, count: 0 };
108
+ entry.total += commit.score;
109
+ entry.count += 1;
110
+ byDay.set(commit.date, entry);
111
+ }
112
+ return [...byDay.entries()]
113
+ .sort((left, right) => left[0].localeCompare(right[0]))
114
+ .map(([date, entry]) => ({ date, score: Math.round(entry.total / entry.count), commits: entry.count }));
115
+ }
116
+ function movingAverage(points, windowDays) {
117
+ return points.map((point, index) => {
118
+ const current = dayNumber(point.date);
119
+ let total = 0;
120
+ let count = 0;
121
+ for (let cursor = index; cursor >= 0; cursor -= 1) {
122
+ const candidate = points[cursor];
123
+ if (current - dayNumber(candidate.date) > windowDays)
124
+ break;
125
+ total += candidate.score;
126
+ count += 1;
127
+ }
128
+ return { ...point, score: Math.round(total / count) };
129
+ });
130
+ }
131
+ function withoutOutliers(points) {
132
+ if (points.length < 4)
133
+ return points;
134
+ const mean = points.reduce((sum, point) => sum + point.score, 0) / points.length;
135
+ const variance = points.reduce((sum, point) => sum + (point.score - mean) ** 2, 0) / points.length;
136
+ const limit = mean + 2 * Math.sqrt(variance);
137
+ const kept = points.filter((point) => point.score <= limit);
138
+ return kept.length >= 4 ? kept : points;
139
+ }
140
+ function regress(points) {
141
+ if (points.length < 2)
142
+ return { slope: 0, intercept: points[0]?.score ?? 0, firstDay: points[0] ? dayNumber(points[0].date) : 0 };
143
+ const firstDay = dayNumber(points[0].date);
144
+ const xs = points.map((point) => dayNumber(point.date) - firstDay);
145
+ const ys = points.map((point) => point.score);
146
+ const meanX = xs.reduce((sum, value) => sum + value, 0) / xs.length;
147
+ const meanY = ys.reduce((sum, value) => sum + value, 0) / ys.length;
148
+ let covariance = 0;
149
+ let variance = 0;
150
+ for (let index = 0; index < xs.length; index += 1) {
151
+ covariance += (xs[index] - meanX) * (ys[index] - meanY);
152
+ variance += (xs[index] - meanX) ** 2;
153
+ }
154
+ const slope = variance === 0 ? 0 : covariance / variance;
155
+ return { slope, intercept: meanY - slope * meanX, firstDay };
156
+ }
157
+ function escapeXml(value) {
158
+ return value
159
+ .replaceAll("&", "&amp;")
160
+ .replaceAll("<", "&lt;")
161
+ .replaceAll(">", "&gt;")
162
+ .replaceAll('"', "&quot;");
163
+ }
164
+ /** Self-contained SVG chart with the smoothed score and the regression line. */
165
+ export function renderBankruptcySvg(points, slope, intercept, firstDay) {
166
+ const width = 720;
167
+ const height = 260;
168
+ const left = 48;
169
+ const right = 16;
170
+ const top = 24;
171
+ const bottom = 36;
172
+ const plotWidth = width - left - right;
173
+ const plotHeight = height - top - bottom;
174
+ const first = points[0] ? dayNumber(points[0].date) : firstDay;
175
+ const last = points.at(-1) ? dayNumber(points.at(-1).date) : first;
176
+ const span = Math.max(1, last - first);
177
+ const x = (day) => left + ((day - first) / span) * plotWidth;
178
+ const y = (score) => top + (1 - Math.max(0, Math.min(100, score)) / 100) * plotHeight;
179
+ const path = points.map((point) => `${x(dayNumber(point.date)).toFixed(1)},${y(point.score).toFixed(1)}`).join(" ");
180
+ const trendStart = slope * 0 + intercept;
181
+ const trendEnd = slope * span + intercept;
182
+ const trend = `M ${left.toFixed(1)} ${y(trendStart).toFixed(1)} L ${(left + plotWidth).toFixed(1)} ${y(trendEnd).toFixed(1)}`;
183
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${String(width)}" height="${String(height)}" viewBox="0 0 ${String(width)} ${String(height)}" role="img" aria-label="Tech debt forecast"><title>Tech debt forecast</title><rect width="${String(width)}" height="${String(height)}" fill="#0b0f14"/><line x1="${String(left)}" y1="${String(top)}" x2="${String(left)}" y2="${String(top + plotHeight)}" stroke="#30363d"/><line x1="${String(left)}" y1="${String(top + plotHeight)}" x2="${String(left + plotWidth)}" y2="${String(top + plotHeight)}" stroke="#30363d"/><line x1="${String(left)}" y1="${String(top)}" x2="${String(left + plotWidth)}" y2="${String(top)}" stroke="#c62828" stroke-dasharray="4 4"/><text x="${String(left - 8)}" y="${String(top + 4)}" text-anchor="end" fill="#c62828" font-family="monospace" font-size="11">100</text><text x="${String(left - 8)}" y="${String(top + plotHeight + 4)}" text-anchor="end" fill="#8b949e" font-family="monospace" font-size="11">0</text><polyline points="${path}" fill="none" stroke="#58a6ff" stroke-width="2"/><path d="${trend}" fill="none" stroke="#f0883e" stroke-width="2" stroke-dasharray="6 3"/>${points[0] ? `<text x="${String(left)}" y="${String(height - 10)}" fill="#8b949e" font-family="monospace" font-size="11">${escapeXml(points[0].date)}</text>` : ""}${points.at(-1) ? `<text x="${String(left + plotWidth)}" y="${String(height - 10)}" text-anchor="end" fill="#8b949e" font-family="monospace" font-size="11">${escapeXml(points.at(-1).date)}</text>` : ""}</svg>`;
184
+ }
185
+ export function buildBankruptcy(cwd, options = {}) {
186
+ const historyDays = Math.max(1, Math.min(3650, Math.round(options.historyDays ?? DEFAULT_HISTORY_DAYS)));
187
+ const commits = readCommits(cwd, historyDays);
188
+ const insufficient = commits.length < MIN_COMMITS;
189
+ const rawPoints = dailyPoints(commits);
190
+ const points = movingAverage(rawPoints, MOVING_WINDOW_DAYS);
191
+ const regressionPoints = withoutOutliers(points);
192
+ const { slope, intercept, firstDay } = regress(regressionPoints);
193
+ const currentScore = points.at(-1)?.score ?? 0;
194
+ const daysToBankruptcy = slope > 0.001 ? Math.max(0, Math.round((100 - intercept) / slope)) : null;
195
+ const forecastDate = daysToBankruptcy === null
196
+ ? null
197
+ : new Date((firstDay + daysToBankruptcy) * DAY_MS).toISOString().slice(0, 10);
198
+ const verdict = insufficient ? "insufficient" : forecastDate ? "forecast" : "stable";
199
+ const lines = [];
200
+ if (insufficient) {
201
+ lines.push(INSUFFICIENT);
202
+ lines.push(`Коммитов в окне ${String(historyDays)} дн.: ${String(commits.length)}.`);
203
+ }
204
+ else {
205
+ lines.push(`Прогноз техдолга: ${String(commits.length)} коммитов за ${String(historyDays)} дн.`);
206
+ lines.push(`Текущий балл: ${String(currentScore)}/100. Скорость: ${slope >= 0 ? "+" : ""}${slope.toFixed(2)}/день.`);
207
+ if (forecastDate) {
208
+ lines.push(`Порог 100 будет достигнут: ${forecastDate} (через ${String(daysToBankruptcy)} дн.).`);
209
+ }
210
+ else {
211
+ lines.push("Скорость не положительна: в обозримом окне банкротство не прогнозируется.");
212
+ }
213
+ }
214
+ if (options.explain) {
215
+ lines.push("", "Формула: score = 100 * (0.35 * testWeakening + 0.30 * security + 0.15 * slop + 0.10 * todos + 0.10 * churn).", "testWeakening: ослабленные тесты из diff (вес 0.35), security: high/medium SAST на добавленных строках (0.30), slop: TODO + слабые тесты + SAST + churn (0.15), todos: добавленные TODO/FIXME/HACK (0.10), churn: добавленные и удалённые строки (0.10).", `Сглаживание: скользящее среднее ${String(MOVING_WINDOW_DAYS)} дн., выбросы выше mean+2σ исключены из регрессии.`);
216
+ }
217
+ return {
218
+ historyDays,
219
+ commits: commits.length,
220
+ points,
221
+ weights: WEIGHTS,
222
+ slopePerDay: Number(slope.toFixed(3)),
223
+ currentScore,
224
+ forecastDate,
225
+ daysToBankruptcy,
226
+ verdict,
227
+ insufficient,
228
+ content: `${lines.join("\n")}\n`,
229
+ svg: renderBankruptcySvg(points, slope, intercept, firstDay),
230
+ };
231
+ }
232
+ //# sourceMappingURL=bankruptcy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bankruptcy.js","sourceRoot":"","sources":["../../src/core/bankruptcy.ts"],"names":[],"mappings":"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"}