code-review-forge 2.4.0__tar.gz → 2.9.0__tar.gz

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 (328) hide show
  1. {code_review_forge-2.4.0/src/code_review_forge.egg-info → code_review_forge-2.9.0}/PKG-INFO +240 -12
  2. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/README.md +233 -10
  3. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/pyproject.toml +10 -3
  4. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/__init__.py +3 -1
  5. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/__main__.py +4 -2
  6. code_review_forge-2.9.0/src/code_forge/advisory.py +112 -0
  7. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/autofix.py +18 -1
  8. code_review_forge-2.9.0/src/code_forge/backend.py +1130 -0
  9. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/baseline.py +18 -3
  10. code_review_forge-2.9.0/src/code_forge/basis.py +134 -0
  11. code_review_forge-2.9.0/src/code_forge/canary.py +186 -0
  12. code_review_forge-2.9.0/src/code_forge/canary_gen.py +420 -0
  13. code_review_forge-2.9.0/src/code_forge/claim.py +52 -0
  14. code_review_forge-2.9.0/src/code_forge/cli.py +4389 -0
  15. code_review_forge-2.9.0/src/code_forge/contract_loader.py +433 -0
  16. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/conventions_resolver.py +2 -2
  17. code_review_forge-2.9.0/src/code_forge/cross_repo.py +449 -0
  18. code_review_forge-2.9.0/src/code_forge/cross_repo_impact.py +342 -0
  19. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/daemon_state.py +16 -8
  20. code_review_forge-2.9.0/src/code_forge/dead_code.py +328 -0
  21. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/delta.py +21 -3
  22. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/detect.py +156 -12
  23. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/diagnose.py +12 -0
  24. code_review_forge-2.9.0/src/code_forge/diff.py +499 -0
  25. code_review_forge-2.9.0/src/code_forge/diff_grouping.py +469 -0
  26. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/disposition.py +4 -0
  27. code_review_forge-2.9.0/src/code_forge/doctor.py +571 -0
  28. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/e2e_check.py +30 -6
  29. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/errors.py +24 -0
  30. code_review_forge-2.9.0/src/code_forge/eval/corpus.py +196 -0
  31. code_review_forge-2.9.0/src/code_forge/eval/export.py +608 -0
  32. code_review_forge-2.9.0/src/code_forge/eval/runner.py +781 -0
  33. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/eval/scorer.py +183 -8
  34. code_review_forge-2.9.0/src/code_forge/evidence.py +67 -0
  35. code_review_forge-2.9.0/src/code_forge/exec_falsify.py +426 -0
  36. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/exit_codes.py +8 -1
  37. code_review_forge-2.9.0/src/code_forge/factories.py +852 -0
  38. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/falsify.py +1 -1
  39. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/falsify_real.py +15 -10
  40. code_review_forge-2.9.0/src/code_forge/findings.py +24 -0
  41. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/fixval.py +13 -9
  42. code_review_forge-2.9.0/src/code_forge/flow_contract.py +33 -0
  43. code_review_forge-2.9.0/src/code_forge/gate.schema.json +430 -0
  44. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/gate_check.py +409 -8
  45. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/git.py +24 -13
  46. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/graph_triage.py +99 -50
  47. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/hold.py +5 -2
  48. code_review_forge-2.9.0/src/code_forge/init_template.py +217 -0
  49. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/install_hooks.py +259 -42
  50. code_review_forge-2.9.0/src/code_forge/ledger.py +210 -0
  51. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/legacy.py +14 -15
  52. code_review_forge-2.9.0/src/code_forge/llm_invoke.py +2282 -0
  53. code_review_forge-2.9.0/src/code_forge/lock.py +455 -0
  54. code_review_forge-2.9.0/src/code_forge/machine.py +2182 -0
  55. code_review_forge-2.9.0/src/code_forge/manifest.py +382 -0
  56. code_review_forge-2.9.0/src/code_forge/mcp_jobs.py +350 -0
  57. code_review_forge-2.9.0/src/code_forge/mcp_server.py +1472 -0
  58. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/mutation.py +117 -6
  59. code_review_forge-2.9.0/src/code_forge/outlet_c.py +225 -0
  60. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/outlet_resolver.py +60 -21
  61. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/__init__.py +3 -2
  62. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/_sarif.py +19 -8
  63. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/base.py +1 -18
  64. code_review_forge-2.9.0/src/code_forge/parsers/eslint.py +64 -0
  65. code_review_forge-2.9.0/src/code_forge/proc.py +120 -0
  66. code_review_forge-2.9.0/src/code_forge/progress.py +72 -0
  67. code_review_forge-2.9.0/src/code_forge/receipt.py +278 -0
  68. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/registry.py +2 -0
  69. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/reporter.py +1 -1
  70. code_review_forge-2.9.0/src/code_forge/reviewer_json.py +191 -0
  71. code_review_forge-2.9.0/src/code_forge/rulepack.py +620 -0
  72. code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/meta.yaml +45 -0
  73. code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/rules.yaml +55 -0
  74. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/runner.py +39 -16
  75. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/runtime.py +41 -19
  76. code_review_forge-2.9.0/src/code_forge/sarif.py +381 -0
  77. code_review_forge-2.9.0/src/code_forge/setup_mcp.py +269 -0
  78. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/SKILL.md +50 -15
  79. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/snapshot.py +2 -2
  80. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/state.py +109 -4
  81. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/taint.py +4 -4
  82. code_review_forge-2.9.0/src/code_forge/trust.py +369 -0
  83. code_review_forge-2.9.0/src/code_forge/user_config.py +111 -0
  84. code_review_forge-2.9.0/src/code_forge/verify.py +904 -0
  85. code_review_forge-2.9.0/src/code_forge/workspace.py +51 -0
  86. {code_review_forge-2.4.0 → code_review_forge-2.9.0/src/code_review_forge.egg-info}/PKG-INFO +240 -12
  87. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/SOURCES.txt +98 -0
  88. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/entry_points.txt +1 -0
  89. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/requires.txt +7 -1
  90. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/top_level.txt +0 -1
  91. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_advisory.py +99 -33
  92. code_review_forge-2.9.0/tests/test_backend.py +2156 -0
  93. code_review_forge-2.9.0/tests/test_backend_attribution.py +123 -0
  94. code_review_forge-2.9.0/tests/test_basis.py +224 -0
  95. code_review_forge-2.9.0/tests/test_canary.py +218 -0
  96. code_review_forge-2.9.0/tests/test_canary_cli.py +431 -0
  97. code_review_forge-2.9.0/tests/test_canary_gen.py +510 -0
  98. code_review_forge-2.9.0/tests/test_canary_smoke.py +394 -0
  99. code_review_forge-2.9.0/tests/test_chunking.py +278 -0
  100. code_review_forge-2.9.0/tests/test_claim_type.py +226 -0
  101. code_review_forge-2.9.0/tests/test_cli_advisory_wiring.py +117 -0
  102. code_review_forge-2.9.0/tests/test_cli_banner.py +349 -0
  103. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_e2e_check.py +162 -2
  104. code_review_forge-2.9.0/tests/test_cli_empty_diff.py +115 -0
  105. code_review_forge-2.9.0/tests/test_cli_entrypoint.py +44 -0
  106. code_review_forge-2.9.0/tests/test_cli_eval.py +929 -0
  107. code_review_forge-2.9.0/tests/test_cli_grouping_wiring.py +52 -0
  108. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_hold_resume.py +64 -9
  109. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_init.py +6 -6
  110. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_integration.py +39 -9
  111. code_review_forge-2.9.0/tests/test_cli_internal_error.py +69 -0
  112. code_review_forge-2.9.0/tests/test_cli_l2_wiring.py +78 -0
  113. code_review_forge-2.9.0/tests/test_cli_ledger.py +770 -0
  114. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_parser.py +9 -37
  115. code_review_forge-2.9.0/tests/test_cli_pending_exit.py +25 -0
  116. code_review_forge-2.9.0/tests/test_cli_phase1_compat.py +38 -0
  117. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_sarif.py +38 -14
  118. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_trust.py +206 -23
  119. code_review_forge-2.9.0/tests/test_cli_verify_required_cycles.py +179 -0
  120. code_review_forge-2.9.0/tests/test_contract_flag.py +611 -0
  121. code_review_forge-2.9.0/tests/test_contract_loader.py +719 -0
  122. code_review_forge-2.9.0/tests/test_contract_wiring.py +415 -0
  123. code_review_forge-2.9.0/tests/test_cross_repo.py +1241 -0
  124. code_review_forge-2.9.0/tests/test_cross_repo_contracts.py +549 -0
  125. code_review_forge-2.9.0/tests/test_cross_repo_impact.py +604 -0
  126. code_review_forge-2.9.0/tests/test_cross_repo_impact_integration.py +568 -0
  127. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_daemon_state.py +122 -22
  128. code_review_forge-2.9.0/tests/test_dead_code.py +697 -0
  129. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_detect.py +104 -0
  130. code_review_forge-2.9.0/tests/test_detect_c.py +88 -0
  131. code_review_forge-2.9.0/tests/test_detect_cpp.py +88 -0
  132. code_review_forge-2.9.0/tests/test_detect_java.py +96 -0
  133. code_review_forge-2.9.0/tests/test_detect_js.py +96 -0
  134. code_review_forge-2.9.0/tests/test_diff.py +898 -0
  135. code_review_forge-2.9.0/tests/test_diff_grouping.py +478 -0
  136. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_disposition.py +3 -3
  137. code_review_forge-2.9.0/tests/test_doctor.py +805 -0
  138. code_review_forge-2.9.0/tests/test_doctor_tool_audit.py +224 -0
  139. code_review_forge-2.9.0/tests/test_dogfood.py +372 -0
  140. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_e2e_check.py +25 -0
  141. code_review_forge-2.9.0/tests/test_encoding_conformance.py +190 -0
  142. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_corpus.py +1 -1
  143. code_review_forge-2.9.0/tests/test_eval_corpus_findings.py +823 -0
  144. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_runner.py +127 -54
  145. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_scorer.py +2 -2
  146. code_review_forge-2.9.0/tests/test_evidence.py +91 -0
  147. code_review_forge-2.9.0/tests/test_exec_falsify.py +603 -0
  148. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_exit_codes.py +35 -4
  149. code_review_forge-2.9.0/tests/test_export_eval.py +1118 -0
  150. code_review_forge-2.9.0/tests/test_f3_legacy_exit.py +311 -0
  151. code_review_forge-2.9.0/tests/test_factories.py +1549 -0
  152. code_review_forge-2.9.0/tests/test_falsify_real.py +317 -0
  153. code_review_forge-2.9.0/tests/test_fast_fail.py +378 -0
  154. code_review_forge-2.9.0/tests/test_findings.py +28 -0
  155. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fixval_integration.py +8 -1
  156. code_review_forge-2.9.0/tests/test_flow_contract_drift.py +90 -0
  157. code_review_forge-2.9.0/tests/test_focus.py +224 -0
  158. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_gate_check.py +197 -6
  159. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_git.py +43 -2
  160. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_graph_triage.py +58 -7
  161. code_review_forge-2.9.0/tests/test_hook_carveout.py +528 -0
  162. code_review_forge-2.9.0/tests/test_hook_failclosed.py +115 -0
  163. code_review_forge-2.9.0/tests/test_infra_convergence.py +228 -0
  164. code_review_forge-2.9.0/tests/test_inline_delegated.py +69 -0
  165. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_install_hooks.py +310 -45
  166. code_review_forge-2.9.0/tests/test_ledger.py +341 -0
  167. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_legacy.py +25 -2
  168. code_review_forge-2.9.0/tests/test_llm_invoke.py +5825 -0
  169. code_review_forge-2.9.0/tests/test_lock.py +802 -0
  170. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_advisory.py +8 -8
  171. code_review_forge-2.9.0/tests/test_machine_ci.py +228 -0
  172. code_review_forge-2.9.0/tests/test_machine_l0_crash_guard.py +93 -0
  173. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_l2.py +277 -3
  174. code_review_forge-2.9.0/tests/test_machine_ledger.py +875 -0
  175. code_review_forge-2.9.0/tests/test_machine_local.py +902 -0
  176. code_review_forge-2.9.0/tests/test_machine_mutation_launch.py +367 -0
  177. code_review_forge-2.9.0/tests/test_manifest.py +266 -0
  178. code_review_forge-2.9.0/tests/test_mcp_jobs.py +1068 -0
  179. code_review_forge-2.9.0/tests/test_mcp_pdeathsig.py +194 -0
  180. code_review_forge-2.9.0/tests/test_mcp_server.py +3101 -0
  181. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_outlet_c.py +71 -0
  182. code_review_forge-2.9.0/tests/test_outlet_c_cli.py +466 -0
  183. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_outlet_resolver.py +120 -6
  184. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_parsers.py +1 -0
  185. code_review_forge-2.9.0/tests/test_post_image_window.py +302 -0
  186. code_review_forge-2.9.0/tests/test_progress.py +55 -0
  187. code_review_forge-2.9.0/tests/test_realpath_ledger.py +116 -0
  188. code_review_forge-2.9.0/tests/test_receipt.py +502 -0
  189. code_review_forge-2.9.0/tests/test_receipt_partial.py +285 -0
  190. code_review_forge-2.9.0/tests/test_reviewer_json.py +119 -0
  191. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_round.py +8 -2
  192. code_review_forge-2.9.0/tests/test_rulepack_blocking.py +143 -0
  193. code_review_forge-2.9.0/tests/test_rulepack_loader.py +224 -0
  194. code_review_forge-2.9.0/tests/test_rulepack_matrix.py +110 -0
  195. code_review_forge-2.9.0/tests/test_rulepack_runner.py +241 -0
  196. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runner.py +8 -6
  197. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime.py +146 -52
  198. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_drift.py +4 -4
  199. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_eval.py +4 -4
  200. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_machine.py +6 -6
  201. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_sarif.py +239 -39
  202. code_review_forge-2.9.0/tests/test_schema_corpus.py +867 -0
  203. code_review_forge-2.9.0/tests/test_setup_mcp.py +270 -0
  204. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_schema.py +30 -2
  205. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint.py +1 -1
  206. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_trust.py +24 -11
  207. code_review_forge-2.9.0/tests/test_trust_empty_backends.py +84 -0
  208. code_review_forge-2.9.0/tests/test_user_config.py +313 -0
  209. code_review_forge-2.9.0/tests/test_verify.py +2270 -0
  210. code_review_forge-2.4.0/src/code_forge/advisory.py +0 -78
  211. code_review_forge-2.4.0/src/code_forge/backend.py +0 -532
  212. code_review_forge-2.4.0/src/code_forge/cli.py +0 -2154
  213. code_review_forge-2.4.0/src/code_forge/diff.py +0 -254
  214. code_review_forge-2.4.0/src/code_forge/eval/corpus.py +0 -79
  215. code_review_forge-2.4.0/src/code_forge/eval/runner.py +0 -464
  216. code_review_forge-2.4.0/src/code_forge/factories.py +0 -338
  217. code_review_forge-2.4.0/src/code_forge/init_template.py +0 -72
  218. code_review_forge-2.4.0/src/code_forge/llm_invoke.py +0 -675
  219. code_review_forge-2.4.0/src/code_forge/lock.py +0 -162
  220. code_review_forge-2.4.0/src/code_forge/machine.py +0 -1213
  221. code_review_forge-2.4.0/src/code_forge/outlet_c.py +0 -102
  222. code_review_forge-2.4.0/src/code_forge/receipt.py +0 -134
  223. code_review_forge-2.4.0/src/code_forge/reviewer_json.py +0 -111
  224. code_review_forge-2.4.0/src/code_forge/sarif.py +0 -243
  225. code_review_forge-2.4.0/src/code_forge/trust.py +0 -178
  226. code_review_forge-2.4.0/src/code_forge/verify.py +0 -381
  227. code_review_forge-2.4.0/tests/test_backend.py +0 -1061
  228. code_review_forge-2.4.0/tests/test_cli_eval.py +0 -326
  229. code_review_forge-2.4.0/tests/test_cli_phase1_compat.py +0 -191
  230. code_review_forge-2.4.0/tests/test_diff.py +0 -324
  231. code_review_forge-2.4.0/tests/test_factories.py +0 -332
  232. code_review_forge-2.4.0/tests/test_falsify_real.py +0 -55
  233. code_review_forge-2.4.0/tests/test_hook_carveout.py +0 -245
  234. code_review_forge-2.4.0/tests/test_llm_invoke.py +0 -1080
  235. code_review_forge-2.4.0/tests/test_lock.py +0 -174
  236. code_review_forge-2.4.0/tests/test_machine_ci.py +0 -133
  237. code_review_forge-2.4.0/tests/test_machine_local.py +0 -384
  238. code_review_forge-2.4.0/tests/test_receipt.py +0 -88
  239. code_review_forge-2.4.0/tests/test_verify.py +0 -305
  240. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/LICENSE +0 -0
  241. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/MANIFEST.in +0 -0
  242. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/setup.cfg +0 -0
  243. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/conventions.py +0 -0
  244. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/coverage.py +0 -0
  245. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/env_resolver.py +0 -0
  246. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/eval/__init__.py +0 -0
  247. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/mode_resolver.py +0 -0
  248. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/checkpatch.py +0 -0
  249. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/clippy.py +0 -0
  250. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/flake8.py +0 -0
  251. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/non_ascii.py +0 -0
  252. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/pylint.py +0 -0
  253. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/ruff.py +0 -0
  254. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/semgrep.py +0 -0
  255. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/shellcheck.py +0 -0
  256. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/rules/forge-taint.yaml +0 -0
  257. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/adversarial-qe/SKILL.md +0 -0
  258. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass1-qodo.md +0 -0
  259. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass2-expert.md +0 -0
  260. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass3-adversarial.md +0 -0
  261. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/code-quality-checklist.md +0 -0
  262. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/removal-plan.md +0 -0
  263. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/security-checklist.md +0 -0
  264. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/solid-checklist.md +0 -0
  265. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/SKILL.md +0 -0
  266. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/references/code-quality-checklist.md +0 -0
  267. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/references/removal-plan.md +0 -0
  268. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/references/security-checklist.md +0 -0
  269. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/references/solid-checklist.md +0 -0
  270. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/kernel-fp-verify/SKILL.md +0 -0
  271. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/qodo-review/SKILL.md +0 -0
  272. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/SKILL.md +0 -0
  273. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/boundary-cases.md +0 -0
  274. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/concurrency-patterns.md +0 -0
  275. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/injection-payloads.md +0 -0
  276. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/README.md +0 -0
  277. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/primitives.sh +0 -0
  278. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/primitives_test.sh +0 -0
  279. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/source.py +0 -0
  280. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/verdict.py +0 -0
  281. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/dependency_links.txt +0 -0
  282. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_baseline.py +0 -0
  283. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_baseline_integration.py +0 -0
  284. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_backend_propagation.py +0 -0
  285. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_detect.py +0 -0
  286. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_install_skill.py +0 -0
  287. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_lock.py +0 -0
  288. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_mutation_check.py +0 -0
  289. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_consecutive_clean.py +0 -0
  290. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_conventions.py +0 -0
  291. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_conventions_resolver.py +0 -0
  292. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_coverage.py +0 -0
  293. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_daemon_state_drift.py +0 -0
  294. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_delta.py +0 -0
  295. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_diagnose.py +0 -0
  296. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo04_lifecycle.py +0 -0
  297. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo05_promotion.py +0 -0
  298. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo06_revert.py +0 -0
  299. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_env_resolver.py +0 -0
  300. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_escalated_frozen.py +0 -0
  301. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_falsify_stub.py +0 -0
  302. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fixval.py +0 -0
  303. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fresh_start.py +0 -0
  304. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_hold_entry.py +0 -0
  305. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_hold_ui.py +0 -0
  306. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_integration.py +0 -0
  307. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_legacy_integration.py +0 -0
  308. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_lock_signals.py +0 -0
  309. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_coverage.py +0 -0
  310. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_e2e.py +0 -0
  311. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_mode_resolver.py +0 -0
  312. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_mutation.py +0 -0
  313. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_ordering.py +0 -0
  314. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_pass_determinism.py +0 -0
  315. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_phase1_migration.py +0 -0
  316. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_phase3.py +0 -0
  317. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_promotion_tracking.py +0 -0
  318. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_pseudo_refs.py +0 -0
  319. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_r1_e2e.py +0 -0
  320. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_registry.py +0 -0
  321. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_smoke_receipt.py +0 -0
  322. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_snapshot.py +0 -0
  323. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_source_hash.py +0 -0
  324. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_04_extensions.py +0 -0
  325. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_extensions.py +0 -0
  326. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint_integration.py +0 -0
  327. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint_rule.py +0 -0
  328. {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_verdict.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-review-forge
3
- Version: 2.4.0
3
+ Version: 2.9.0
4
4
  Summary: 3-state quality gate for code review
5
5
  Author-email: Minxi Hou <houminxi@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -19,17 +19,22 @@ Requires-Dist: pyyaml>=6.0
19
19
  Requires-Dist: unidiff<0.8.0,>=0.7.5
20
20
  Provides-Extra: dev
21
21
  Requires-Dist: pytest>=8.0; extra == "dev"
22
+ Requires-Dist: pytest-asyncio>=1.0; extra == "dev"
23
+ Requires-Dist: ruff>=0.5; extra == "dev"
22
24
  Requires-Dist: mutmut<4.0,>=3.3; extra == "dev"
23
- Requires-Dist: semgrep<1.100,>=1.0; extra == "dev"
25
+ Requires-Dist: semgrep<1.170,>=1.0; extra == "dev"
26
+ Requires-Dist: jsonschema>=4.18; extra == "dev"
24
27
  Provides-Extra: vertex
25
28
  Requires-Dist: google-auth>=2.35.0; extra == "vertex"
26
29
  Requires-Dist: requests>=2.20.0; extra == "vertex"
30
+ Provides-Extra: mcp
31
+ Requires-Dist: mcp<2,>=1.27; extra == "mcp"
27
32
  Dynamic: license-file
28
33
 
29
34
  # code-forge
30
35
 
31
- [![PyPI version](https://img.shields.io/pypi/v/code-review-forge.svg)](https://pypi.org/project/code-review-forge/)
32
- [![Python](https://img.shields.io/pypi/pyversions/code-review-forge.svg)](https://pypi.org/project/code-review-forge/)
36
+ [![PyPI version](https://img.shields.io/pypi/v/code-review-forge.svg?cacheSeconds=300)](https://pypi.org/project/code-review-forge/)
37
+ [![Python](https://img.shields.io/pypi/pyversions/code-review-forge.svg?cacheSeconds=300)](https://pypi.org/project/code-review-forge/)
33
38
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/HouMinXi/forge/blob/main/LICENSE)
34
39
 
35
40
  A 5-step code review pipeline for AI coding assistants. Treats review as a
@@ -60,6 +65,12 @@ pip install code-review-forge
60
65
  code-forge install-skill
61
66
  ```
62
67
 
68
+ For MCP server support (IDE integration):
69
+
70
+ ```bash
71
+ pip install code-review-forge[mcp]
72
+ ```
73
+
63
74
  The first command installs the CLI (Python >=3.12). The second copies the
64
75
  6 review skills into `~/.claude/skills/`. Then in Claude Code, run the
65
76
  full pipeline:
@@ -88,15 +99,142 @@ code-forge install-skill --skill code-forge # one skill only
88
99
  code-forge install-skill --force # overwrite existing
89
100
  ```
90
101
 
102
+ ## Getting Started
103
+
104
+ A complete walkthrough from install to your first gated commit.
105
+
106
+ ### 1. Install and initialize
107
+
108
+ ```bash
109
+ pip install code-review-forge
110
+ cd your-repo
111
+ code-forge init
112
+ ```
113
+
114
+ `init` creates `.code-forge/gate.yaml` with commented examples. It does **not**
115
+ configure a backend or a test runner -- both are your responsibility.
116
+
117
+ ### 2. Configure a backend
118
+
119
+ Open `.code-forge/gate.yaml` and uncomment one backend block. For the Anthropic
120
+ API:
121
+
122
+ ```yaml
123
+ backends:
124
+ claude-api:
125
+ type: api
126
+ format: anthropic
127
+ base_url: https://api.anthropic.com
128
+ api_key_env: ANTHROPIC_API_KEY
129
+ default: true
130
+ ```
131
+
132
+ `api_key_env` is the **name** of an environment variable, not the key itself.
133
+ Set the variable in your shell:
134
+
135
+ ```bash
136
+ export ANTHROPIC_API_KEY=sk-ant-...
137
+ ```
138
+
139
+ Then trust the configuration (required once per gate.yaml change):
140
+
141
+ ```bash
142
+ code-forge trust
143
+ ```
144
+
145
+ Review **refuses to run** until at least one backend is configured and trusted.
146
+
147
+ ### 3. Run your first review
148
+
149
+ code-forge requires a git worktree for review isolation. Create one and make a
150
+ change:
151
+
152
+ ```bash
153
+ git worktree add .worktrees/work -b my-feature
154
+ cd .worktrees/work
155
+ # edit some code, then stage it
156
+ git add -A
157
+ code-forge review
158
+ ```
159
+
160
+ The review reads the **staged (index) diff** -- you do not need to commit first.
161
+
162
+ **Simple single-branch repos:** if worktrees are overkill for your workflow,
163
+ bypass the check:
164
+
165
+ ```bash
166
+ code-forge review --allow-main
167
+ # or permanently:
168
+ FORGE_ALLOW_MAIN=1 code-forge review
169
+ ```
170
+
171
+ ### 4. Install the commit gate (optional but recommended)
172
+
173
+ The commit gate runs `code-forge verify` (receipt tamper check) and
174
+ `code-forge gate-check` (test suite) on every code commit. It requires a
175
+ `test` section in gate.yaml:
176
+
177
+ ```yaml
178
+ test:
179
+ command: [pytest, -q]
180
+ timeout_seconds: 900
181
+ ```
182
+
183
+ Then install:
184
+
185
+ ```bash
186
+ code-forge install-hooks
187
+ ```
188
+
189
+ **What this means for your workflow:**
190
+
191
+ - **Code commits** (`.py`, `.go`, `.rs`, etc.) require a passing review first.
192
+ The hook runs `code-forge verify` which checks that a full review has been
193
+ recorded for the staged diff. Without a prior review, the commit is blocked.
194
+ - **Doc/config commits** (`.md`, `.yaml`, `.toml`, `LICENSE`, etc.) skip the
195
+ gate automatically -- no review or `--no-verify` needed.
196
+
197
+ **Bootstrapping a new repo:** if you install hooks before running your first
198
+ review, code commits will be blocked. Either run a successful `code-forge review`
199
+ first, or set `FORGE_ALLOW_NO_BACKEND=1` temporarily to bypass the receipt gate
200
+ while you get your backend working.
201
+
202
+ ### 5. Commit with the gate active
203
+
204
+ ```bash
205
+ # 1. Stage your changes
206
+ git add -A
207
+ # 2. Run a review (must pass before committing code)
208
+ code-forge review
209
+ # 3. Commit -- the pre-commit hook verifies the review receipt
210
+ git commit -m "your message"
211
+ ```
212
+
213
+ If the review found issues, fix them and re-run `code-forge review` until it
214
+ passes. The commit gate checks that the staged diff has a clean review receipt.
215
+
216
+ ### 6. Diagnostics
217
+
218
+ ```bash
219
+ code-forge doctor # check backend reachability, config health
220
+ code-forge verify # check review receipt status
221
+ ```
222
+
91
223
  ## Backend configuration
92
224
 
225
+ Backends can also be set once for all projects in
226
+ `~/.config/code-forge/config.yaml` (override the location with
227
+ `FORGE_CONFIG_DIR`); a backend with the same name in a project's
228
+ `gate.yaml` wins. `code-forge doctor` prints the resolved user-level
229
+ config path every run.
230
+
93
231
  By default, code-forge uses the `claude` CLI in your PATH with the session
94
232
  model (no model pin). Three environment variables control the backend:
95
233
 
96
234
  | Variable | Purpose | Default |
97
235
  |---|---|---|
98
- | `FORGE_BACKEND` | Select a named backend from `backends.yaml` | session-default |
99
- | `FORGE_OUTLET` | Force outlet: `cli` or `inline` | auto-detected |
236
+ | `FORGE_BACKEND` | Select a named backend from `gate.yaml` | session-default |
237
+ | `FORGE_OUTLET` | Force outlet: `subprocess` \| `inline` \| `subagent` | auto-detected |
100
238
  | `FORGE_LLM_MODEL` | Override model for CLI backends | `claude-sonnet-4-6` |
101
239
 
102
240
  **Quick examples:**
@@ -108,29 +246,30 @@ code-forge review
108
246
  # Pin a specific model for this run
109
247
  FORGE_LLM_MODEL=claude-opus-4-5 code-forge review
110
248
 
111
- # Use a named API backend from backends.yaml
249
+ # Use a named API backend from gate.yaml
112
250
  FORGE_BACKEND=claude-api code-forge review
113
251
 
114
- # Force inline outlet (no CLI subprocess)
252
+ # Force inline outlet (no subprocess)
115
253
  FORGE_OUTLET=inline code-forge review
116
254
  ```
117
255
 
118
- **Named backends** (optional) are defined in `~/.config/code-forge/backends.yaml`:
256
+ **Named backends** (optional) are defined in the `backends:` key of
257
+ `.code-forge/gate.yaml` (created by `code-forge init`):
119
258
 
120
259
  ```yaml
121
260
  backends:
122
- - name: claude-api
261
+ claude-api:
123
262
  type: api
124
263
  format: anthropic
125
264
  base_url: https://api.anthropic.com
126
265
  api_key_env: ANTHROPIC_API_KEY
127
266
  default: true
128
- - name: openai
267
+ openai-compatible:
129
268
  type: api
130
269
  format: openai
131
270
  base_url: https://api.openai.com/v1
132
271
  api_key_env: OPENAI_API_KEY
133
- - name: local-claude
272
+ local-claude:
134
273
  type: cli
135
274
  model: claude-opus-4-5
136
275
  command: claude
@@ -139,10 +278,77 @@ backends:
139
278
  Full reference: [docs/configuration.md](docs/configuration.md)
140
279
 
141
280
  Editor setup guides:
281
+ - Claude Code: [docs/setup-claude-code.md](docs/setup-claude-code.md)
142
282
  - VS Code: [docs/setup-vscode.md](docs/setup-vscode.md)
143
283
  - Cursor: [docs/setup-cursor.md](docs/setup-cursor.md)
144
284
  - PyCharm: [docs/setup-pycharm.md](docs/setup-pycharm.md)
145
285
 
286
+ ## MCP server (IDE integration)
287
+
288
+ `code-forge-mcp` is a local stdio MCP server that exposes forge as tools
289
+ callable from any MCP-capable editor (Claude Code, VS Code Copilot, Cursor,
290
+ PyCharm AI Assistant). Reviews route to the configured CN backend -- the
291
+ calling model never reviews its own code.
292
+
293
+ | Tool | Purpose |
294
+ |------|---------|
295
+ | `forge_review` | Review the current git diff (inline if fast, job_id if slow) |
296
+ | `forge_gate_check` | Pre-commit gate on staged changes |
297
+ | `forge_resolve_outlet` | Show which backend forge will use (read-only) |
298
+ | `forge_job_status` | Poll a long-running review by job_id |
299
+ | `forge_init` | Create `.code-forge/` in the workspace |
300
+ | `forge_trust` | Trust the gate.yaml backends |
301
+
302
+ **Prerequisite:** a configured backend with its API key in the server
303
+ environment. Without it, `forge_review` fails closed (same as the CLI).
304
+ One server instance serves one project -- for multi-project setups, use
305
+ per-project `FORGE_PROJECT_DIR` entries (see [docs/setup-mcp.md](docs/setup-mcp.md)).
306
+
307
+ **Claude Code:**
308
+
309
+ ```bash
310
+ claude mcp add forge -- code-forge-mcp
311
+ ```
312
+
313
+ Launch `claude` from the repo root so the server finds `.code-forge/gate.yaml`.
314
+
315
+ **VS Code** (1.102+, `.vscode/mcp.json`):
316
+
317
+ ```json
318
+ {
319
+ "servers": {
320
+ "forge": {
321
+ "type": "stdio",
322
+ "command": "code-forge-mcp",
323
+ "cwd": "${workspaceFolder}"
324
+ }
325
+ }
326
+ }
327
+ ```
328
+
329
+ **Gotcha:** GUI editors do not inherit your shell environment. Either wrap
330
+ `code-forge-mcp` in a script that exports the API key, or set `env` in the
331
+ server config. See [docs/setup-mcp.md](docs/setup-mcp.md) for a `pass`-based
332
+ wrapper example and the per-editor MCP configs.
333
+
334
+ **Verify:** call `forge_resolve_outlet` -- it should name a backend, not
335
+ "key not set". Then call `forge_review` on a real diff.
336
+
337
+ ### Troubleshooting: stale server processes
338
+
339
+ If old `code-forge-mcp` processes accumulate (visible as high memory or
340
+ multiple PIDs), clean them up manually:
341
+
342
+ ```bash
343
+ pgrep -af code-forge-mcp # list survivors
344
+ pkill -TERM -f code-forge-mcp # graceful shutdown
345
+ sleep 3
346
+ pkill -KILL -f code-forge-mcp # force-kill any that remain
347
+ ```
348
+
349
+ After a server restart, job IDs from the previous instance become invalid.
350
+ Completed reviews leave receipts under `.code-forge/` regardless.
351
+
146
352
  ## The pipeline
147
353
 
148
354
  ```
@@ -210,6 +416,24 @@ Code Change
210
416
  components mapping raises an uncertain finding when a hub and a
211
417
  dependent both change in the same diff and no integration test under
212
418
  the dependent's paths matches the configured test patterns.
419
+ - **Execution before the verdict.** The reviewed diff is run, not just
420
+ read. A declared environment is verified against its lockfile by
421
+ sha256; the run happens in a disposable directory so the reviewed tree
422
+ stays read-only; a timeout kills the whole descendant process group.
423
+ The evidence is asymmetric on purpose -- a test failing before the fix
424
+ is a verdict input, a test passing after it is recorded but cannot
425
+ confirm a finding. When the environment cannot be grounded, the report
426
+ says so instead of reasoning against a version the build never used.
427
+ - **Large diffs do not silently review as clean.** Past a token budget a
428
+ diff is split along def-use lines and each group reviewed separately,
429
+ with the shared prompt prefix placed ahead of the per-pass role
430
+ sentence so the backend can cache it. Measured on a 14-file diff that
431
+ previously lost all three passes to truncation and returned zero
432
+ findings: 15/15 passes completed, 16-22 findings per cycle, billed
433
+ input per pass down from 65,748 to 21,987 tokens. Under-budget diffs
434
+ keep the byte-identical single-pass path. A reply truncated inside its
435
+ own reasoning is salvaged only where the verdict is already complete,
436
+ never into a clean round.
213
437
 
214
438
  ## Honest limitations
215
439
 
@@ -239,6 +463,7 @@ passes count.
239
463
  - Python 3.12 or newer
240
464
  - `jq` for the bash smoke primitives
241
465
  - Claude Code or a compatible AI coding assistant for skill invocation
466
+ - `mcp` Python package (optional, for `code-forge-mcp`): `pip install code-review-forge[mcp]`
242
467
 
243
468
  ## Installation alternatives
244
469
 
@@ -261,6 +486,9 @@ do not set up enforcement. The R1 pre-commit gate -- the un-fakeable layer that
261
486
  runs the test suite on every commit and blocks on new failures, regardless of
262
487
  what the in-editor review claims -- is a separate, manual step:
263
488
 
489
+ For running this gate in CI rather than as a local hook, see
490
+ [docs/setup-ci.md](docs/setup-ci.md).
491
+
264
492
  1. Add a `test:` section to `.code-forge/gate.yaml`. Without it, `gate-check`
265
493
  exits with `gate.yaml must have a 'test' section`:
266
494
 
@@ -1,7 +1,7 @@
1
1
  # code-forge
2
2
 
3
- [![PyPI version](https://img.shields.io/pypi/v/code-review-forge.svg)](https://pypi.org/project/code-review-forge/)
4
- [![Python](https://img.shields.io/pypi/pyversions/code-review-forge.svg)](https://pypi.org/project/code-review-forge/)
3
+ [![PyPI version](https://img.shields.io/pypi/v/code-review-forge.svg?cacheSeconds=300)](https://pypi.org/project/code-review-forge/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/code-review-forge.svg?cacheSeconds=300)](https://pypi.org/project/code-review-forge/)
5
5
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/HouMinXi/forge/blob/main/LICENSE)
6
6
 
7
7
  A 5-step code review pipeline for AI coding assistants. Treats review as a
@@ -32,6 +32,12 @@ pip install code-review-forge
32
32
  code-forge install-skill
33
33
  ```
34
34
 
35
+ For MCP server support (IDE integration):
36
+
37
+ ```bash
38
+ pip install code-review-forge[mcp]
39
+ ```
40
+
35
41
  The first command installs the CLI (Python >=3.12). The second copies the
36
42
  6 review skills into `~/.claude/skills/`. Then in Claude Code, run the
37
43
  full pipeline:
@@ -60,15 +66,142 @@ code-forge install-skill --skill code-forge # one skill only
60
66
  code-forge install-skill --force # overwrite existing
61
67
  ```
62
68
 
69
+ ## Getting Started
70
+
71
+ A complete walkthrough from install to your first gated commit.
72
+
73
+ ### 1. Install and initialize
74
+
75
+ ```bash
76
+ pip install code-review-forge
77
+ cd your-repo
78
+ code-forge init
79
+ ```
80
+
81
+ `init` creates `.code-forge/gate.yaml` with commented examples. It does **not**
82
+ configure a backend or a test runner -- both are your responsibility.
83
+
84
+ ### 2. Configure a backend
85
+
86
+ Open `.code-forge/gate.yaml` and uncomment one backend block. For the Anthropic
87
+ API:
88
+
89
+ ```yaml
90
+ backends:
91
+ claude-api:
92
+ type: api
93
+ format: anthropic
94
+ base_url: https://api.anthropic.com
95
+ api_key_env: ANTHROPIC_API_KEY
96
+ default: true
97
+ ```
98
+
99
+ `api_key_env` is the **name** of an environment variable, not the key itself.
100
+ Set the variable in your shell:
101
+
102
+ ```bash
103
+ export ANTHROPIC_API_KEY=sk-ant-...
104
+ ```
105
+
106
+ Then trust the configuration (required once per gate.yaml change):
107
+
108
+ ```bash
109
+ code-forge trust
110
+ ```
111
+
112
+ Review **refuses to run** until at least one backend is configured and trusted.
113
+
114
+ ### 3. Run your first review
115
+
116
+ code-forge requires a git worktree for review isolation. Create one and make a
117
+ change:
118
+
119
+ ```bash
120
+ git worktree add .worktrees/work -b my-feature
121
+ cd .worktrees/work
122
+ # edit some code, then stage it
123
+ git add -A
124
+ code-forge review
125
+ ```
126
+
127
+ The review reads the **staged (index) diff** -- you do not need to commit first.
128
+
129
+ **Simple single-branch repos:** if worktrees are overkill for your workflow,
130
+ bypass the check:
131
+
132
+ ```bash
133
+ code-forge review --allow-main
134
+ # or permanently:
135
+ FORGE_ALLOW_MAIN=1 code-forge review
136
+ ```
137
+
138
+ ### 4. Install the commit gate (optional but recommended)
139
+
140
+ The commit gate runs `code-forge verify` (receipt tamper check) and
141
+ `code-forge gate-check` (test suite) on every code commit. It requires a
142
+ `test` section in gate.yaml:
143
+
144
+ ```yaml
145
+ test:
146
+ command: [pytest, -q]
147
+ timeout_seconds: 900
148
+ ```
149
+
150
+ Then install:
151
+
152
+ ```bash
153
+ code-forge install-hooks
154
+ ```
155
+
156
+ **What this means for your workflow:**
157
+
158
+ - **Code commits** (`.py`, `.go`, `.rs`, etc.) require a passing review first.
159
+ The hook runs `code-forge verify` which checks that a full review has been
160
+ recorded for the staged diff. Without a prior review, the commit is blocked.
161
+ - **Doc/config commits** (`.md`, `.yaml`, `.toml`, `LICENSE`, etc.) skip the
162
+ gate automatically -- no review or `--no-verify` needed.
163
+
164
+ **Bootstrapping a new repo:** if you install hooks before running your first
165
+ review, code commits will be blocked. Either run a successful `code-forge review`
166
+ first, or set `FORGE_ALLOW_NO_BACKEND=1` temporarily to bypass the receipt gate
167
+ while you get your backend working.
168
+
169
+ ### 5. Commit with the gate active
170
+
171
+ ```bash
172
+ # 1. Stage your changes
173
+ git add -A
174
+ # 2. Run a review (must pass before committing code)
175
+ code-forge review
176
+ # 3. Commit -- the pre-commit hook verifies the review receipt
177
+ git commit -m "your message"
178
+ ```
179
+
180
+ If the review found issues, fix them and re-run `code-forge review` until it
181
+ passes. The commit gate checks that the staged diff has a clean review receipt.
182
+
183
+ ### 6. Diagnostics
184
+
185
+ ```bash
186
+ code-forge doctor # check backend reachability, config health
187
+ code-forge verify # check review receipt status
188
+ ```
189
+
63
190
  ## Backend configuration
64
191
 
192
+ Backends can also be set once for all projects in
193
+ `~/.config/code-forge/config.yaml` (override the location with
194
+ `FORGE_CONFIG_DIR`); a backend with the same name in a project's
195
+ `gate.yaml` wins. `code-forge doctor` prints the resolved user-level
196
+ config path every run.
197
+
65
198
  By default, code-forge uses the `claude` CLI in your PATH with the session
66
199
  model (no model pin). Three environment variables control the backend:
67
200
 
68
201
  | Variable | Purpose | Default |
69
202
  |---|---|---|
70
- | `FORGE_BACKEND` | Select a named backend from `backends.yaml` | session-default |
71
- | `FORGE_OUTLET` | Force outlet: `cli` or `inline` | auto-detected |
203
+ | `FORGE_BACKEND` | Select a named backend from `gate.yaml` | session-default |
204
+ | `FORGE_OUTLET` | Force outlet: `subprocess` \| `inline` \| `subagent` | auto-detected |
72
205
  | `FORGE_LLM_MODEL` | Override model for CLI backends | `claude-sonnet-4-6` |
73
206
 
74
207
  **Quick examples:**
@@ -80,29 +213,30 @@ code-forge review
80
213
  # Pin a specific model for this run
81
214
  FORGE_LLM_MODEL=claude-opus-4-5 code-forge review
82
215
 
83
- # Use a named API backend from backends.yaml
216
+ # Use a named API backend from gate.yaml
84
217
  FORGE_BACKEND=claude-api code-forge review
85
218
 
86
- # Force inline outlet (no CLI subprocess)
219
+ # Force inline outlet (no subprocess)
87
220
  FORGE_OUTLET=inline code-forge review
88
221
  ```
89
222
 
90
- **Named backends** (optional) are defined in `~/.config/code-forge/backends.yaml`:
223
+ **Named backends** (optional) are defined in the `backends:` key of
224
+ `.code-forge/gate.yaml` (created by `code-forge init`):
91
225
 
92
226
  ```yaml
93
227
  backends:
94
- - name: claude-api
228
+ claude-api:
95
229
  type: api
96
230
  format: anthropic
97
231
  base_url: https://api.anthropic.com
98
232
  api_key_env: ANTHROPIC_API_KEY
99
233
  default: true
100
- - name: openai
234
+ openai-compatible:
101
235
  type: api
102
236
  format: openai
103
237
  base_url: https://api.openai.com/v1
104
238
  api_key_env: OPENAI_API_KEY
105
- - name: local-claude
239
+ local-claude:
106
240
  type: cli
107
241
  model: claude-opus-4-5
108
242
  command: claude
@@ -111,10 +245,77 @@ backends:
111
245
  Full reference: [docs/configuration.md](docs/configuration.md)
112
246
 
113
247
  Editor setup guides:
248
+ - Claude Code: [docs/setup-claude-code.md](docs/setup-claude-code.md)
114
249
  - VS Code: [docs/setup-vscode.md](docs/setup-vscode.md)
115
250
  - Cursor: [docs/setup-cursor.md](docs/setup-cursor.md)
116
251
  - PyCharm: [docs/setup-pycharm.md](docs/setup-pycharm.md)
117
252
 
253
+ ## MCP server (IDE integration)
254
+
255
+ `code-forge-mcp` is a local stdio MCP server that exposes forge as tools
256
+ callable from any MCP-capable editor (Claude Code, VS Code Copilot, Cursor,
257
+ PyCharm AI Assistant). Reviews route to the configured CN backend -- the
258
+ calling model never reviews its own code.
259
+
260
+ | Tool | Purpose |
261
+ |------|---------|
262
+ | `forge_review` | Review the current git diff (inline if fast, job_id if slow) |
263
+ | `forge_gate_check` | Pre-commit gate on staged changes |
264
+ | `forge_resolve_outlet` | Show which backend forge will use (read-only) |
265
+ | `forge_job_status` | Poll a long-running review by job_id |
266
+ | `forge_init` | Create `.code-forge/` in the workspace |
267
+ | `forge_trust` | Trust the gate.yaml backends |
268
+
269
+ **Prerequisite:** a configured backend with its API key in the server
270
+ environment. Without it, `forge_review` fails closed (same as the CLI).
271
+ One server instance serves one project -- for multi-project setups, use
272
+ per-project `FORGE_PROJECT_DIR` entries (see [docs/setup-mcp.md](docs/setup-mcp.md)).
273
+
274
+ **Claude Code:**
275
+
276
+ ```bash
277
+ claude mcp add forge -- code-forge-mcp
278
+ ```
279
+
280
+ Launch `claude` from the repo root so the server finds `.code-forge/gate.yaml`.
281
+
282
+ **VS Code** (1.102+, `.vscode/mcp.json`):
283
+
284
+ ```json
285
+ {
286
+ "servers": {
287
+ "forge": {
288
+ "type": "stdio",
289
+ "command": "code-forge-mcp",
290
+ "cwd": "${workspaceFolder}"
291
+ }
292
+ }
293
+ }
294
+ ```
295
+
296
+ **Gotcha:** GUI editors do not inherit your shell environment. Either wrap
297
+ `code-forge-mcp` in a script that exports the API key, or set `env` in the
298
+ server config. See [docs/setup-mcp.md](docs/setup-mcp.md) for a `pass`-based
299
+ wrapper example and the per-editor MCP configs.
300
+
301
+ **Verify:** call `forge_resolve_outlet` -- it should name a backend, not
302
+ "key not set". Then call `forge_review` on a real diff.
303
+
304
+ ### Troubleshooting: stale server processes
305
+
306
+ If old `code-forge-mcp` processes accumulate (visible as high memory or
307
+ multiple PIDs), clean them up manually:
308
+
309
+ ```bash
310
+ pgrep -af code-forge-mcp # list survivors
311
+ pkill -TERM -f code-forge-mcp # graceful shutdown
312
+ sleep 3
313
+ pkill -KILL -f code-forge-mcp # force-kill any that remain
314
+ ```
315
+
316
+ After a server restart, job IDs from the previous instance become invalid.
317
+ Completed reviews leave receipts under `.code-forge/` regardless.
318
+
118
319
  ## The pipeline
119
320
 
120
321
  ```
@@ -182,6 +383,24 @@ Code Change
182
383
  components mapping raises an uncertain finding when a hub and a
183
384
  dependent both change in the same diff and no integration test under
184
385
  the dependent's paths matches the configured test patterns.
386
+ - **Execution before the verdict.** The reviewed diff is run, not just
387
+ read. A declared environment is verified against its lockfile by
388
+ sha256; the run happens in a disposable directory so the reviewed tree
389
+ stays read-only; a timeout kills the whole descendant process group.
390
+ The evidence is asymmetric on purpose -- a test failing before the fix
391
+ is a verdict input, a test passing after it is recorded but cannot
392
+ confirm a finding. When the environment cannot be grounded, the report
393
+ says so instead of reasoning against a version the build never used.
394
+ - **Large diffs do not silently review as clean.** Past a token budget a
395
+ diff is split along def-use lines and each group reviewed separately,
396
+ with the shared prompt prefix placed ahead of the per-pass role
397
+ sentence so the backend can cache it. Measured on a 14-file diff that
398
+ previously lost all three passes to truncation and returned zero
399
+ findings: 15/15 passes completed, 16-22 findings per cycle, billed
400
+ input per pass down from 65,748 to 21,987 tokens. Under-budget diffs
401
+ keep the byte-identical single-pass path. A reply truncated inside its
402
+ own reasoning is salvaged only where the verdict is already complete,
403
+ never into a clean round.
185
404
 
186
405
  ## Honest limitations
187
406
 
@@ -211,6 +430,7 @@ passes count.
211
430
  - Python 3.12 or newer
212
431
  - `jq` for the bash smoke primitives
213
432
  - Claude Code or a compatible AI coding assistant for skill invocation
433
+ - `mcp` Python package (optional, for `code-forge-mcp`): `pip install code-review-forge[mcp]`
214
434
 
215
435
  ## Installation alternatives
216
436
 
@@ -233,6 +453,9 @@ do not set up enforcement. The R1 pre-commit gate -- the un-fakeable layer that
233
453
  runs the test suite on every commit and blocks on new failures, regardless of
234
454
  what the in-editor review claims -- is a separate, manual step:
235
455
 
456
+ For running this gate in CI rather than as a local hook, see
457
+ [docs/setup-ci.md](docs/setup-ci.md).
458
+
236
459
  1. Add a `test:` section to `.code-forge/gate.yaml`. Without it, `gate-check`
237
460
  exits with `gate.yaml must have a 'test' section`:
238
461