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
package/README.ru.md CHANGED
@@ -23,7 +23,7 @@ oc-pilot scan # секреты в diff без вызова модел
23
23
  Из GitHub, с фиксацией на теге релиза (работает до первого релиза в npm):
24
24
 
25
25
  ```bash
26
- npm install -g https://github.com/MyNameIsNikki/oc-pilot/archive/refs/tags/v0.5.1.tar.gz
26
+ npm install -g https://github.com/MyNameIsNikki/oc-pilot/archive/refs/tags/v0.5.2.tar.gz
27
27
  ```
28
28
 
29
29
  Из npm, после публикации:
@@ -104,10 +104,79 @@ oc-pilot review --engine openai --model deepseek-chat \
104
104
  # Локальная модель через Ollama (ключ для localhost не нужен)
105
105
  oc-pilot review --engine openai --model qwen2.5-coder \
106
106
  --base-url http://127.0.0.1:11434/v1
107
+
108
+ # То же через пресет
109
+ oc-pilot review --engine-preset ollama --model qwen2.5-coder
107
110
  ```
108
111
 
109
112
  Ключ читается из `OC_PILOT_API_KEY` или `OPENAI_API_KEY`; переменную можно переименовать через `--api-key-env` / `apiKeyEnv`. Ключ не попадает в логи и ошибки.
110
113
 
114
+ ### Пресеты движков
115
+
116
+ Для частых OpenAI-совместимых провайдеров `--engine-preset` сам подставляет base URL, переменную с ключом и (где есть разумный дефолт) модель:
117
+
118
+ | Пресет | Base URL | Переменная ключа | Модель по умолчанию |
119
+ | --- | --- | --- | --- |
120
+ | `ollama` | `http://localhost:11434/v1` | `OLLAMA_API_KEY` (на loopback не нужен) | `llama3.2` |
121
+ | `lmstudio` | `http://localhost:1234/v1` | `LMSTUDIO_API_KEY` (на loopback не нужен) | — |
122
+ | `openrouter` | `https://openrouter.ai/api/v1` | `OPENROUTER_API_KEY` | — |
123
+
124
+ Пресет переключает движок на `openai`, если явно не указано иное, а явные флаги всегда важнее: `oc-pilot review --engine-preset ollama --model qwen2.5-coder` оставит endpoint из пресета и переопределит только модель.
125
+
126
+ ### Движок Anthropic
127
+
128
+ `--engine anthropic` работает с Claude Messages API напрямую, без SDK:
129
+
130
+ ```bash
131
+ ANTHROPIC_API_KEY=sk-ant-... oc-pilot review --engine anthropic --model claude-sonnet-4-5
132
+ ```
133
+
134
+ Системный промпт уходит блоком `system` с `cache_control: {"type": "ephemeral"}`, поэтому повторные ревью переиспользуют закэшированный префикс. Запросы несут `anthropic-version: 2023-06-01` и `x-api-key`. Расход токенов попадает в ту же таблицу цен, что и у движка `openai`, так что `--max-cost` и `oc-pilot stats` работают без изменений.
135
+
136
+ Slicing, двухфазный роутинг и кеш ответов остаются только у `openai`: движок Anthropic всегда отправляет один запрос за прогон.
137
+
138
+ ### Умный slicing (`openai`)
139
+
140
+ Когда diff не помещается в один промпт (300 000 символов), движок `openai` не отбрасывает файлы усечением. Вместо этого блоки diff по файлам группируются в слайсы, каждый укладывается в бюджет; на каждый слайс делается отдельный вызов API с тем же дополнительным контекстом, ответы склеиваются в один анализ по OUTPUT SCHEMA (количество вызовов видно в `meta.slices`). До трёх слайсов уходят параллельно, ответы собираются в исходном порядке файлов. Файл, чей diff больше бюджета, уходит отдельным слайсом и усекается только тогда. Slicing работает для `review`, `test-fix`, `custom` и `commit --engine openai`; `fix` всегда шлёт один промпт, потому что должен вернуть единый патч.
141
+
142
+ ### Повторы запросов
143
+
144
+ Временные сбои не валят прогон: ответы 408, 425, 429, 500, 502, 503 и 504 повторяются до трёх раз с экспоненциальной задержкой (500 мс, 1 с, 2 с, потолок 8 с), заголовок `Retry-After` важнее расчётной задержки. Ошибки аутентификации, прочие 4xx, сетевые ошибки и таймауты падают сразу — повторять их бессмысленно. Слайсы подчиняются тому же правилу.
145
+
146
+ ### Двухфазный роутинг (`openai`)
147
+
148
+ `review` может прогонять diff через дешёвую модель-триаж до основного вызова. Модель триажа получает те же данные с компактным системным промптом и отвечает одной строкой: `TRIAGE: REVIEW` или `TRIAGE: LGTM`. Тривиально безопасные изменения (доки, форматирование, бампы версий, переименования) получают `LGTM` — основной вызов пропускается целиком; остальное идёт в полный ревью. Любая ошибка или нечитаемый ответ триажа откатывается к полному ревью: роутинг экономит деньги, но не способен пропустить проблему. Блокировка по секретам (`--fail-on-secrets`) работает независимо от роутера.
149
+
150
+ ```bash
151
+ oc-pilot review --router --router-model gpt-4.1-mini --engine openai --model gpt-4.1
152
+ ```
153
+
154
+ Включается на один запуск флагом `--router` или постоянно — полями `routerEnabled: true` и `routerModel` в `.oc-pilot.json` (или переменными `OC_PILOT_ROUTER` / `OC_PILOT_ROUTER_MODEL`). `--no-router` отключает роутинг на один запуск. В JSON-отчёте появляется `meta.router` с моделью, решением и длительностью.
155
+
156
+ ### Cache-friendly промпты
157
+
158
+ oc-pilot собирает каждый промпт так, чтобы стабильные части шли первыми, а изменчивый `GIT_DIFF` — последним: инструкция, тип проекта, рецепт, флаги репозитория, контекст и отчёт сканера секретов одинаковы между слайсами, раундами fix и повторными ревью одного изменения. Провайдеры с префикс-кэшированием (OpenAI, DeepSeek, Anthropic, OpenRouter) переиспользуют стабильный префикс автоматически — второй и последующие вызовы на том же контексте дешевле и быстрее. Настройка не требуется.
159
+
160
+ ### Кеш ответов (`openai`)
161
+
162
+ Движок `openai` кеширует полные ответы модели на диске. Ключ кеша — sha256 от модели, base URL, системного промпта и входа, поэтому повторный запуск той же команды на том же diff (типично при настройке хуков, CI и скриптов) не тратит ни одного токена и возвращается мгновенно. Записи лежат в `.git/oc-pilot/cache/` — внутри метаданных репозитория, они не попадают в рабочее дерево и в коммиты.
163
+
164
+ TTL по умолчанию 24 часа (`cacheTtlSeconds`, или `OC_PILOT_CACHE_TTL`; `0` отключает кеш). `--no-cache` обходит кеш на один запуск, `oc-pilot cache --stats | --prune | --clear` показывает и обслуживает его, `doctor --fix` вычищает просроченные записи. В JSON-отчёте видно `meta.cache: "hit" | "miss"`. Кеш работает только для движка `openai` (триаж, основной вызов и слайсы); запуски через OpenCode не кешируются, а ошибка кеша никогда не ломает ревью.
165
+
166
+ ### Second opinion (`openai`)
167
+
168
+ `review --second-opinion` перед финальным вердиктом прогоняет до 10 критичных находок через вторую, скептическую модель. Ответ — одна строка: `VERDICT: CONFIRM` подтверждает находку, `VERDICT: REJECT — <причина>` понижает её до style и помечает буллет `[second opinion: rejected — причина]`. Если верификатор недоступен или ошибся, находки остаются как есть — ошибка проверки никогда не ослабляет ревью. Верификатор настраивается флагами `--second-opinion-model` / `--second-opinion-base-url` / `--second-opinion-api-key-env` или ключами конфига `secondOpinionEnabled`, `secondOpinionModel`, `secondOpinionBaseUrl`, `secondOpinionApiKeyEnv`; итог — в `meta.secondOpinion`.
169
+
170
+ ### Лимиты и статистика
171
+
172
+ Каждый запуск и вызов API записывается в `.git/oc-pilot/stats.jsonl` (находки, движок, код возврата, попадания кеша). `oc-pilot stats` выводит запуски, вызовы API, попадания кеша и находки за сегодня, неделю и всё время (`--clear` сбрасывает). Дневной бюджет вызовов задаётся `maxDailyApiCalls` или `OC_PILOT_MAX_DAILY_API_CALLS` (`0` — без лимита); при исчерпании команда выходит с кодом 1 — попадания кеша лимит не расходуют. `oc-pilot day --since "1 day ago"` — сводка того, что натворил агент: коммиты, churn по файлам, строки +/- и находки oc-pilot.
173
+
174
+ Рядом с бюджетом вызовов есть бюджет денег: `--max-cost <usd>` (или `maxCostUsd`, `OC_PILOT_MAX_COST`; `0` — без лимита) ограничивает дневные расходы на вызовы `openai`. Стоимость считается по `usage` из ответа модели и встроенной таблице цен (gpt-4.1 с вариантами mini/nano, gpt-4o, o4-mini, o3-mini), копится в `stats.jsonl` и суммируется за сегодня; при превышении команда выходит с кодом 1. Это страховка от зацикленного агента, а не бухгалтерия: для моделей вне таблицы стоимость считается нулевой, попадания в кеш бесплатны.
175
+
176
+ ### Правила агента
177
+
178
+ Если в проекте есть `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.cursorrules` или `.github/copilot-instructions.md`, oc-pilot включает его в каждый промпт (первый найденный, до 10 000 символов, секреты маскируются) — ревьюер знает те же договорённости, что и кодинг-агент. Отключается `agentRules: false` в конфиге или `OC_PILOT_AGENT_RULES=0`.
179
+
111
180
  ## Команды
112
181
 
113
182
  ### `review`
@@ -127,6 +196,7 @@ oc-pilot review [пути...] [опции]
127
196
  | `--context <text\|@file>` | дополнительный контекст |
128
197
  | `--lang <en\|ru>` | язык системного промпта и ответа (по умолчанию `en`) |
129
198
  | `--engine <opencode\|openai>` | движок модели (по умолчанию `opencode`) |
199
+ | `--engine-preset <p>` | пресет API: `ollama`, `lmstudio`, `openrouter` |
130
200
  | `--base-url <url>` | OpenAI-совместимый endpoint |
131
201
  | `--api-key-env <name>` | переменная с API-ключом (по умолчанию `OC_PILOT_API_KEY`) |
132
202
  | `--no-repo-context` | не давать агенту читать файлы (только diff) |
@@ -134,6 +204,53 @@ oc-pilot review [пути...] [опции]
134
204
  | `--fail-on <level>` | exit 3 при замечаниях `critical`, `warning` или `style` |
135
205
  | `--fail-on-secrets` | exit 3 при critical-секретах |
136
206
  | `--no-secret-scan` | не искать секреты и не редактировать diff |
207
+ | `--router` | двухфазный роутинг: дешёвый триаж перед ревью (`openai`) |
208
+ | `--no-router` | отключить роутинг, включённый в конфиге |
209
+ | `--router-model <m>` | модель триажа (по умолчанию `routerModel` из конфига) |
210
+ | `--baseline` | скрыть находки из `.oc-pilot/baseline.json` |
211
+ | `--update-baseline` | перезаписать baseline текущими находками и выйти |
212
+ | `--pr` | отправить inline-комментарии к строкам PR (Actions REST или `gh`) |
213
+ | `--no-pr-inline` | отправить один сводный комментарий вместо inline |
214
+ | `--pr-status` | выставить блокирующий commit status (`failure` при critical) |
215
+ | `--mr` | отправить review в merge request GitLab (`CI_MERGE_REQUEST_IID`) |
216
+ | `--no-mr-inline` | только сводная заметка в MR, без inline-обсуждений |
217
+ | `--mr-status` | выставить статус `oc-pilot` в GitLab (`GITLAB_TOKEN`) |
218
+ | `--second-opinion` | проверить критичные находки второй моделью (`openai`) |
219
+ | `--second-opinion-model <m>` | модель-верификатор (по умолчанию `secondOpinionModel` или основная) |
220
+ | `--require-tests` | код 3, если логика изменена без тестов |
221
+ | `--no-test-weakening` | код 3, если тесты ослаблены (skip, удалённые проверки) |
222
+ | `--interactive` | по каждой находке спросить, не скрыть ли её в baseline (TTY) |
223
+
224
+ С `--baseline` находки, уже записанные в `.oc-pilot/baseline.json`, скрываются из вывода и не влияют на код возврата, JSON, SARIF и PR-комментарий — блокируют только новые. Отпечаток находки — `severity | файл | нормализованный текст`, без номера строки, поэтому известные находки переживают сдвиги кода. `--update-baseline` перезаписывает файл по текущему ревью и выходит с кодом 0; `--interactive` прячет находки по одной и дописывает их в baseline. `--pr` отправляет ревью в текущий PR: внутри GitHub Actions — через review API с `GITHUB_TOKEN`, до 25 находок прикрепляются inline-комментариями к своим строкам диффа (нужна permission `pull-requests: write`); находки вне изменённых строк и любой запуск вне Actions откатываются на один сводный комментарий (локально — через `gh pr comment`, нужен установленный и авторизованный `gh`). `--no-pr-inline` принудительно оставляет только сводный комментарий. `--pr-status` выставляет commit status в контексте `oc-pilot` — `failure`, пока остаются critical-находки, иначе `success` — чтобы правило защиты ветки могло его требовать (нужна `statuses: write`). Работает и в текстовом, и в SARIF-режиме.
225
+
226
+ В GitLab CI `--mr` отправляет ревью в merge request: до 25 находок становятся inline-обсуждениями, привязанными к своим строкам диффа, а сводка всегда уходит заметкой. `CI_MERGE_REQUEST_IID`, `CI_PROJECT_ID` и `CI_API_V4_URL` указывают на MR, а `GITLAB_TOKEN` должен иметь scope `api` (`CI_JOB_TOKEN` не умеет писать заметки). Для позиции обсуждения нужны `base_sha`/`start_sha`/`head_sha`: они берутся из `CI_MERGE_REQUEST_DIFF_BASE_SHA`, `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` и `CI_COMMIT_SHA`, а если их нет — запрашиваются у merge request как `diff_refs`. `--no-mr-inline` оставляет только сводную заметку. Добавьте `--mr-status`, чтобы выставить и commit status `oc-pilot`. Любая часть при отсутствии контекста пайплайна, токена или отдельной позиции деградирует до предупреждения, поэтому ревью никогда не падает из-за неготовой интеграции.
227
+
228
+ Минимальная задача выглядит так:
229
+
230
+ ```yaml
231
+ oc-pilot:
232
+ image: node:22
233
+ rules:
234
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
235
+ script:
236
+ - npm i -g oc-pilot
237
+ - oc-pilot review --base "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --fail-on critical --mr --mr-status
238
+ variables:
239
+ OC_PILOT_API_KEY: $OC_PILOT_API_KEY
240
+ GITLAB_TOKEN: $GITLAB_TOKEN
241
+ ```
242
+
243
+ До вызова модели `review` сам осматривает diff: новые зависимости проверяются на тайпосквоты, незакреплённые версии и VCS/URL-спеки в манифестах npm, PyPI, Go, Cargo, RubyGems, Packagist, Maven/Gradle и NuGet (подсказка `DEPENDENCY_CHANGES`, `meta.dependencies`); крупное изменение логики (20+ добавленных строк кода) без тестов даёт `TEST_COVERAGE_HINT` (`--require-tests` превращает в код 3, `meta.testDelta`); ослабленные тесты дают `TEST_WEAKENING` (пропущенные и сфокусированные тесты, удалённые проверки без замены, закомментированные ассерты, поднятые таймауты; `--no-test-weakening` превращает в код 3, `meta.testWeakening`); добавленные строки с признаками prompt injection (переопределение инструкций, role-hijack, эксфильтрация промпта, base64-блобы, невидимый Unicode) дают предупреждение `PROMPT_INJECTION_RISKS` (`meta.injection`).
244
+
245
+ ### Подавление находок в коде
246
+
247
+ Осознанный компромисс не должен возвращаться замечанием в каждом ревью. Пометьте его в самом коде:
248
+
249
+ ```go
250
+ func pay() {} // oc-pilot:ignore: nil невозможен для старого кошелька
251
+ ```
252
+
253
+ Маркер подавляет находку, чья цель — эта строка или строка сразу под ним, поэтому он работает и отдельным комментарием над кодом. `// oc-pilot:ignore-file: код сгенерирован protoc` в первых десяти строках файла отключает ревью для всего файла. Причина обязательна: голый `oc-pilot:ignore` не действует, находка остаётся, а прогон выдаёт предупреждение. Подавленные находки исчезают из текста, JSON, SARIF и комментариев PR или MR и не влияют на код возврата, но `meta.suppressed` перечисляет каждую с файлом, строкой и причиной. `oc-pilot:ignore-secret` относится к сканеру секретов и никогда не скрывает находку ревью.
137
254
 
138
255
  ### `test-fix`
139
256
 
@@ -148,6 +265,27 @@ oc-pilot test-fix --log - --exit-code 1
148
265
 
149
266
  `test-fix` прикладывает diff (если это git-репозиторий), выдержки из файлов, найденных в стеке, и последние строки вывода. Успешный прогон не анализируется, если не передан `--force`.
150
267
 
268
+ ### `test-gen`
269
+
270
+ Превращает diff в тесты, которые действительно запускаются. Модель пишет тесты на поведение, изменённое в диффе, патч применяется, `testCommand` выполняется, и остаётся только зелёный результат: неудачная попытка откатывается, а лог падения уходит обратно в модель как обратная связь.
271
+
272
+ ```bash
273
+ oc-pilot test-gen --staged --apply
274
+ oc-pilot test-gen --staged --coverage --apply
275
+ oc-pilot test-gen --from-slop --apply
276
+ oc-pilot test-gen src/billing.ts --apply --rounds 1
277
+ oc-pilot test-gen --base main --json
278
+ oc-pilot test-gen --diff changes.diff
279
+ ```
280
+
281
+ Без `--apply` команда только печатает патч. Патч может менять только тестовые файлы (`*.test.ts`, `*.spec.ts`, `*_test.go`, `test_*.py` или пути внутри `test/`); производственный файл в патче отклоняет весь раунд. Существующие тесты защищены, пока не передан `--force`, поэтому сгенерированные тесты не перезаписывают написанные вручную. `--no-run` применяет патч без запуска набора, `--keep-failing` оставляет красный тест для отладки, а `--rounds <n>` (по умолчанию 2) задаёт, сколько раз падение отправляется модели.
282
+
283
+ `--coverage` сужает запрос до изменённых строк, которые ещё не выполнил ни один тест. Команда читает отчёт lcov, Istanbul JSON, Cobertura XML или Go cover profile (`--coverage-file <path>` переопределяет автоопределение `coverage/lcov.info`, `coverage/coverage-final.json`, `cobertura.xml`, `coverage.out` и похожих файлов), пересекает его со строками, добавленными в диффе, и отправляет модели только эти пробелы. Если все изменённые строки уже покрыты, команда выходит с кодом 0, не вызывая модель.
284
+
285
+ `--from-slop` игнорирует diff и позволяет скану slop выбрать работу: команда ищет исходники, у которых нет тестов, и ранжирует их по churn, дублированным блокам и нерешённым TODO. `--slop-files <n>` (по умолчанию 3) ограничивает число файлов. Смешивать `--from-slop` с `--diff`, `--staged`, `--base`, `--coverage` или явными путями нельзя: они уже задают вход. Если тест есть у каждого исходника, команда выходит с кодом 0, не вызывая модель.
286
+
287
+ JSON-результат — `{applied, patch, files, status, tests, rounds, analysis, meta, coverage, targets}`, где `status` равен `pass`, `fail` или `not-run`, `coverage` содержит `{report, format, uncoveredLines, gaps, missing}` (или `null` без `--coverage`), а `targets` перечисляет выбранные сканом файлы с оценками и причинами (или `null` без `--from-slop`); код возврата 1, пока тесты остаются красными.
288
+
151
289
  ### `fix`
152
290
 
153
291
  Просит модель вернуть unified diff, проверяет его через `git apply --check` и с `--apply` применяет в рабочем дереве. Это единственная команда, которая меняет файлы.
@@ -156,6 +294,8 @@ oc-pilot test-fix --log - --exit-code 1
156
294
  oc-pilot fix --diff changes.diff # только показать патч
157
295
  oc-pilot fix --apply --command "npm test" # применить и проверить
158
296
  oc-pilot fix --apply --command "go test ./..." --keep-on-test-failure
297
+ oc-pilot fix --from-sast --staged --apply # починить SAST-находки
298
+ oc-pilot fix --from-authz --staged --apply # починить находки авторизации
159
299
  oc-pilot review --github # аннотации GitHub Actions
160
300
  ```
161
301
 
@@ -165,9 +305,18 @@ oc-pilot review --github # аннотации GitHub Act
165
305
  | `--command <cmd>` | тесты после применения; иначе `testCommand` или автоопределение |
166
306
  | `--no-tests` | применить без запуска тестов |
167
307
  | `--keep-on-test-failure` | не откатывать патч при падении тестов |
308
+ | `--no-snapshot` | не создавать снимок перед применением |
309
+ | `--from-sast` | исправить high-находки SAST в изменённых файлах и пересканировать |
310
+ | `--from-authz` | исправить high-находки авторизации маршрутов и пересканировать |
168
311
 
169
312
  `fix` не делает commit и push. При падении тестов патч откатывается, если не указан `--keep-on-test-failure`. Чужие незакоммиченные изменения не откатываются.
170
313
 
314
+ Перед применением `fix` сохраняет снимок рабочего дерева в `.git/oc-pilot/snapshots/` (tracked-изменения бинарным патчем + копии untracked-файлов). Снимки локальны: они не попадают в коммиты. Откат — `oc-pilot restore`; отключить снимок — `--no-snapshot`.
315
+
316
+ С `--from-sast` команда сканирует изменённые файлы встроенными правилами SAST, просит модель о патче, применяет его и пересканирует. В JSON добавляется `sast: {before, after, remaining}`; код 1, если high-находки остались.
317
+
318
+ С `--from-authz` тот же цикл работает с находками авторизации маршрутов (маршрут без сессии, IDOR, админка без роли), а в JSON добавляется `authz: {before, after, remaining}`; `--from-sast` и `--from-authz` несовместимы.
319
+
171
320
  ### `docgen`
172
321
 
173
322
  ```bash
@@ -210,10 +359,343 @@ oc-pilot custom "Объясни архитектуру" --context @ARCHITECTURE.
210
359
  ```bash
211
360
  oc-pilot scan
212
361
  oc-pilot scan --staged --strict
362
+ oc-pilot scan --all
213
363
  git diff main...HEAD | oc-pilot scan --stdin --json
364
+
365
+ # SARIF 2.1.0 для GitHub Code Scanning
366
+ oc-pilot scan --staged --format sarif -o oc-pilot.sarif
214
367
  ```
215
368
 
216
- Код возврата `1` при critical-находках (или при любых с `--strict`), `0` — чисто, `--no-fail` — всегда `0`.
369
+ Код возврата `1` при critical-находках (или при любых с `--strict`), `0` — чисто, `--no-fail` — всегда `0`. `--format sarif` пишет отчёт SARIF 2.1.0 (правила `oc-pilot/secret`, `oc-pilot/critical`, `oc-pilot/warning`), который загружается в GitHub Code Scanning; превью секретов остаются замаскированными.
370
+
371
+ `--all` сканирует всё дерево, а не diff: учитываются `.gitignore` и `.oc-pilot/ignore`, пропускаются бинарники, `node_modules`, `dist` и файлы больше 512 КБ, в отчёте есть число проверенных файлов (`meta.filesScanned`).
372
+
373
+ ### `preflight`
374
+
375
+ Один офлайн-вердикт перед коммитом. Шесть проверок идут без модели и без сети: секреты в диффе, детерминированный SAST по изменённым исходникам (инъекции команд и SQL, path traversal, SSRF, выполнение кода, XSS и другое), авторизация маршрутов по изменённым исходникам (маршрут без сессии, IDOR, админский путь без роли), здоровье зависимостей в границах изменённых файлов, ослабление тестов (`it.skip`, удалённые проверки, поднятые таймауты) и дельта Slop Index относительно базовой ссылки.
376
+
377
+ ```bash
378
+ oc-pilot preflight
379
+ oc-pilot preflight --staged
380
+ oc-pilot preflight --base main --max-delta 0
381
+ oc-pilot preflight --no-slop --fail-on-issue medium
382
+ oc-pilot preflight --staged --no-sast
383
+ ```
384
+
385
+ Проблемы зависимостей ограничены скоупом: preflight сообщает только о файлах, которые меняет дифф, и о пакетах, названных в добавленных строках, поэтому старый репозиторий не падает на первом же запуске. Находки, записанные в `.oc-pilot/baseline.json`, по умолчанию скрываются, поэтому гейт сообщает только о новых проблемах; `receipt` использует тот же baseline. `--fail-on-issue` (по умолчанию `high`) задаёт порог и для находок SAST, и для авторизации маршрутов, и для severity зависимостей, а `--max-delta` (по умолчанию 10 пунктов) — порог Slop Index; каждую проверку можно отключить через `--no-secret-scan`, `--no-sast`, `--no-authz`, `--no-deps`, `--no-tests` или `--no-slop`. Код возврата 1, если хоть одна проверка упала, иначе 0 — один шаг CI заменяет шесть.
386
+
387
+ JSON-отчёт — `{status, checks, diff}`, где каждая проверка содержит `{id, label, status, summary, details}`, а `status` равен `pass`, `fail` или `skip`.
388
+
389
+ ### `receipt`
390
+
391
+ Превращает «у меня работает» в проверяемое утверждение. Квитанция прогоняет тесты и preflight (включая SAST и authz), а затем записывает результат вместе с SHA коммита, веткой, состоянием рабочего дерева, статистикой диффа и точными командами. Файл пишется в `.git/oc-pilot/receipt.json`, поэтому никогда не попадает в рабочее дерево. `--no-sast` или `--no-authz` пропускает проверку для изменения, где она неприменима.
392
+
393
+ ```bash
394
+ oc-pilot receipt --staged
395
+ oc-pilot receipt --staged --no-sast
396
+ oc-pilot receipt --json
397
+ oc-pilot receipt --verify
398
+ oc-pilot receipt --verify --receipt path/to/receipt.json
399
+ oc-pilot receipt --keygen receipt.key
400
+ oc-pilot receipt --sign --key receipt.key
401
+ oc-pilot receipt --verify --public-key receipt.key.pub
402
+ ```
403
+
404
+ Файл запечатан SHA-256 хешем тела. `--verify` пересчитывает хеш и сравнивает коммит с текущим `HEAD`, поэтому изменённый файл или квитанция от старого коммита считаются недействительными: `{path, ok, hashOk, stale, commit, head, signature, reason?}`. Код возврата 1, если тесты упали, preflight не прошёл или квитанция не проверяется.
405
+
406
+ Хеш доказывает целостность, но не авторство. `--sign` подписывает хеш Ed25519-ключом: `--keygen <file>` создаёт приватный ключ (права 0600) и `<file>.pub`; `--key` или `OC_PILOT_RECEIPT_KEY` указывает на приватный ключ; в квитанции появляется поле `signature`. Проверка сверяет подпись, если доступен публичный ключ: `--public-key <file>`, `OC_PILOT_RECEIPT_PUBLIC_KEY` или закоммиченный `.oc-pilot/receipt.pub`. Статус подписи — `valid`, `invalid`, `missing` или `unchecked`; неподписанная квитанция не проходит проверку, когда ключ передан. `ready` тоже проверяет подпись, если существует `.oc-pilot/receipt.pub`. Приватный ключ храните вне репозитория.
407
+
408
+ Квитанция содержит `{version, tool, toolVersion, createdAt, commit, branch, dirty, diff, files, tests, preflight, hash, signature?}`. `tests` — `{command, exitCode, timedOut, durationMs, passed, outputTail}` или `null` при `--no-run`; `preflight` — тот же отчёт, что печатает `preflight`. Вне репозитория квитанцию можно записать только в явный путь через `--out`.
409
+
410
+ ### `ready`
411
+
412
+ Оценивает готовность репозитория к работе с ИИ-агентом. Одно офлайн-число от 0 до 100 по девяти проверкам: тесты (15), lockfile (10), git-хуки (15), Slop Index (15), свежая квитанция (10), инструкции для агента (10), CI (5), конфиг (5) и безопасность (15). Каждая проверка даёт `pass`, `warn` или `fail` и приносит 100%, 50% или 0% своего веса. Проверка безопасности прогоняет детерминированные правила SAST и авторизации маршрутов по репозиторию и учитывает `.oc-pilot/baseline.json`. Модель не вызывается, сеть не используется, но нужен git-репозиторий.
413
+
414
+ ```bash
415
+ oc-pilot ready
416
+ oc-pilot ready --json
417
+ oc-pilot ready --badge
418
+ oc-pilot ready --fail-under 85
419
+ oc-pilot ready --fix
420
+ oc-pilot ready --fix --dry-run
421
+ oc-pilot ready --fix --receipt
422
+ ```
423
+
424
+ Оценка переводится в грейд: 85 и выше — `agent-ready`, 65 и выше — `almost`, 40 и выше — `risky`, ниже — `not-ready`. `--badge` печатает shields.io-бейдж в markdown для README, а `--fail-under <n>` возвращает код 1 ниже порога, поэтому оценкой можно гейтить pull request.
425
+
426
+ `--fix` применяет только безопасные офлайн-исправления: ставит хук `pre-commit`, если хука нет, пишет `.oc-pilot.json` с найденной тестовой командой и создаёт `AGENTS.md` с командами проекта. Чужой хук, существующий конфиг или готовые инструкции для агента не перезаписываются — они попадают в список пропущенных вместе с проверками, которые требуют человека: квитанция, lockfile и Slop Index. `--dry-run` печатает план, не трогая дерево, а после исправлений оценка пересчитывается.
427
+
428
+ `--receipt` превращает `--fix` в полный цикл: после исправлений команда прогоняет тесты, запускает preflight и сохраняет квитанцию для `HEAD`, поэтому проверка квитанции проходит в том же запуске. Флаг работает только вместе с `--fix`; без тестовой команды квитанция попадает в пропущенные. Упавшие тесты или проваленный preflight всё равно создают квитанцию — отчёт скажет, что именно не прошло.
429
+
430
+ JSON-результат — `{score, grade, checks, commit}`; каждая проверка — `{id, label, status, points, max, detail}`, где `detail` называет файл, который принёс или потерял очки, и команду, которая это исправляет. С `--fix` в payload добавляется `fix: {applied, dryRun, fixes, skipped, receipt}`, где `receipt` — `{path, testsPassed, preflight}` или отсутствует.
431
+
432
+ ### `mutate`
433
+
434
+ Мутационное тестирование отвечает на вопрос сложнее покрытия: тесты действительно ловят баги? Команда переворачивает операторы сравнения и булевы операторы в изменённых исходниках, прогоняет набор тестов на каждой мутации и считает, сколько мутантов тесты убили. Выживший мутант — это строка, которую набор исполняет, но по-настоящему не проверяет.
435
+
436
+ ```bash
437
+ oc-pilot mutate --staged
438
+ oc-pilot mutate --base main --max-mutants 10
439
+ oc-pilot mutate src/billing.ts --min-score 80
440
+ oc-pilot mutate --diff changes.diff --json
441
+ ```
442
+
443
+ Операторы: `===`/`!==`, `==`/`!=`, `>=`/`<`, `<=`/`>`, `&&`/`||` и `true`/`false`; строки и комментарии маскируются, поэтому мутируется только реальный код. `--max-mutants <n>` ограничивает прогон (по умолчанию 20, максимум 500), потому что каждый мутант запускает весь набор. `--min-score <n>` возвращает код 1, если mutation score ниже порога, — это CI-гейт. Таймаут считается убийством: мутант изменил наблюдаемое поведение.
444
+
445
+ JSON: `{command, files, sites, mutants, killed, survived, timedOut, score, truncated, durationMs}`; каждый мутант — `{file, line, column, operator, original, replacement, status, durationMs}` со `status` равным `killed`, `survived` или `timeout`.
446
+
447
+ ### `flaky`
448
+
449
+ Запускает тестовую команду несколько раз и сравнивает результаты отдельных тестов. Тест, который прошёл в одном прогоне и упал в другом, помечается нестабильным; тест, падающий каждый раз, — просто сломанным. Модель не вызывается, команда работает только с выводом раннера.
450
+
451
+ ```bash
452
+ oc-pilot flaky
453
+ oc-pilot flaky --runs 5
454
+ oc-pilot flaky --shuffle --command "node --test {files}"
455
+ oc-pilot flaky --command "go test ./..." --json
456
+ oc-pilot flaky --fail-on-flaky
457
+ ```
458
+
459
+ `--runs <n>` задаёт число прогонов (по умолчанию 3, максимум 10). `--command` переопределяет `testCommand` и автоопределение. `--fail-on-flaky` возвращает код 1, если найден хотя бы один нестабильный тест, — это готовый CI-гейт.
460
+
461
+ `--shuffle` превращает прогон в проверку порядка. Команда должна содержать `{files}`: `oc-pilot flaky --shuffle --command "node --test {files}"`. Тестовые файлы собираются из репозитория, перемешиваются seeded-генератором и подставляются в команду; каждый прогон получает новый seed от базового, поэтому тест, падающий только после определённого соседа, проявляется как нестабильный. `--seed <value>` фиксирует базовый seed, когда нужно воспроизвести падение.
462
+
463
+ Распознаются Node spec (`✔`/`✖`), TAP (`ok`/`not ok`), Go (`--- PASS`/`--- FAIL`), pytest (`PASSED`/`FAILED`) и Jest/Vitest (`✓`/`✕`). Если маркеров нет, `parsed` равен `false`, и команда честно сравнивает только коды возврата.
464
+
465
+ JSON: `{command, runs, completed, parsed, tests, flaky, failing, shuffle}`, где каждый тест — `{name, passes, failures, status}` со `status` равным `flaky`, `failing` или `passing`. С `--shuffle` поле `shuffle` равно `{seed, files}`.
466
+
467
+ ### `authz`
468
+
469
+ Проверка авторизации HTTP-маршрутов: маршрут без проверки сессии, объект, который достаётся по id из запроса без проверки владельца (IDOR), и админский путь без роли. Команда читает изменённые исходники и не вызывает модель.
470
+
471
+ ```bash
472
+ oc-pilot authz --staged
473
+ oc-pilot authz --public /health,/login
474
+ oc-pilot authz --staged --fail-on-issue medium
475
+ oc-pilot authz --staged --format sarif -o authz.sarif
476
+ ```
477
+
478
+ Распознаются маршруты Express, Fastify и Koa (`app.get`, `router.post`, ...), а также Next.js `app/**/route.ts` и `pages/api/**`. Handler по ссылке (`router.get("/x", controller.list)`) пропускается: проверка может жить в контроллере. Пути `/health`, `/login`, `/signup`, `/public`, `/webhooks`, `/oauth` и подобные считаются публичными; `--public <prefixes>` расширяет список.
479
+
480
+ Осознанное исключение подавляется на строке маршрута или строкой выше:
481
+
482
+ ```js
483
+ // oc-pilot:authz-ignore idor: шлюз ограничивает запрос тенантом
484
+ router.get("/users/:id", handler);
485
+ ```
486
+
487
+ Подавление без причины игнорируется. `--ignore <rules>` отключает целые правила, `--no-suppressions` отключает inline-подавления.
488
+
489
+ `--fail-on-issue <high|medium>` задаёт порог для кода возврата (по умолчанию `high`). `--format sarif` выдаёт SARIF 2.1.0 с правилом, методом и маршрутом.
490
+
491
+ `--baseline <file>` скрывает находки, уже записанные в `.oc-pilot/baseline.json`, поэтому падают только новые; `--update-baseline` записывает текущие находки в файл и выходит с кодом 0 — так легаси-репозиторий может включить гейт, не исправляя всё сразу. Baseline хранит SHA-256-отпечатки правила, файла и фрагмента (или метода и маршрута для `authz`), поэтому записи переживают сдвиги строк. `preflight` и `receipt` читают тот же baseline по умолчанию.
492
+
493
+ JSON: `{files, routes, findings, suppressed, summary}`; каждый маршрут — `{file, line, method, route, public}`, находка добавляет `{rule, severity, method, route}`. С `--baseline` в payload добавляется `baselineSuppressed`, с `--update-baseline` — `baseline: {path, updated, entries}`.
494
+
495
+ ### `sast`
496
+
497
+ Детерминированный статический анализ изменённых файлов: инъекции команд и SQL, path traversal, SSRF, выполнение кода, XSS, открытые редиректы, отключённая проверка TLS, wildcard CORS, prototype pollution, слабые хеши и JWT `none`. Модель не вызывается, сеть не используется: один и тот же дифф всегда даёт одни и те же находки.
498
+
499
+ ```bash
500
+ oc-pilot sast --staged
501
+ oc-pilot sast --base main --fail-on-issue medium
502
+ oc-pilot sast src/server.ts --json
503
+ oc-pilot sast --staged --format sarif -o sast.sarif
504
+ ```
505
+
506
+ Анализ учитывает источники данных, но остаётся эвристическим: сток (sink) помечается, когда данные запроса (`req.query`, `req.body`, `req.params`, заголовки, cookies, `userInput`, `untrusted*`) или подстановка шаблона доходят до него в том же выражении. Константы и параметризованные запросы не помечаются. `path.resolve`, `path.normalize`, `path.basename` и `path.join` снимают находку path traversal.
507
+
508
+ Осознанное исключение подавляется на строке находки или строкой выше:
509
+
510
+ ```js
511
+ exec(req.query.cmd); // oc-pilot:sast-ignore command-injection: admin-only endpoint
512
+ ```
513
+
514
+ Подавление без причины игнорируется. `--ignore <rules>` отключает целые правила, `--no-suppressions` отключает inline-подавления для аудита.
515
+
516
+ `--fail-on-issue <high|medium|low>` задаёт порог для кода возврата (по умолчанию `high`). `--format sarif` выдаёт SARIF 2.1.0 для GitHub code scanning и других потребителей.
517
+
518
+ `--baseline <file>` скрывает находки, уже записанные в `.oc-pilot/baseline.json`, поэтому падают только новые; `--update-baseline` записывает текущие находки в файл и выходит с кодом 0 — так легаси-репозиторий может включить гейт, не исправляя всё сразу. Baseline хранит SHA-256-отпечатки правила, файла и фрагмента, поэтому записи переживают сдвиги строк. `preflight` и `receipt` читают тот же baseline по умолчанию.
519
+
520
+ JSON: `{files, findings, suppressed, summary}`, каждая находка — `{rule, severity, file, line, column, message, snippet}`, `summary` считает `high`, `medium`, `low`. С `--baseline` в payload добавляется `baselineSuppressed`, с `--update-baseline` — `baseline: {path, updated, entries}`.
521
+
522
+ ### `deps`
523
+
524
+ Офлайн-аудит здоровья npm-, pnpm- и yarn-зависимостей. Модель не вызывается, сеть не используется.
525
+
526
+ ```bash
527
+ oc-pilot deps
528
+ oc-pilot deps --json
529
+ oc-pilot deps --fail-on-issue high
530
+ oc-pilot deps --ignore lint-staged
531
+ oc-pilot deps --fix --dry-run
532
+ oc-pilot deps --fix
533
+ oc-pilot deps --why qs
534
+ oc-pilot deps --audit --fail-on-vuln high
535
+ oc-pilot deps --audit --offline
536
+ oc-pilot deps --sbom sbom.json
537
+ ```
538
+
539
+ Команда сравнивает `package.json` с тем, что код реально импортирует, и с лок-файлом проекта: `package-lock.json`, `pnpm-lock.yaml` или `yarn.lock`:
540
+
541
+ - **phantom** (high) — пакет импортируется, но не объявлен, поэтому чистая установка или CI упадёт;
542
+ - **unused** (medium) — объявлен, но нигде не импортируется и не упоминается в скриптах;
543
+ - **misplaced** (low) — используется только тестами, но лежит в `dependencies`;
544
+ - **duplicate** (low) — две библиотеки из одной группы решают одну задачу (`moment` и `dayjs`);
545
+ - **unpinned** (medium) — `*`, `latest` или пустая версия;
546
+ - **vcs** (high для git/URL, low для `file:`) — зависимость из git, URL или локального пути;
547
+ - **lockfile** (high) — объявлен, но отсутствует в лок-файле проекта, поэтому чистая установка упадёт (`npm ci`, `pnpm install --frozen-lockfile` или `yarn install --immutable`).
548
+
549
+ `--fail-on-issue <high|medium|low>` превращает аудит в CI-гейт (код 1). `--ignore <names>` принимает список через запятую для ложных срабатываний, например когда пакет загружается динамически. Workspace-пакеты (`packages/*`) и `@types/*` учитываются, peer-зависимости не считаются неиспользуемыми.
550
+
551
+ `--fix` исправляет то, что можно решить офлайн: пакет, используемый только тестами, переезжает в `devDependencies`; импортируемый, но не объявленный пакет добавляется с версией, уже разрешённой в лок-файле (в `devDependencies`, если все импортёры — тесты); плавающая версия `*`/`latest` прибивается к версии из lockfile. Ничего не выдумывается: фантомный импорт без записи в lockfile, неиспользуемый пакет, дубликат и vcs-зависимость попадают в `skipped` с причиной. `--dry-run` печатает план, не трогая `package.json`. После записи аудит запускается заново, поэтому код возврата отражает уже исправленное состояние.
552
+
553
+ `--why <name>` отвечает на вопрос, который возникает до любой чистки: откуда этот пакет вообще взялся. Команда локально читает `package.json` и лок-файл проекта и показывает поле и спецификацию объявления, файлы с прямым импортом, пакеты, которые от него зависят, все установленные версии и число копий, а также цепочки зависимостей от корня. Если пакет не объявлен, не установлен и не импортируется, код возврата 1. `--why` не сочетается с `--fix`.
554
+
555
+ `--audit` добавляет известные уязвимости и лицензии. Команда спрашивает OSV (`api.osv.dev`) по каждому пакету из lockfile, показывает CVE/GHSA, severity и первую исправленную версию, а ответы кеширует в `.oc-pilot/osv-cache.json` на 24 часа. `--offline` использует только кеш, не ходит в сеть и падает, если кеш пуст. `--osv-url` направляет запрос на зеркало. `--fail-on-vuln <critical|high|medium|low>` превращает результат в security-гейт: код 1, если хотя бы одна уязвимость достигает порога. Лицензии читаются из установленных манифестов в `node_modules`; strong copyleft, proprietary и unknown попадают в отчёт, а пакеты без установленного манифеста считаются `missing`, а не угадываются.
556
+
557
+ `--sbom <file>` записывает CycloneDX 1.5 SBOM по каждому пакету из lockfile, с npm purl, относительно корня проекта. Сеть не нужна.
558
+
559
+ JSON-результат — `{packageName, declared, imported, scannedFiles, truncated, lockfile, issues}`; с `--fix` добавляется `fix: {applied, dryRun, fixes, skipped}`, с `--why` команда печатает один объект `DependencyWhy`: `{name, versions, copies, declared, importedBy, dependents, chains}`, с `--audit` добавляется `audit: {checked, unchecked, vulnerabilities, online, stale, cachePath, licenses}`, а с `--sbom` — `sbom: <path>`.
560
+
561
+ ### `commit`
562
+
563
+ Генерирует commit-сообщение в формате Conventional Commits по staged-изменениям и опционально коммитит. Модель видит последние 10 commit-сообщений проекта и подстраивается под их стиль.
564
+
565
+ ```bash
566
+ oc-pilot commit # вывести сообщение
567
+ oc-pilot commit --apply # закоммитить staged с готовым сообщением
568
+ oc-pilot commit --json # машиночитаемый вывод
569
+ ```
570
+
571
+ `--apply` работает только со staged и блокируется (код `3`) при critical-секретах в diff; `--allow-secrets` снимает блокировку. С `--engine openai` большой diff разбивается на слайсы (см. «Движки»), сообщение покрывает все файлы.
572
+
573
+ ### `install-hook`
574
+
575
+ Ставит нативные git-хуки без husky и зависимостей. Хук `pre-commit` запускает `oc-pilot preflight --staged`: секреты, SAST, авторизация маршрутов, здоровье зависимостей в границах изменения, ослабление тестов и дельта Slop Index. С `--pre-push` дополнительно ставится `pre-push` с `oc-pilot review --fail-on critical --fail-on-secrets`. Флаг `--scan` оставляет лёгкий pre-commit только с `oc-pilot scan --staged`.
576
+
577
+ ```bash
578
+ oc-pilot install-hook
579
+ oc-pilot install-hook --scan
580
+ oc-pilot install-hook --pre-push
581
+ oc-pilot install-hook --uninstall
582
+ ```
583
+
584
+ Хуки опциональны и обратимы. Чужой хук не перезаписывается без `--force`, а при замене сохраняется как `<hook>.oc-pilot.bak`. Каждый управляемый хук помечен маркером; хуки старых версий `oc-pilot doctor` показывает как устаревшие и обновляет через `oc-pilot doctor --fix`. Обход на одну команду — `OC_PILOT_SKIP=1`. Поддерживаются `core.hooksPath` и worktrees.
585
+
586
+ ### `restore`
587
+
588
+ Восстанавливает рабочее дерево из последнего снимка, сделанного перед `fix --apply`.
589
+
590
+ ```bash
591
+ oc-pilot restore # последний снимок
592
+ oc-pilot restore --list # список снимков
593
+ oc-pilot restore <id> # конкретный снимок
594
+ ```
595
+
596
+ Снимки хранятся в `.git/oc-pilot/snapshots/` и не попадают в коммиты. Восстановление отказывается работать, если HEAD ушёл вперёд после снимка, чтобы не потерять закоммиченную работу. Разделение staged/unstaged не восстанавливается; untracked-файлы, созданные после снимка, не удаляются.
597
+
598
+ ### `cache`
599
+
600
+ Показывает и обслуживает кеш ответов движка `openai` в `.git/oc-pilot/cache/`.
601
+
602
+ ```bash
603
+ oc-pilot cache # записи, размер, просрочено
604
+ oc-pilot cache --prune # удалить просроченные записи
605
+ oc-pilot cache --clear # удалить всё
606
+ ```
607
+
608
+ Кеш работает только внутри git-репозитория и только для движка `openai`.
609
+
610
+ ### `stats`
611
+
612
+ Статистика использования из `.git/oc-pilot/stats.jsonl`: запуски, вызовы API, попадания кеша, средняя длительность вызова и находки (critical/warning/style) за сегодня, 7 дней и всё время.
613
+
614
+ ```bash
615
+ oc-pilot stats
616
+ oc-pilot stats --json
617
+ oc-pilot stats --clear
618
+ ```
619
+
620
+ ### `day`
621
+
622
+ Локальный дайджест активности: что закоммичено с заданного момента, какие файлы больше всего менялись, строки +/- и находки oc-pilot за период.
623
+
624
+ ```bash
625
+ oc-pilot day
626
+ oc-pilot day --since "3 days ago" --json
627
+ ```
628
+
629
+ ### `impact`
630
+
631
+ Показывает, где ещё используются изменённые символы. Из diff извлекаются объявления функций, методов, классов, типов и интерфейсов — и из добавленных, и из удалённых строк, поэтому переименование видно под обоими именами, — затем по ним ищутся вхождения в tracked и untracked файлах. Это текстовый поиск, а не AST, поэтому возможны лишние совпадения; команда никогда не валит сборку.
632
+
633
+ ```bash
634
+ oc-pilot impact
635
+ oc-pilot impact --staged --json
636
+ ```
637
+
638
+ `--json` отдаёт `symbols`, `references`, `scannedFiles` и `touchedFiles` — ровно то, что нужно агенту, чтобы понять, что ещё может сломаться от изменения.
639
+
640
+ ### `explain`
641
+
642
+ Объясняет находки прошлого ревью для одного места в коде. Каждый запуск `review` сохраняет замечания в `.git/oc-pilot/last-review.json`; `explain` находит замечание на указанной строке или ближайшее в пределах трёх строк и печатает его рядом с фрагментом текущего файла. Секреты в сниппете маскируются тем же сканером, что и везде.
643
+
644
+ ```bash
645
+ oc-pilot explain src/wallet.ts:42
646
+ oc-pilot explain src/wallet.ts:42 --json
647
+ ```
648
+
649
+ Без номера строки — или если совпадений нет — команда показывает все находки по этому файлу, так что она остаётся полезной, когда строки сдвинулись.
650
+
651
+ ### `reviewers`
652
+
653
+ Предлагает, кому отдать текущий diff на ревью. Для каждого изменённого файла команда смотрит последние коммиты, которые его трогали, считает авторов и выбирает лучших кандидатов; боты пропускаются. `CODEOWNERS` читается из `.github/CODEOWNERS`, `CODEOWNERS` или `docs/CODEOWNERS` и матчится по тем же правилам, что в GitHub и GitLab: побеждает последнее подходящее правило.
654
+
655
+ ```bash
656
+ oc-pilot reviewers --base main
657
+ oc-pilot reviewers --staged --limit 5 --exclude renovate
658
+ oc-pilot reviewers --base main --json -o reviewers.json
659
+ ```
660
+
661
+ `--depth` увеличивает глубину истории (по умолчанию 50 коммитов). `--json` отдаёт файлы, кандидатов (`name`, `email`, `commits`, `files`, `share`) и найденных `codeowners` — этого достаточно, чтобы подставить имена в `gh pr create --reviewer`.
662
+
663
+ ### `replay`
664
+
665
+ Повторно выводит последнее сохранённое ревью, не вызывая модель. Каждый `review` пишет `.git/oc-pilot/last-review.json`, поэтому SARIF-отчёт или комментарий для PR можно перегенерировать бесплатно — или отдать файл коллеге.
666
+
667
+ ```bash
668
+ oc-pilot replay
669
+ oc-pilot replay --format sarif -o report.sarif
670
+ oc-pilot replay --as md -o pr-comment.md
671
+ oc-pilot replay --in saved.json --fail-on critical
672
+ ```
673
+
674
+ `--format` понимает text, json и sarif; `--as` добавляет md для тела комментария в PR. `--in` читает любой файл с массивом `findings`. Код возврата считается по `--fail-on`, как в `review`.
675
+
676
+ ### `slop`
677
+
678
+ Измеряет энтропию, которую оставляет быстрая генерация кода. `oc-pilot slop` оценивает репозиторий от 0 (чисто) до 100 (гниёт) без API-ключа, модели и сети: нужны только git и рабочее дерево.
679
+
680
+ | Категория | Что находит | Максимум |
681
+ | --- | --- | --- |
682
+ | Дубликаты | Блоки от 72 токенов, повторённые в двух разных файлах | 30 |
683
+ | Мёртвый код | Экспорты, имя которых не встречается ни в одном другом файле (type-only экспорты и точки входа пропускаются) | 25 |
684
+ | Churn без тестов | Файлы, изменённые в пяти и более коммитах, тогда как тесты менялись менее чем в 40% из них | 25 |
685
+ | TODO-кладбище | `TODO`, `FIXME`, `HACK` и `XXX` в комментариях, с весом по возрасту из `git blame` | 20 |
686
+
687
+ ```bash
688
+ oc-pilot slop
689
+ oc-pilot slop --since origin/main --max-delta 10
690
+ oc-pilot slop --json -o slop.json
691
+ oc-pilot slop --badge -o slop.svg
692
+ ```
693
+
694
+ `--since <ref>` сравнивает рабочее дерево с ревизией и показывает, что ветка добавила и убрала по каждой категории, плюс `deltaPoints`. Дельта важнее абсолютного числа: репозиторий может стоять на 50 и при этом быть стабильным.
695
+
696
+ Остальные флаги: `--limit` (элементов на категорию), `--since-days` (окно churn и blame, по умолчанию 30), `--exclude` (глобы или подстроки), `--no-blame` (без `git blame`, заметно быстрее), `--max-index` и `--max-delta` (код возврата 3 при превышении), `--badge` (SVG в стиле shields), `--json`.
697
+
698
+ Ложные срабатывания выносятся в `.oc-pilot/slopignore`: по одному глобу или подстроке на строку, `#` начинает комментарий. Перед анализом из кода вырезаются комментарии и строковые литералы, а тестовые, сгенерированные файлы и lock-файлы пропускаются. Оценка — эвристика, а не приговор.
217
699
 
218
700
  ### `setup`
219
701
 
@@ -239,18 +721,27 @@ oc-pilot setup --client claude --local \
239
721
  oc-pilot doctor
240
722
  oc-pilot doctor --json
241
723
  oc-pilot doctor --engine openai --model deepseek-chat
724
+ oc-pilot doctor --fix
242
725
  ```
243
726
 
244
- Проверки: Node, движок, ключ API, git и репозиторий, тестовая команда, правила проекта и конфиги MCP-клиентов. Ошибки дают exit 1; `--strict` также падает на предупреждениях. Секреты не печатаются.
727
+ Проверки: Node, движок, ключ API, git и репозиторий, тестовая команда, правила проекта, git-хуки oc-pilot и кеш ответов, конфиги MCP-клиентов. `--fix` обновляет устаревшие хуки oc-pilot (предыдущий файл сохраняется как бэкап) и вычищает просроченные записи кеша; чужие хуки не трогаются — о них сообщается. Ошибки дают exit 1; `--strict` также падает на предупреждениях. Секреты не печатаются.
245
728
 
246
729
  ### `init`
247
730
 
248
731
  ```bash
249
732
  oc-pilot init
250
733
  oc-pilot init --force
734
+ oc-pilot init --preset node
735
+ oc-pilot init --hooks
251
736
  ```
252
737
 
253
- Создаёт `.oc-pilot.json` с настройками по умолчанию.
738
+ Создаёт `.oc-pilot.json` с настройками по умолчанию. С `--preset <a,b>` дополнительно пишет готовый `.oc-pilot/rules.md` под стек. Пресеты можно комбинировать, например `--preset react,security`:
739
+
740
+ `base` (универсальный), `node`, `react`, `next`, `vue`, `svelte`, `angular`, `typescript`, `python`, `go`, `rust`, `java`, `kotlin`, `csharp`, `swift`, `php`, `ruby`, `flutter`, `elixir`, `zig`, `scala`, `security` (сквозная безопасность), `devops` (Docker, CI, инфраструктура).
741
+
742
+ Это обычный файл правил — дополняйте его свободно.
743
+
744
+ `--hooks` ставит те же git-хуки, что и `install-hook`: `preflight --staged` на коммит и `review` на пуш. Существующие хуки сохраняются в бэкап, а отсутствие каталога хуков даёт только предупреждение, поэтому `init` из-за этого не падает.
254
745
 
255
746
  ## Конфигурация
256
747
 
@@ -268,7 +759,10 @@ oc-pilot init --force
268
759
  "testCommand": "npm test",
269
760
  "redactSecrets": true,
270
761
  "repoContext": true,
271
- "failOn": "none"
762
+ "failOn": "none",
763
+ "agentRules": true,
764
+ "secondOpinionEnabled": false,
765
+ "maxDailyApiCalls": 0
272
766
  }
273
767
  ```
274
768
 
@@ -293,6 +787,19 @@ oc-pilot init --force
293
787
  ## Безопасность
294
788
 
295
789
  - Сканер ищет AWS/GitHub/GitLab/Slack/Stripe/Google/OpenAI/Anthropic/npm/Hugging Face/Groq/Discord/SendGrid/DigitalOcean/PyPI/Azure-токены, Telegram-бот-токены, JWT, приватные ключи, credentials в URL, generic-присваивания (`password: "..."`) и `.env`-строки (`DB_PASSWORD=...`).
790
+ - Присваивания длиной от 20 символов с энтропией Шеннона выше 4 бит помечаются как critical `High-entropy secret`.
791
+ - Ложные срабатывания отключаются точечно: маски путей в `.oc-pilot/ignore` (по одной на строку, `#` — комментарий) или инлайн-маркер в конце строки кода:
792
+
793
+ ```
794
+ # .oc-pilot/ignore
795
+ fixtures/**
796
+ docs/examples/**
797
+
798
+ # инлайн, любой язык
799
+ const TOKEN = "sk-proj-..."; // oc-pilot:ignore-secret
800
+ ```
801
+
802
+ Правила действуют по путям и строкам во всех точках сканирования (diff, правила, docgen, full-file контекст) и не отключают сканер для остального проекта.
296
803
  - Проверяются только **добавленные** строки diff; удалённые и контекстные строки не считаются утечкой.
297
804
  - Найденные значения заменяются маркерами до отправки модели. В отчётах показывается только маска вида `AKIA…MPLE`.
298
805
  - Блок приватного ключа редактируется целиком, включая тело.
@@ -347,7 +854,9 @@ oc-pilot init --force
347
854
 
348
855
  ## MCP-сервер
349
856
 
350
- `oc-pilot-mcp` — MCP-сервер для Claude Code, Codex, Cursor, Gemini CLI, OpenCode, ZCode и любых клиентов с `.agents/mcp.json`. Он даёт агенту инструменты `review`, `test_fix`, `fix`, `docgen`, `custom`, `scan`, а модель и доступ к репозиторию остаются в вашем CLI.
857
+ `oc-pilot-mcp` — MCP-сервер для Claude Code, Codex, Cursor, Gemini CLI, OpenCode, ZCode и любых клиентов с `.agents/mcp.json`. Он даёт агенту инструменты `review`, `invariants`, `test_fix`, `fix`, `test_gen`, `docgen`, `custom`, `scan`, `commit`, `stats`, `slop`, `mutate`, `fuzz`, `bankruptcy`, `query_ast`, `sandbox`, `hivemind_status`, `flaky`, `impact`, `deps`, `coverage`, `reviewers`, `test_guard`, `env_sync`, `mock_leak`, `ecosystem_verify`, `pack`, `pack_hologram`, `zoom_symbol`, `contract_drift`, `anti_regression`, `boundaries`, `test_plan`, `compliance_verify`, `brag`, `cleanup`, `arch_diff`, `roast`, `cinema`, `bounty`, `autopsy`, `echo`, `sast`, `preflight`, `ready`, `receipt_verify`, а модель и доступ к репозиторию остаются в вашем CLI.
858
+
859
+ Помимо инструментов сервер отдаёт read-only MCP-ресурсы: `oc-pilot://config` (итоговый конфиг), `oc-pilot://rules` (правила проекта с маскировкой секретов), `oc-pilot://prompt/en` и `oc-pilot://prompt/ru` (встроенные системные промпты), `oc-pilot://version`. `oc-pilot://slop` отдаёт Slop Index в JSON без вызова модели. Шаблоны ресурсов дают живые данные: `oc-pilot://diff/{mode}` (staged/unstaged/head diff, секреты замаскированы), `oc-pilot://scan/{mode}` (офлайн-поиск секретов в JSON) и `oc-pilot://file/{+path}` (любой файл проекта до 2 МБ с маскировкой найденных секретов). Клиенты получают списки через `resources/list` и `resources/templates/list`.
351
860
 
352
861
  Автонастройка клиента:
353
862
 
@@ -358,12 +867,34 @@ oc-pilot setup --client cursor --global
358
867
 
359
868
  ZCode импортирует серверы из Claude Code, Codex, OpenCode и `.agents`, либо пишет нативный конфиг через `oc-pilot setup --client zcode`.
360
869
 
870
+ Инструменты: `review`, `invariants`, `test_fix`, `fix`, `test_gen`, `docgen`, `custom`, `scan`, `commit`, `stats`, `slop`, `mutate`, `fuzz`, `bankruptcy`, `query_ast`, `sandbox`, `hivemind_status`, `flaky`, `impact`, `deps`, `coverage`, `reviewers`, `test_guard`, `env_sync`, `mock_leak`, `ecosystem_verify`, `pack`, `pack_hologram`, `zoom_symbol`, `contract_drift`, `anti_regression`, `boundaries`, `test_plan`, `compliance_verify`, `brag`, `battle`, `cleanup`, `arch_diff`, `roast`, `cinema`, `bounty`, `autopsy`, `echo`, `sast`, `authz`, `preflight`, `ready`, `receipt_verify`. У `scan` есть `all: true` — проверка всего репозитория, а не diff. `slop` запускает офлайн Slop Index и принимает `since`, `since_days`, `limit`, `exclude` и `no_blame`. `mutate` прогоняет мутационное тестирование по изменённому коду, принимает `command`, `max_mutants` и `min_score` и возвращает оценку и всех выживших мутантов; оценка ниже `min_score` — обычный результат с кодом 1. `flaky` несколько раз запускает тестовую команду и сравнивает результаты отдельных тестов, принимая `runs`, `command`, `fail_on_flaky`, `shuffle` и `seed`; сам он файлы не меняет, но запускает тесты проекта. `impact` показывает, какие объявления diff изменил или удалил и в каких нетронутых файлах эти имена ещё встречаются; принимает те же флаги источника, а поиск текстовый, поэтому совпадения в комментариях и строках возможны. `deps` проверяет объявленные, импортируемые и залоченные зависимости, `why` объясняет цепочку, `audit` добавляет уязвимости OSV и лицензии, `fix` правит `package.json`, а `sbom` пишет CycloneDX; `fix` и `sbom` пишут файлы и требуют `--allow-write`. `coverage` сверяет изменённые строки с локальным отчётом lcov, Istanbul, Cobertura или Go и возвращает непокрытые строки, файлы без данных и гейт по `fail_under` или `max_uncovered`. `reviewers` ранжирует авторов, которые трогали изменённые файлы, показывает владельцев из CODEOWNERS и принимает `limit`, `depth` и `exclude`; используется только история git. `test_guard` запускает офлайн-проверку на ослабление тестов: пропущенные, сфокусированные или удалённые тесты, удалённые и закомментированные проверки, поднятые таймауты, строгие матчеры, заменённые проверкой существования, `@ts-ignore` и пустые catch; с `fail_on_weakening` находка даёт код 1. `env_sync` сверяет переменные окружения, добавленные diff (`process.env`, `import.meta.env`, `Deno.env`, `Bun.env`), с локальными `.env` и `.env.example`/`.sample`/`.template`: отсутствие определения даёт fail с `fail_on_missing`, а определённые, но не задокументированные переменные — warn. `mock_leak` ищет забытые заглушки и хардкод в добавленном прод-коде: локальные пути, тестовые токены, `if (true)`/`if (false)`, имена mock/fake/stub, комментарии про заглушки и localhost-адреса; `fail_on_leak` даёт код 1 на выбранном уровне. `ecosystem_verify` проверяет, что именованные импорты из изменённых файлов существуют в установленном пакете или его `.d.ts`, и ищет пакеты, которых нет ни в `node_modules`, ни в `package.json`; с `online` дополнительно смотрит возраст и недельные загрузки новых npm-пакетов, а `fail_on_issue` даёт код 1 на выбранном уровне. `pack` собирает компактный контекст задачи: правила проекта, подписи изменённых файлов, связанные ссылки и необязательный лог тестов, с ограничением `budget` в символах; файлы не меняет. `contract_drift` сравнивает изменённые TypeScript-интерфейсы, Zod-объекты, Prisma-модели, Pydantic-модели и JSON Schema с предыдущей версией, находит удалённые поля, ставшие обязательными поля и смену типов и показывает нетронутые файлы, где удалённое поле ещё используется; `fail_on_drift` даёт код 1 на выбранной строгости. `anti_regression` сравнивает строки, добавленные diff, со строками, которые человек явно удалил в истории git, указывает коммит-удаление и ловит повторно добавленный код или импорты; `fail_on_regression` даёт код 1. `boundaries` проверяет добавленные импорты по правилам слоёв из `.oc-pilot/architecture.json`, показывает файл, строку, импорт и причину правила, а `fail_on_violation` даёт код 1 при пересечении границы слоя. `test_plan` выбирает тестовые файлы, затронутые diff, по статическому графу импортов: изменённые тесты, прямые и транзитивные импортёры, совпадения по имени и ссылки на символы; непокрытые изменённые файлы попадают в отчёт, а `fail_on_uncovered` даёт код 1. `compliance_verify` проверяет подписанный аудит-манифест текущего коммита: SHA-256, коммит, цепочку хешей предыдущих манифестов и необязательную подпись Ed25519; отсутствующий, изменённый или разорванный манифест — обычный результат с кодом 1. `test_gen` просит модель написать тесты на изменённый код; с `apply` он пишет файлы, прогоняет тесты и откатывает падения, если не указан `keep_failing`; `coverage` сужает генерацию до непокрытых изменённых строк, а `from_slop` выбирает файлы без тестов. `brag` собирает самодостаточный HTML/SVG-отчёт о сессии из статистики, истории git, последнего ревью и квитанции; только встроенные ресурсы, без модели и сети, `no_paths` скрывает пути. `battle` запускает экспериментальный цикл Coder/Hacker: кодер предлагает патч, хакер делает ревью и прогоняет SAST, авторизацию и проверку ослабления тестов, а цикл останавливается только когда high-находок нет и тесты проходят; `apply` требует `--allow-write`. `cleanup` собирает офлайн-план уборки из проблем зависимостей, Slop Index, переменных окружения и ослабленных тестов; `apply` выполняет только безопасные исправления зависимостей и требует `--allow-write`. `arch_diff` рисует Mermaid-схему внутренних импортов, которые diff добавил или удалил: зелёные стрелки — новые зависимости, красные пунктирные — удалённые, а `fail_on_removed` даёт код 1, когда зависимость исчезла. `roast` превращает diff в технически обоснованную прожарку в выбранной роли (linus, ramsay, corporate или default), ссылается на file:line для каждой шутки и заканчивает одним реальным фиксом; вызывает модель и не меняет файлы. `cinema` собирает терминальный таймлапс сессии из коммитов, запусков, вызовов API, последнего ревью и квитанции: самодостаточный HTML-плеер или asciinema v2 cast, без сети, внешних ресурсов и вызова модели; `no_paths` скрывает темы коммитов и места находок. `bounty` оценивает каждый файл по находкам SAST, дубликатам, мёртвым экспортам, старым TODO и churn без тестов и рисует ASCII-плакат WANTED с худшим файлом и причинами; детерминированно и офлайн. `autopsy` разбирает коммит как детектив: статистика diff, SAST по добавленным строкам, ослабленные тесты, утечки заглушек, рейтинг подозреваемых и хронология до/после; `fail_on_risk` даёт код 1 при опасном вердикте. `echo` собирает самодостаточные SVG-бейджи из локальной статистики, истории git и квитанции (коммиты, запуски агента, вызовы API, попадания в кеш, находки и статус тестов); `submit` отправляет на явный `endpoint` только ник, окно и агрегаты, без путей, diff и секретов, а по умолчанию сети нет. `sast` запускает детерминированный статический анализ по изменению или по явным `paths` и принимает `fail_on_issue`, `ignore` и `no_suppressions`; находка на уровне порога или выше — обычный результат с кодом 1. `authz` проверяет авторизацию маршрутов по изменению или явным `paths` и принимает `fail_on_issue`, `ignore`, `public` и `no_suppressions`; находка маршрута на уровне порога или выше — тоже обычный результат с кодом 1. `preflight` возвращает один офлайн-вердикт по планируемому изменению и принимает те же флаги источника (`diff`, `base`, `staged`, `unstaged`, `include_untracked`), плюс `since`, `max_delta`, `fail_on_issue`, `no_secret_scan`, `no_sast`, `no_authz`, `no_deps`, `no_tests` и `no_slop`; проваленная проверка — обычный результат со `status: "fail"` и кодом 1, а не ошибка инструмента, чтобы агент видел, какая именно проверка упала. `ready` возвращает офлайн-оценку готовности 0–100 и принимает `fail_under`; оценка ниже порога — тоже обычный результат с кодом 1. `receipt_verify` пересчитывает SHA-256 квитанции, сверяет записанный коммит с HEAD и возвращает `ok`, `hashOk` и `stale`; отсутствующая, изменённая или устаревшая квитанция — обычный результат с `ok: false` и кодом 1, чтобы агент видел, почему доказательство не прошло. Инструмент `fix` принимает `from_sast` и `from_authz`, чтобы чинить находки безопасности и пересканировать; результат тогда содержит `sast` или `authz` с `{before, after, remaining}`. Сервер по умолчанию read-only: `--allow-write` разрешает `fix` с `apply: true`, `commit` с `apply: true`, `test_fix` с командой, `stats` с `clear: true` и `mutate`, который временно перезаписывает исходники. Результат `fix` содержит unified-патч, список `files` и `patchStats` (`additions`, `deletions`, `hunks`, `bytes`); патчи длиннее 200 000 символов обрезаются с флагами `patchTruncated` и `patchBytes`, чтобы хост мог показать или применить изменение, не разбирая diff заново.
871
+
872
+ `invariants` проверяет diff против `.oc-pilot/invariants.md`
873
+
874
+ `hivemind` — шифрованная TCP-сеть для обмена аналитической работой: `init` создаёт ed25519 identity, `trust` закрепляет публичный ключ узла, `serve` принимает подписанный ECDH X25519 handshake, а `send` передаёт AES-256-GCM payload. Разрешены только diff, AST и LLM-запросы; исполняемые payload отклоняются, а недоверенные узлы отбрасываются до чтения данных.
875
+
876
+ `sandbox run <file>` исполняет один самодостаточный JavaScript или ESM-файл в `node:vm` с отдельным контекстом: статические импорты, `require`, `fetch`, `process.exit` и таймеры длиннее секунды блокируются, вывод console перехватывается, а исполнение ограничено `--timeout` и `--memory-limit`. TypeScript запускается только из собранного `dist/*.js`. Это не ОС-песочница для нативного кода.
877
+
878
+ `query` выполняет цепочный AQL-запрос к облегчённому графу кода: `find(File|Function|Class|Import|CallExpression).where(field, value).sort(field).limit(n).select(fields...).count()`. Это не SQL и не полный TypeScript AST, а быстрый текстовый граф, который агент может опросить перед правкой. В MCP он доступен как `query_ast`.
879
+
880
+ `bankruptcy` прогнозирует техдолг по истории коммитов: оценивает каждый коммит по ослабленным тестам, SAST high/medium, добавленным TODO, churn и slop-прокси, сглаживает дневной ряд скользящим средним за 14 дней, выбрасывает выбросы и строит линейную регрессию. На выходе — текущий балл, скорость, дата прогноза и самодостаточный SVG-график; меньше 10 коммитов даёт `[INSUFFICIENT DATA: Need at least 10 commits to compute Slop Velocity]`. `--explain` печатает точные веса, где доминируют ослабленные тесты (0.35) и безопасность (0.30).
881
+
882
+ `fix --shadow` и `battle --shadow` выполняют применённый патч внутри `.oc-pilot/shadow-tree` — отдельного git worktree, поэтому тесты и внешние компиляторы видят изменённые файлы. Diff извлекается через `git diff` и применяется к рабочему дереву только при успехе; неудачный прогон оставляет диск нетронутым. `--shadow` требует `--apply`.
883
+
884
+ `fuzz` находит новые экспортируемые функции в diff и вызывает их с null, undefined, -1, 0, пустой строкой, строкой на 10 МБ, объектом `__proto__` и пустыми контейнерами. Каждая цель запускается в отдельном процессе Node с жёстким таймаутом 2 с, настраиваемым лимитом кучи и заглушками fs/net/http/child_process; файлы с импортом побочных модулей блокируются до запуска, а падение или таймаут показываются вместе с конкретным входом. Модель не вызывается.: область `## area` ограничивает правила, `[CRITICAL]` делает правило блокирующим, а правила, чья область не пересекается с изменёнными файлами и их импортёрами, получают `[SKIPPED: Out of scope]` без вызова модели. Модель отвечает строгим JSON, вердикты кешируются по хешу diff и файла инвариантов, а нарушения по умолчанию остаются предупреждениями. Нарушение CRITICAL или `--strict` / `--fail-on violation` даёт код 3. `preflight --invariants` добавляет ту же проверку к гейту.
885
+
886
+ `pack --hologram` собирает слоистый контекст вместо дампа репозитория: LOD 0 оставляет файлы из diff целиком, LOD 1 скрывает тела функций за маркерами `body hidden` с подсказками `EFFECTS` и добавляет подходящие тесты, LOD 2 показывает только имена экспортов. При несбалансированных скобках файл отдаётся целиком с `[Hologram: parse bailout]`, а итоговый Markdown проходит проверку секретов. `zoom-symbol <file> <symbol>` возвращает скрытое тело по запросу; `pack_hologram` и `zoom_symbol` дают тот же сценарий через MCP.
887
+
888
+ Каждый инструмент принимает `max_findings` (по умолчанию 50; урезанный результат дополнительно содержит `truncated` и `totalFindings`) и `verbosity` (`full` отдаёт JSON, `compact` — одну строку сводки, а те же данные остаются в `structuredContent`). Если клиент передал `_meta.progressToken`, сервер шлёт `notifications/progress`; после `logging/setLevel` — ещё и `notifications/message` на каждый вызов. `--max-calls <n>` (или `OC_PILOT_MCP_MAX_CALLS`) ограничивает число вызовов с моделью за сессию, `0` снимает лимит, а офлайн-инструменты `scan`, `fuzz`, `bankruptcy`, `query_ast`, `sandbox`, `hivemind_status`, `stats`, `slop`, `flaky`, `impact`, `deps`, `coverage`, `reviewers`, `test_guard`, `env_sync`, `mock_leak`, `ecosystem_verify`, `pack`, `pack_hologram`, `zoom_symbol`, `contract_drift`, `anti_regression`, `boundaries`, `test_plan`, `compliance_verify`, `brag`, `cleanup`, `arch_diff`, `roast`, `cinema`, `bounty`, `autopsy`, `echo`, `sast`, `authz`, `preflight`, `ready` и `receipt_verify` работают и после исчерпания бюджета.
889
+
890
+ Готовые промпты отдаются через `prompts/list` и рендерятся `prompts/get`, чтобы клиент мог показать их в своём меню: `review-my-diff` (необязательный `context`), `fix-failing-tests` (необязательный `log`), `pre-commit-gate` (scan, review и commit одним проходом), `secure-change` (ревью с фокусом на безопасность), `slop-check` (проверка энтропии вайб-кода) и `preflight-before-commit` (прогнать офлайн-гейт, починить самую дешёвую упавшую проверку и повторять до вердикта pass), `compile-hologram` (собрать слоистую голограмму, оставить LOD 0 полным, считать скрытые тела LOD 1 неизвестными и вызывать `zoom_symbol` перед рассуждением о них), `check-invariants` (проверить изменение против `.oc-pilot/invariants.md`, объяснить каждое нарушение с file:line и не скрывать CRITICAL-правило), `fuzz-the-diff` (вызвать новые экспорты с мусорными входами в изолированных процессах, починить каждое падение и не считать заблокированные цели проверенными), `forecast-tech-debt` (прочитать тренд техдолга, объяснить балл и веса и использовать дату прогноза для плана выплаты, а не для игры с TODO), `query-the-ast` (найти вызовы, функции, классы и импорты через AQL, проверить каждое попадание в исходнике и использовать доказательства для плана рефакторинга), `sandbox-script` (запустить сгенерированный JS/ESM-файл в node:vm с блокировкой импортов и побочных эффектов, затем показать вывод и точный статус), `join-the-swarm` (проверить identity и доверенных узлов hivemind, затем обмениваться только diff, AST и LLM-запросами по шифрованной сети; никогда не отправлять исполняемые команды), `get-ready` (оценить репозиторий, починить безопасные пробелы, доказать результат квитанцией и повторять до оценки не ниже 85), `fix-security` (починить находки SAST или авторизации маршрутов и пересканировать, пока не останется high), `stabilize-flaky` (воспроизвести нестабильный тест повторными и перемешанными прогонами и внести минимальное детерминированное исправление), `check-impact` (найти внешние ссылки на изменённые объявления, починить сломанные места и повторять, пока не останется устаревших ссылок), `triage-deps` (проверить зависимости и уязвимости OSV, починить самое дешёвое и повторить, не скрывая находки), `cover-changed-lines` (добавить тесты на изменённые строки, которые не выполнил ни один тест, и повторить тот же гейт), `generate-tests` (сгенерировать тесты на изменение или его непокрытые строки, применить, прогнать и повторять до зелёного), `pick-reviewers` (выбрать минимальный набор ревьюеров, которые знают изменённые файлы, с доказательствами из истории и CODEOWNERS), `guard-tests` (найти тесты, которые изменение пропустило, ослабило или удалило, вернуть им защиту и повторять до прохождения гейта), `sync-env` (сверить переменные окружения, добавленные изменением, с `.env` и `.env.example`, добавить недостающие определения и задокументировать их, не выдумывая секреты), `remove-mocks` (найти забытые заглушки, локальные пути, тестовые токены и всегда истинные условия в прод-коде, заменить их реальной реализацией и повторять до чистого отчёта), `verify-ecosystem` (проверить, что импорты существуют в установленных пакетах, а новые npm-пакеты не появились вчера с парой загрузок, и не ставить подозрительный пакет без решения человека), `pack-context` (собрать компактный контекст задачи из правил, подписей, ссылок и лога тестов и использовать его вместо вываливания целых файлов), `check-contracts` (найти удалённые или суженные поля в изменённых типах и схемах, обновить всех оставшихся потребителей, не ломая их молча), `guard-regressions` (сравнить добавленные строки с кодом, который человек удалил, изучить коммит-удаление и не возвращать его без явного решения), `respect-boundaries` (проверить добавленные импорты по правилам слоёв, исправить направление зависимости и повторять, пока ни одна граница не пересечена), `plan-tests` (прогнать план затронутых тестов, запустить только их, добавить тест на каждый непокрытый изменённый файл и повторить, не расширяя стратегию), `prove-compliance` (проверить подписанный аудит-манифест для HEAD, цепочку хешей и подпись и не заявлять о готовности, пока манифест недействителен), `cleanup-plan` (собрать офлайн-план уборки и применить только безопасные исправления зависимостей), `show-arch-diff` (нарисовать Mermaid-схему добавленных и удалённых внутренних импортов), `roast-my-code` (прожарить diff в выбранной персоне, с file:line и одним реальным исправлением), `play-session` (собрать терминальный таймлапс сессии в виде самодостаточного HTML-плеера или asciinema cast), `wanted-poster` (нарисовать плакат WANTED для худшего файла, объяснить причины и самое весомое исправление и повторить после исправления), `autopsy-commit` (разобрать коммит, перечислить сигналы, ранжировать подозреваемых, прочитать хронологию до/после и предложить минимальное исправление и тест, который поймал бы проблему), `share-progress` (собрать локальные SVG-бейджи и только с явного разрешения отправить анонимные агрегаты на указанный endpoint), `prove-tests` (прогнать мутационное тестирование по изменению и усилить тесты, пока mutation score не достигнет 80) и `prove-done` (проверить квитанцию для HEAD, создать свежую, если её нет или она устарела, и не заявлять о готовности, пока `ok` не равен true, а тесты в квитанции не пройдены).
891
+
361
892
  Запуск вручную:
362
893
 
363
894
  ```bash
364
895
  oc-pilot-mcp --cwd "C:\path\to\project"
365
896
  # после релиза в npm, версия зафиксирована:
366
- npx -y oc-pilot@0.5.1 mcp --cwd "C:\path\to\project"
897
+ npx -y oc-pilot@0.5.2 mcp --cwd "C:\path\to\project"
367
898
  ```
368
899
 
369
900
  Пример для Claude Code (`.mcp.json`):
@@ -393,7 +924,7 @@ curl http://127.0.0.1:8787/health
393
924
 
394
925
  Сервер возвращает `Mcp-Session-Id` при initialize; его нужно передавать в следующих запросах. При `--token` все запросы кроме `GET /health` требуют `Authorization: Bearer <token>`. Без токена длиной от 16 символов сервер не запустится на не-loopback хосте. Для публичного доступа ставьте TLS-прокси.
395
926
 
396
- MCP по умолчанию **read-only** и для stdio, и для HTTP: `fix` с `apply:true` и `test_fix`, запускающий новую команду, отклоняются. Для доверенного локального клиента или аутентифицированного окружения добавьте `--allow-write` (в `setup` — `oc-pilot setup --allow-write`) или `OC_PILOT_MCP_READ_ONLY=false`.
927
+ MCP по умолчанию **read-only** и для stdio, и для HTTP: `fix` с `apply:true`, `test_fix`, запускающий новую команду, и `deps` с `fix: true` или `sbom`, а также `test_gen` с `apply: true` отклоняются. Для доверенного локального клиента или аутентифицированного окружения добавьте `--allow-write` (в `setup` — `oc-pilot setup --allow-write`) или `OC_PILOT_MCP_READ_ONLY=false`.
397
928
 
398
929
  ```bash
399
930
  export OC_PILOT_MCP_TOKEN="$(openssl rand -hex 24)"
@@ -406,7 +937,18 @@ docker run --rm -p 8787:8787 \
406
937
 
407
938
  Или `docker-compose up`. Образ включает OpenCode; `scan` работает без модели.
408
939
 
409
- Agent Skill для Claude Code/Codex/OpenCode лежит в [`skills/oc-pilot/SKILL.md`](skills/oc-pilot/SKILL.md): он объясняет агенту, когда вызывать `scan`, `review`, `test-fix`, `fix` и `docgen`.
940
+ В `skills/` лежат переносимые Agent Skills для Claude Code, Codex, Cursor, Copilot и OpenCode. Каждый объясняет агенту, какой шлагбаум нужно закрыть, прежде чем считать работу готовой:
941
+
942
+ | Skill | Назначение |
943
+ | --- | --- |
944
+ | `oc-pilot` | Точка входа: когда вызывать `scan`, `review`, `test-fix`, `fix` и `docgen`. |
945
+ | `agent-self-review` | Цикл перед коммитом: скан, ревью, фикс, повторная проверка, отчёт с кодом возврата. |
946
+ | `test-failure-triage` | Захват лога падения, первопричина, патч со снимком, повторный прогон. |
947
+ | `secure-diff-gate` | Секреты, правила безопасности, признаки промпт-инъекций и риски зависимостей, SARIF. |
948
+ | `commit-discipline` | Conventional Commit по staged-diff с блокировкой при секретах. |
949
+ | `stack-review-packs` | Комбинируемые наборы правил для 23 стеков. |
950
+
951
+ Скопируйте нужный каталог в свой skills-каталог или укажите клиенту на этот репозиторий.
410
952
 
411
953
  Конфигурации для Codex, Cursor, Gemini CLI и OpenCode, формат результата и CI-примеры — в [docs/integrations.md](docs/integrations.md). Инструменты принимают `diff` и `log` как текст, а `paths` — относительно `--cwd`.
412
954
 
@@ -424,7 +966,7 @@ jobs:
424
966
  - uses: actions/checkout@v4
425
967
  with:
426
968
  fetch-depth: 0
427
- - uses: MyNameIsNikki/oc-pilot@v0.5.1
969
+ - uses: MyNameIsNikki/oc-pilot@v0.88.1
428
970
  with:
429
971
  command: scan
430
972
  args: --base origin/${{ github.base_ref }} --fail-on-secrets
@@ -464,6 +1006,18 @@ jobs:
464
1006
 
465
1007
  `--github` печатает inline-аннотации `::error file=...,line=...` и `::warning`. Для машинного отчёта используйте `--json --output review.json`. Провайдер и переменные авторизации зависят от вашей конфигурации OpenCode. В CI заранее выполните `opencode auth` или передайте ключ провайдера через секреты.
466
1008
 
1009
+ Загрузка результатов в GitHub Code Scanning:
1010
+
1011
+ ```yaml
1012
+ - run: node dist/cli.js scan --base "origin/${{ github.base_ref }}" --format sarif -o oc-pilot.sarif
1013
+ working-directory: oc-pilot
1014
+ - uses: github/codeql-action/upload-sarif@v3
1015
+ with:
1016
+ sarif_file: oc-pilot.sarif
1017
+ ```
1018
+
1019
+ Каждый релиз публикуется из тега workflow самого репозитория (OIDC trusted publishing с provenance-аттестацией; секрет `NPM_TOKEN` включает запасной путь через granular-токен npm), а тело GitHub Release берётся из соответствующего раздела `CHANGELOG.md`. CI гоняет тесты на Node 22 и 24 и печатает информационную таблицу покрытия через `node --test --experimental-test-coverage` — без порога, чтобы шумный сигнал не блокировал мерж.
1020
+
467
1021
  ## Ограничения
468
1022
 
469
1023
  - Diff обрезается до `maxDiffChars`; при переполнении файлы усекаются, в diff появляется маркер.
@@ -518,6 +1072,14 @@ README.md
518
1072
  README.ru.md
519
1073
  ```
520
1074
 
1075
+ ### Регрессионные тесты
1076
+
1077
+ Три уровня защищают контракты, которые видит модель:
1078
+
1079
+ - `test/golden/` фиксирует собранный INPUT для заданных diff: порядок секций, обработка пустых значений и redaction секретов меняются только осознанно. Пересобрать: `OC_PILOT_UPDATE_GOLDEN=1 npm test`, затем прочитать diff перед коммитом.
1080
+ - `test/fixtures/model-output/` — реалистичные ответы моделей; `src/core/output-format.test.ts` проверяет, какие severity, локации и текст CLI из них извлекает.
1081
+ - `normalizeLocation` приводит форматы локаций, которые реально пишут модели (`a.ts:10-14`, `a.ts:10,12`, `a.ts#L12`, `a.ts (line 10)` → `a.ts:10`), а списки внутри code fence при разборе игнорируются.
1082
+
521
1083
  ## Лицензия
522
1084
 
523
1085
  MIT. См. [LICENSE](LICENSE).