code-review-forge 2.1.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 (321) hide show
  1. code_review_forge-2.9.0/PKG-INFO +577 -0
  2. code_review_forge-2.9.0/README.md +544 -0
  3. code_review_forge-2.9.0/pyproject.toml +71 -0
  4. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/__init__.py +3 -1
  5. {code_review_forge-2.1.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.1.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.1.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.9.0/src/code_forge/conventions.py +155 -0
  17. code_review_forge-2.9.0/src/code_forge/conventions_resolver.py +808 -0
  18. code_review_forge-2.9.0/src/code_forge/coverage.py +173 -0
  19. code_review_forge-2.9.0/src/code_forge/cross_repo.py +449 -0
  20. code_review_forge-2.9.0/src/code_forge/cross_repo_impact.py +342 -0
  21. code_review_forge-2.9.0/src/code_forge/daemon_state.py +497 -0
  22. code_review_forge-2.9.0/src/code_forge/dead_code.py +328 -0
  23. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/delta.py +21 -3
  24. code_review_forge-2.9.0/src/code_forge/detect.py +652 -0
  25. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/diagnose.py +12 -0
  26. code_review_forge-2.9.0/src/code_forge/diff.py +499 -0
  27. code_review_forge-2.9.0/src/code_forge/diff_grouping.py +469 -0
  28. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/disposition.py +4 -0
  29. code_review_forge-2.9.0/src/code_forge/doctor.py +571 -0
  30. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/e2e_check.py +30 -6
  31. code_review_forge-2.9.0/src/code_forge/errors.py +62 -0
  32. code_review_forge-2.9.0/src/code_forge/eval/__init__.py +1 -0
  33. code_review_forge-2.9.0/src/code_forge/eval/corpus.py +196 -0
  34. code_review_forge-2.9.0/src/code_forge/eval/export.py +608 -0
  35. code_review_forge-2.9.0/src/code_forge/eval/runner.py +781 -0
  36. code_review_forge-2.9.0/src/code_forge/eval/scorer.py +472 -0
  37. code_review_forge-2.9.0/src/code_forge/evidence.py +67 -0
  38. code_review_forge-2.9.0/src/code_forge/exec_falsify.py +426 -0
  39. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/exit_codes.py +8 -1
  40. code_review_forge-2.9.0/src/code_forge/factories.py +852 -0
  41. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/falsify.py +1 -1
  42. code_review_forge-2.9.0/src/code_forge/falsify_real.py +70 -0
  43. code_review_forge-2.9.0/src/code_forge/findings.py +24 -0
  44. code_review_forge-2.9.0/src/code_forge/fixval.py +576 -0
  45. code_review_forge-2.9.0/src/code_forge/flow_contract.py +33 -0
  46. code_review_forge-2.9.0/src/code_forge/gate.schema.json +430 -0
  47. code_review_forge-2.9.0/src/code_forge/gate_check.py +1181 -0
  48. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/git.py +129 -11
  49. code_review_forge-2.9.0/src/code_forge/graph_triage.py +615 -0
  50. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/hold.py +5 -2
  51. code_review_forge-2.9.0/src/code_forge/init_template.py +217 -0
  52. code_review_forge-2.9.0/src/code_forge/install_hooks.py +947 -0
  53. code_review_forge-2.9.0/src/code_forge/ledger.py +210 -0
  54. code_review_forge-2.9.0/src/code_forge/legacy.py +273 -0
  55. code_review_forge-2.9.0/src/code_forge/llm_invoke.py +2282 -0
  56. code_review_forge-2.9.0/src/code_forge/lock.py +455 -0
  57. code_review_forge-2.9.0/src/code_forge/machine.py +2182 -0
  58. code_review_forge-2.9.0/src/code_forge/manifest.py +382 -0
  59. code_review_forge-2.9.0/src/code_forge/mcp_jobs.py +350 -0
  60. code_review_forge-2.9.0/src/code_forge/mcp_server.py +1472 -0
  61. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/mutation.py +298 -51
  62. code_review_forge-2.9.0/src/code_forge/outlet_c.py +225 -0
  63. code_review_forge-2.9.0/src/code_forge/outlet_resolver.py +271 -0
  64. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/__init__.py +17 -4
  65. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/_sarif.py +22 -10
  66. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/base.py +1 -18
  67. code_review_forge-2.9.0/src/code_forge/parsers/eslint.py +64 -0
  68. code_review_forge-2.9.0/src/code_forge/parsers/flake8.py +74 -0
  69. code_review_forge-2.9.0/src/code_forge/parsers/pylint.py +108 -0
  70. code_review_forge-2.9.0/src/code_forge/proc.py +120 -0
  71. code_review_forge-2.9.0/src/code_forge/progress.py +72 -0
  72. code_review_forge-2.9.0/src/code_forge/receipt.py +278 -0
  73. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/registry.py +11 -14
  74. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/reporter.py +1 -1
  75. code_review_forge-2.9.0/src/code_forge/reviewer_json.py +191 -0
  76. code_review_forge-2.9.0/src/code_forge/rulepack.py +620 -0
  77. code_review_forge-2.9.0/src/code_forge/rules/forge-taint.yaml +60 -0
  78. code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/meta.yaml +45 -0
  79. code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/rules.yaml +55 -0
  80. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/runner.py +39 -16
  81. code_review_forge-2.9.0/src/code_forge/runtime.py +386 -0
  82. code_review_forge-2.9.0/src/code_forge/sarif.py +381 -0
  83. code_review_forge-2.9.0/src/code_forge/setup_mcp.py +269 -0
  84. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/SKILL.md +614 -63
  85. code_review_forge-2.9.0/src/code_forge/skills/code-forge/passes/pass1-qodo.md +115 -0
  86. code_review_forge-2.9.0/src/code_forge/skills/code-forge/passes/pass2-expert.md +123 -0
  87. code_review_forge-2.9.0/src/code_forge/skills/code-forge/passes/pass3-adversarial.md +166 -0
  88. code_review_forge-2.9.0/src/code_forge/skills/code-review-expert/references/code-quality-checklist.md +130 -0
  89. code_review_forge-2.9.0/src/code_forge/skills/code-review-expert/references/removal-plan.md +52 -0
  90. code_review_forge-2.9.0/src/code_forge/skills/code-review-expert/references/security-checklist.md +118 -0
  91. code_review_forge-2.9.0/src/code_forge/skills/code-review-expert/references/solid-checklist.md +65 -0
  92. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/SKILL.md +43 -0
  93. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/snapshot.py +2 -2
  94. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/state.py +135 -4
  95. code_review_forge-2.9.0/src/code_forge/taint.py +283 -0
  96. code_review_forge-2.9.0/src/code_forge/trust.py +369 -0
  97. code_review_forge-2.9.0/src/code_forge/user_config.py +111 -0
  98. code_review_forge-2.9.0/src/code_forge/verify.py +904 -0
  99. code_review_forge-2.9.0/src/code_forge/workspace.py +51 -0
  100. code_review_forge-2.9.0/src/code_review_forge.egg-info/PKG-INFO +577 -0
  101. code_review_forge-2.9.0/src/code_review_forge.egg-info/SOURCES.txt +296 -0
  102. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/entry_points.txt +1 -0
  103. code_review_forge-2.9.0/src/code_review_forge.egg-info/requires.txt +17 -0
  104. code_review_forge-2.9.0/tests/test_advisory.py +304 -0
  105. code_review_forge-2.9.0/tests/test_backend.py +2156 -0
  106. code_review_forge-2.9.0/tests/test_backend_attribution.py +123 -0
  107. code_review_forge-2.9.0/tests/test_basis.py +224 -0
  108. code_review_forge-2.9.0/tests/test_canary.py +218 -0
  109. code_review_forge-2.9.0/tests/test_canary_cli.py +431 -0
  110. code_review_forge-2.9.0/tests/test_canary_gen.py +510 -0
  111. code_review_forge-2.9.0/tests/test_canary_smoke.py +394 -0
  112. code_review_forge-2.9.0/tests/test_chunking.py +278 -0
  113. code_review_forge-2.9.0/tests/test_claim_type.py +226 -0
  114. code_review_forge-2.9.0/tests/test_cli_advisory_wiring.py +117 -0
  115. code_review_forge-2.9.0/tests/test_cli_backend_propagation.py +39 -0
  116. code_review_forge-2.9.0/tests/test_cli_banner.py +349 -0
  117. code_review_forge-2.9.0/tests/test_cli_detect.py +224 -0
  118. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_e2e_check.py +162 -2
  119. code_review_forge-2.9.0/tests/test_cli_empty_diff.py +115 -0
  120. code_review_forge-2.9.0/tests/test_cli_entrypoint.py +44 -0
  121. code_review_forge-2.9.0/tests/test_cli_eval.py +929 -0
  122. code_review_forge-2.9.0/tests/test_cli_grouping_wiring.py +52 -0
  123. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_hold_resume.py +69 -9
  124. code_review_forge-2.9.0/tests/test_cli_init.py +60 -0
  125. code_review_forge-2.9.0/tests/test_cli_integration.py +1282 -0
  126. code_review_forge-2.9.0/tests/test_cli_internal_error.py +69 -0
  127. code_review_forge-2.9.0/tests/test_cli_l2_wiring.py +78 -0
  128. code_review_forge-2.9.0/tests/test_cli_ledger.py +770 -0
  129. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_lock.py +12 -2
  130. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_parser.py +169 -6
  131. code_review_forge-2.9.0/tests/test_cli_pending_exit.py +25 -0
  132. code_review_forge-2.9.0/tests/test_cli_phase1_compat.py +38 -0
  133. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_sarif.py +112 -14
  134. code_review_forge-2.9.0/tests/test_cli_trust.py +466 -0
  135. code_review_forge-2.9.0/tests/test_cli_verify_required_cycles.py +179 -0
  136. code_review_forge-2.9.0/tests/test_consecutive_clean.py +175 -0
  137. code_review_forge-2.9.0/tests/test_contract_flag.py +611 -0
  138. code_review_forge-2.9.0/tests/test_contract_loader.py +719 -0
  139. code_review_forge-2.9.0/tests/test_contract_wiring.py +415 -0
  140. code_review_forge-2.9.0/tests/test_conventions.py +151 -0
  141. code_review_forge-2.9.0/tests/test_conventions_resolver.py +548 -0
  142. code_review_forge-2.9.0/tests/test_coverage.py +171 -0
  143. code_review_forge-2.9.0/tests/test_cross_repo.py +1241 -0
  144. code_review_forge-2.9.0/tests/test_cross_repo_contracts.py +549 -0
  145. code_review_forge-2.9.0/tests/test_cross_repo_impact.py +604 -0
  146. code_review_forge-2.9.0/tests/test_cross_repo_impact_integration.py +568 -0
  147. code_review_forge-2.9.0/tests/test_daemon_state.py +730 -0
  148. code_review_forge-2.9.0/tests/test_daemon_state_drift.py +52 -0
  149. code_review_forge-2.9.0/tests/test_dead_code.py +697 -0
  150. code_review_forge-2.9.0/tests/test_detect.py +776 -0
  151. code_review_forge-2.9.0/tests/test_detect_c.py +88 -0
  152. code_review_forge-2.9.0/tests/test_detect_cpp.py +88 -0
  153. code_review_forge-2.9.0/tests/test_detect_java.py +96 -0
  154. code_review_forge-2.9.0/tests/test_detect_js.py +96 -0
  155. code_review_forge-2.9.0/tests/test_diff.py +898 -0
  156. code_review_forge-2.9.0/tests/test_diff_grouping.py +478 -0
  157. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_disposition.py +3 -3
  158. code_review_forge-2.9.0/tests/test_doctor.py +805 -0
  159. code_review_forge-2.9.0/tests/test_doctor_tool_audit.py +224 -0
  160. code_review_forge-2.9.0/tests/test_dogfood.py +372 -0
  161. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_e2e_check.py +25 -0
  162. code_review_forge-2.9.0/tests/test_encoding_conformance.py +190 -0
  163. code_review_forge-2.9.0/tests/test_eval_corpus.py +177 -0
  164. code_review_forge-2.9.0/tests/test_eval_corpus_findings.py +823 -0
  165. code_review_forge-2.9.0/tests/test_eval_runner.py +557 -0
  166. code_review_forge-2.9.0/tests/test_eval_scorer.py +227 -0
  167. code_review_forge-2.9.0/tests/test_evidence.py +91 -0
  168. code_review_forge-2.9.0/tests/test_exec_falsify.py +603 -0
  169. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_exit_codes.py +35 -4
  170. code_review_forge-2.9.0/tests/test_export_eval.py +1118 -0
  171. code_review_forge-2.9.0/tests/test_f3_legacy_exit.py +311 -0
  172. code_review_forge-2.9.0/tests/test_factories.py +1549 -0
  173. code_review_forge-2.9.0/tests/test_falsify_real.py +317 -0
  174. code_review_forge-2.9.0/tests/test_fast_fail.py +378 -0
  175. code_review_forge-2.9.0/tests/test_findings.py +28 -0
  176. code_review_forge-2.9.0/tests/test_fixval.py +734 -0
  177. code_review_forge-2.9.0/tests/test_fixval_integration.py +490 -0
  178. code_review_forge-2.9.0/tests/test_flow_contract_drift.py +90 -0
  179. code_review_forge-2.9.0/tests/test_focus.py +224 -0
  180. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_gate_check.py +689 -4
  181. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_git.py +181 -1
  182. code_review_forge-2.9.0/tests/test_graph_triage.py +644 -0
  183. code_review_forge-2.9.0/tests/test_hook_carveout.py +528 -0
  184. code_review_forge-2.9.0/tests/test_hook_failclosed.py +115 -0
  185. code_review_forge-2.9.0/tests/test_infra_convergence.py +228 -0
  186. code_review_forge-2.9.0/tests/test_inline_delegated.py +69 -0
  187. code_review_forge-2.9.0/tests/test_install_hooks.py +1380 -0
  188. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_integration.py +25 -5
  189. code_review_forge-2.9.0/tests/test_ledger.py +341 -0
  190. code_review_forge-2.9.0/tests/test_legacy.py +498 -0
  191. code_review_forge-2.9.0/tests/test_legacy_integration.py +275 -0
  192. code_review_forge-2.9.0/tests/test_llm_invoke.py +5825 -0
  193. code_review_forge-2.9.0/tests/test_lock.py +802 -0
  194. code_review_forge-2.9.0/tests/test_machine_advisory.py +174 -0
  195. code_review_forge-2.9.0/tests/test_machine_ci.py +228 -0
  196. code_review_forge-2.9.0/tests/test_machine_coverage.py +208 -0
  197. code_review_forge-2.9.0/tests/test_machine_l0_crash_guard.py +93 -0
  198. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_machine_l2.py +277 -3
  199. code_review_forge-2.9.0/tests/test_machine_ledger.py +875 -0
  200. code_review_forge-2.9.0/tests/test_machine_local.py +902 -0
  201. code_review_forge-2.9.0/tests/test_machine_mutation_launch.py +367 -0
  202. code_review_forge-2.9.0/tests/test_manifest.py +266 -0
  203. code_review_forge-2.9.0/tests/test_mcp_jobs.py +1068 -0
  204. code_review_forge-2.9.0/tests/test_mcp_pdeathsig.py +194 -0
  205. code_review_forge-2.9.0/tests/test_mcp_server.py +3101 -0
  206. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_mutation.py +290 -0
  207. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_ordering.py +4 -3
  208. code_review_forge-2.9.0/tests/test_outlet_c.py +597 -0
  209. code_review_forge-2.9.0/tests/test_outlet_c_cli.py +466 -0
  210. code_review_forge-2.9.0/tests/test_outlet_resolver.py +780 -0
  211. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_parsers.py +216 -6
  212. code_review_forge-2.9.0/tests/test_post_image_window.py +302 -0
  213. code_review_forge-2.9.0/tests/test_progress.py +55 -0
  214. code_review_forge-2.9.0/tests/test_r1_e2e.py +158 -0
  215. code_review_forge-2.9.0/tests/test_realpath_ledger.py +116 -0
  216. code_review_forge-2.9.0/tests/test_receipt.py +502 -0
  217. code_review_forge-2.9.0/tests/test_receipt_partial.py +285 -0
  218. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_registry.py +47 -12
  219. code_review_forge-2.9.0/tests/test_reviewer_json.py +119 -0
  220. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_round.py +14 -7
  221. code_review_forge-2.9.0/tests/test_rulepack_blocking.py +143 -0
  222. code_review_forge-2.9.0/tests/test_rulepack_loader.py +224 -0
  223. code_review_forge-2.9.0/tests/test_rulepack_matrix.py +110 -0
  224. code_review_forge-2.9.0/tests/test_rulepack_runner.py +241 -0
  225. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_runner.py +8 -6
  226. code_review_forge-2.9.0/tests/test_runtime.py +809 -0
  227. code_review_forge-2.9.0/tests/test_runtime_drift.py +48 -0
  228. code_review_forge-2.9.0/tests/test_runtime_eval.py +769 -0
  229. code_review_forge-2.9.0/tests/test_runtime_machine.py +343 -0
  230. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_sarif.py +297 -24
  231. code_review_forge-2.9.0/tests/test_schema_corpus.py +867 -0
  232. code_review_forge-2.9.0/tests/test_setup_mcp.py +270 -0
  233. code_review_forge-2.9.0/tests/test_smoke_receipt.py +436 -0
  234. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_state_schema.py +30 -2
  235. code_review_forge-2.9.0/tests/test_taint.py +475 -0
  236. code_review_forge-2.9.0/tests/test_taint_integration.py +202 -0
  237. code_review_forge-2.9.0/tests/test_taint_rule.py +210 -0
  238. code_review_forge-2.9.0/tests/test_trust.py +332 -0
  239. code_review_forge-2.9.0/tests/test_trust_empty_backends.py +84 -0
  240. code_review_forge-2.9.0/tests/test_user_config.py +313 -0
  241. code_review_forge-2.9.0/tests/test_verify.py +2270 -0
  242. code_review_forge-2.1.0/PKG-INFO +0 -237
  243. code_review_forge-2.1.0/README.md +0 -221
  244. code_review_forge-2.1.0/pyproject.toml +0 -36
  245. code_review_forge-2.1.0/src/code_forge/cli.py +0 -983
  246. code_review_forge-2.1.0/src/code_forge/diff.py +0 -82
  247. code_review_forge-2.1.0/src/code_forge/errors.py +0 -34
  248. code_review_forge-2.1.0/src/code_forge/factories.py +0 -191
  249. code_review_forge-2.1.0/src/code_forge/gate_check.py +0 -466
  250. code_review_forge-2.1.0/src/code_forge/install_hooks.py +0 -331
  251. code_review_forge-2.1.0/src/code_forge/lock.py +0 -162
  252. code_review_forge-2.1.0/src/code_forge/machine.py +0 -792
  253. code_review_forge-2.1.0/src/code_forge/sarif.py +0 -226
  254. code_review_forge-2.1.0/src/code_review_forge.egg-info/PKG-INFO +0 -237
  255. code_review_forge-2.1.0/src/code_review_forge.egg-info/SOURCES.txt +0 -122
  256. code_review_forge-2.1.0/src/code_review_forge.egg-info/requires.txt +0 -6
  257. code_review_forge-2.1.0/tests/test_cli_integration.py +0 -184
  258. code_review_forge-2.1.0/tests/test_cli_phase1_compat.py +0 -179
  259. code_review_forge-2.1.0/tests/test_diff.py +0 -175
  260. code_review_forge-2.1.0/tests/test_factories.py +0 -243
  261. code_review_forge-2.1.0/tests/test_install_hooks.py +0 -597
  262. code_review_forge-2.1.0/tests/test_lock.py +0 -174
  263. code_review_forge-2.1.0/tests/test_machine_ci.py +0 -133
  264. code_review_forge-2.1.0/tests/test_machine_local.py +0 -230
  265. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/LICENSE +0 -0
  266. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/MANIFEST.in +0 -0
  267. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/setup.cfg +0 -0
  268. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/env_resolver.py +0 -0
  269. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/mode_resolver.py +0 -0
  270. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/checkpatch.py +0 -0
  271. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/clippy.py +0 -0
  272. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/non_ascii.py +0 -0
  273. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/ruff.py +0 -0
  274. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/semgrep.py +0 -0
  275. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/parsers/shellcheck.py +0 -0
  276. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/adversarial-qe/SKILL.md +0 -0
  277. {code_review_forge-2.1.0/src/code_forge/skills/code-review-expert → code_review_forge-2.9.0/src/code_forge/skills/code-forge}/references/code-quality-checklist.md +0 -0
  278. {code_review_forge-2.1.0/src/code_forge/skills/code-review-expert → code_review_forge-2.9.0/src/code_forge/skills/code-forge}/references/removal-plan.md +0 -0
  279. {code_review_forge-2.1.0/src/code_forge/skills/code-review-expert → code_review_forge-2.9.0/src/code_forge/skills/code-forge}/references/security-checklist.md +0 -0
  280. {code_review_forge-2.1.0/src/code_forge/skills/code-review-expert → code_review_forge-2.9.0/src/code_forge/skills/code-forge}/references/solid-checklist.md +0 -0
  281. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/SKILL.md +0 -0
  282. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/kernel-fp-verify/SKILL.md +0 -0
  283. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/qodo-review/SKILL.md +0 -0
  284. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/boundary-cases.md +0 -0
  285. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/concurrency-patterns.md +0 -0
  286. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/injection-payloads.md +0 -0
  287. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/README.md +0 -0
  288. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/primitives.sh +0 -0
  289. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/test-library/shell/primitives_test.sh +0 -0
  290. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/source.py +0 -0
  291. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_forge/verdict.py +0 -0
  292. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/dependency_links.txt +0 -0
  293. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/top_level.txt +0 -0
  294. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_baseline.py +0 -0
  295. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_baseline_integration.py +0 -0
  296. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_install_skill.py +0 -0
  297. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_cli_mutation_check.py +0 -0
  298. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_delta.py +0 -0
  299. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_diagnose.py +0 -0
  300. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_dispo04_lifecycle.py +0 -0
  301. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_dispo05_promotion.py +0 -0
  302. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_dispo06_revert.py +0 -0
  303. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_env_resolver.py +0 -0
  304. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_escalated_frozen.py +0 -0
  305. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_falsify_stub.py +0 -0
  306. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_fresh_start.py +0 -0
  307. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_hold_entry.py +0 -0
  308. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_hold_ui.py +0 -0
  309. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_lock_signals.py +0 -0
  310. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_machine_e2e.py +0 -0
  311. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_mode_resolver.py +0 -0
  312. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_pass_determinism.py +0 -0
  313. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_phase1_migration.py +0 -0
  314. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_phase3.py +0 -0
  315. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_promotion_tracking.py +0 -0
  316. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_pseudo_refs.py +0 -0
  317. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_snapshot.py +0 -0
  318. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_source_hash.py +0 -0
  319. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_state_04_extensions.py +0 -0
  320. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_state_extensions.py +0 -0
  321. {code_review_forge-2.1.0 → code_review_forge-2.9.0}/tests/test_verdict.py +0 -0
@@ -0,0 +1,577 @@
1
+ Metadata-Version: 2.4
2
+ Name: code-review-forge
3
+ Version: 2.9.0
4
+ Summary: 3-state quality gate for code review
5
+ Author-email: Minxi Hou <houminxi@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Quality Assurance
15
+ Requires-Python: >=3.12
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: pyyaml>=6.0
19
+ Requires-Dist: unidiff<0.8.0,>=0.7.5
20
+ Provides-Extra: dev
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"
24
+ Requires-Dist: mutmut<4.0,>=3.3; extra == "dev"
25
+ Requires-Dist: semgrep<1.170,>=1.0; extra == "dev"
26
+ Requires-Dist: jsonschema>=4.18; extra == "dev"
27
+ Provides-Extra: vertex
28
+ Requires-Dist: google-auth>=2.35.0; extra == "vertex"
29
+ Requires-Dist: requests>=2.20.0; extra == "vertex"
30
+ Provides-Extra: mcp
31
+ Requires-Dist: mcp<2,>=1.27; extra == "mcp"
32
+ Dynamic: license-file
33
+
34
+ # code-forge
35
+
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/)
38
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/HouMinXi/forge/blob/main/LICENSE)
39
+
40
+ A 5-step code review pipeline for AI coding assistants. Treats review as a
41
+ state machine: three independent passes per cycle, three consecutive clean
42
+ cycles required, any finding resets the counter. The minimum path to a
43
+ commit is 9 static review passes plus a runtime smoke test.
44
+
45
+ ## Why
46
+
47
+ AI coding assistants ship code that compiles, runs, and looks right.
48
+ Single-pass review (Copilot, Cursor, CodeRabbit, etc.) catches the obvious
49
+ defects but misses two failure modes:
50
+
51
+ - **Author and reviewer collapse.** When the same model writes and reviews
52
+ the change, it inherits its own blind spots. code-forge runs three
53
+ independent review perspectives (qodo, expert, adversarial) and treats
54
+ their findings as untrusted claims that must be reproduced before any fix.
55
+ - **Self-claimed completion.** Hooks that gate on "I finished" markers are
56
+ bypassable by any agent that can write a string. code-forge gates on
57
+ actual state: a real `pre-commit` hook running the test suite, a mutation
58
+ runner proving the tests catch regressions, and a coverage heuristic
59
+ detecting drift across components.
60
+
61
+ ## Quick start
62
+
63
+ ```bash
64
+ pip install code-review-forge
65
+ code-forge install-skill
66
+ ```
67
+
68
+ For MCP server support (IDE integration):
69
+
70
+ ```bash
71
+ pip install code-review-forge[mcp]
72
+ ```
73
+
74
+ The first command installs the CLI (Python >=3.12). The second copies the
75
+ 6 review skills into `~/.claude/skills/`. Then in Claude Code, run the
76
+ full pipeline:
77
+
78
+ ```
79
+ /code-forge
80
+ ```
81
+
82
+ Or invoke individual passes:
83
+
84
+ ```
85
+ /qodo-review # change-aware pre-review (Pass 1)
86
+ /code-review-expert # SOLID, architecture, security (Pass 2)
87
+ /adversarial-qe # red-team QE, 12 attack dimensions (Pass 3)
88
+ /kernel-fp-verify # false-positive verification (Step 3.5)
89
+ /smoke-test # runtime verification (Step 4)
90
+ ```
91
+
92
+ Other agent targets:
93
+
94
+ ```bash
95
+ code-forge install-skill --target vscode # <cwd>/.claude/skills/
96
+ code-forge install-skill --target universal # <cwd>/.agents/skills/
97
+ code-forge install-skill --dest /path/to/dir # explicit location
98
+ code-forge install-skill --skill code-forge # one skill only
99
+ code-forge install-skill --force # overwrite existing
100
+ ```
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
+
223
+ ## Backend configuration
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
+
231
+ By default, code-forge uses the `claude` CLI in your PATH with the session
232
+ model (no model pin). Three environment variables control the backend:
233
+
234
+ | Variable | Purpose | Default |
235
+ |---|---|---|
236
+ | `FORGE_BACKEND` | Select a named backend from `gate.yaml` | session-default |
237
+ | `FORGE_OUTLET` | Force outlet: `subprocess` \| `inline` \| `subagent` | auto-detected |
238
+ | `FORGE_LLM_MODEL` | Override model for CLI backends | `claude-sonnet-4-6` |
239
+
240
+ **Quick examples:**
241
+
242
+ ```bash
243
+ # Use the default (claude CLI, session model)
244
+ code-forge review
245
+
246
+ # Pin a specific model for this run
247
+ FORGE_LLM_MODEL=claude-opus-4-5 code-forge review
248
+
249
+ # Use a named API backend from gate.yaml
250
+ FORGE_BACKEND=claude-api code-forge review
251
+
252
+ # Force inline outlet (no subprocess)
253
+ FORGE_OUTLET=inline code-forge review
254
+ ```
255
+
256
+ **Named backends** (optional) are defined in the `backends:` key of
257
+ `.code-forge/gate.yaml` (created by `code-forge init`):
258
+
259
+ ```yaml
260
+ backends:
261
+ claude-api:
262
+ type: api
263
+ format: anthropic
264
+ base_url: https://api.anthropic.com
265
+ api_key_env: ANTHROPIC_API_KEY
266
+ default: true
267
+ openai-compatible:
268
+ type: api
269
+ format: openai
270
+ base_url: https://api.openai.com/v1
271
+ api_key_env: OPENAI_API_KEY
272
+ local-claude:
273
+ type: cli
274
+ model: claude-opus-4-5
275
+ command: claude
276
+ ```
277
+
278
+ Full reference: [docs/configuration.md](docs/configuration.md)
279
+
280
+ Editor setup guides:
281
+ - Claude Code: [docs/setup-claude-code.md](docs/setup-claude-code.md)
282
+ - VS Code: [docs/setup-vscode.md](docs/setup-vscode.md)
283
+ - Cursor: [docs/setup-cursor.md](docs/setup-cursor.md)
284
+ - PyCharm: [docs/setup-pycharm.md](docs/setup-pycharm.md)
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
+
352
+ ## The pipeline
353
+
354
+ ```
355
+ Code Change
356
+ |
357
+ v
358
+ [Step 0] Syntax (0a) + Lint (0b) + Non-ASCII (0c)
359
+ |
360
+ v
361
+ [Cycle 1] Pass 1: qodo-review
362
+ Pass 2: code-review-expert
363
+ Pass 3: adversarial-qe
364
+ |
365
+ | zero findings -> counter += 1
366
+ | any finding -> fix, counter = 0, restart Cycle 1
367
+ v
368
+ [Cycle 2] (same 3 passes)
369
+ |
370
+ v
371
+ [Cycle 3] (same 3 passes)
372
+ | counter = 3
373
+ v
374
+ [Step 3.5] kernel-fp-verify (if fixes were applied during cycles)
375
+ |
376
+ v
377
+ [Step 4] smoke-test (runtime verification)
378
+ |
379
+ v
380
+ [COMMIT GATE] # post-review-c3
381
+ ```
382
+
383
+ ## What ships
384
+
385
+ | Skill | Step | Purpose |
386
+ |--------------------|-----------|----------------------------------------------------------|
387
+ | code-forge | Orchestrator | Runs the full 5-step pipeline |
388
+ | qodo-review | Pass 1 | Change-aware pre-review with feature-grouped walkthrough |
389
+ | code-review-expert | Pass 2 | SOLID, architecture, security analysis |
390
+ | adversarial-qe | Pass 3 | Red-team QE with 12 attack dimensions |
391
+ | kernel-fp-verify | Step 3.5 | 10-step false-positive verification protocol |
392
+ | smoke-test | Step 4 | Runtime verification with bash assertion primitives |
393
+
394
+ ## What code-forge does that others don't
395
+
396
+ - **Multi-pass convergence.** Three consecutive clean cycles from three
397
+ independent perspectives. Any finding resets the counter to zero.
398
+ Copilot, CodeRabbit, Cursor, and Devin are single-pass.
399
+ - **Anti-hallucination gates.** code-forge treats LLM review output as
400
+ untrusted claims. Parser-deterministic findings auto-confirm; LLM
401
+ findings require falsification before disposition; Step 4 runs the
402
+ actual code. Prompt-only mitigations cap at 15% hallucination
403
+ reduction; tool grounding reaches 65-80% (CodeAnt and Suprmind data,
404
+ 2026).
405
+ - **Real commit gate (R1).** A real `.git/hooks/pre-commit` that runs the
406
+ test suite and blocks on NEW failures vs a baseline. Gates on diff
407
+ content and test results, not a self-claimed marker. Closes the
408
+ terminal-and-IDE bypass that PreToolUse hooks cannot reach.
409
+ - **Mutation-gated review (R2).** Diff-scoped mutation runs after static
410
+ review and before the verdict. Each mutant introduced into the changed
411
+ code is run against the test suite; a surviving mutant flags tests that
412
+ cannot catch the change. Toothless tests block the same cycle that
413
+ finds the defect.
414
+ - **Cross-component coverage heuristic (R3).** Detects diffs that span
415
+ multiple source areas with a changed function signature. An opt-in
416
+ components mapping raises an uncertain finding when a hub and a
417
+ dependent both change in the same diff and no integration test under
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.
437
+
438
+ ## Honest limitations
439
+
440
+ - **No cross-repo impact.** code-forge reviews a single repository.
441
+ Multi-repo dependency analysis requires CodeRabbit-style tooling or
442
+ Chromium's `Cq-Depend`.
443
+ - **No feedback learning.** code-forge does not adapt to dismissed
444
+ findings or developer preferences. Each review is independent.
445
+ - **No long-term maintainability scoring.** code-forge does not assess
446
+ technical debt accumulation. SonarQube's tech-debt tracking is the
447
+ closest automated approximation.
448
+ - **No performance regression suite.** No benchmark harness equivalent to
449
+ Rust's `perf.rust-lang.org`.
450
+ - **R3 is artifact-presence, not coverage proof.** The cross-component
451
+ check confirms an integration test file exists under the expected path;
452
+ it does not verify that the test exercises the specific code that
453
+ changed. A present-but-stale test passes the gate.
454
+
455
+ Static review (3-cycle convergence) is one layer. code-forge learned
456
+ from its own Phase 2 experience where 9 static passes and 639 mock tests
457
+ missed 3 bugs that dynamic verification caught. Verification grounding
458
+ (test suite + mutation + e2e coverage check) is the thesis -- not a
459
+ passes count.
460
+
461
+ ## Requirements
462
+
463
+ - Python 3.12 or newer
464
+ - `jq` for the bash smoke primitives
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]`
467
+
468
+ ## Installation alternatives
469
+
470
+ ### git clone
471
+
472
+ ```bash
473
+ git clone https://github.com/HouMinXi/forge.git
474
+ cd forge
475
+ ./install.sh
476
+ ```
477
+
478
+ Symlinks each of the 6 skills from `~/.claude/skills/<name>` to this
479
+ repo's `skills/<name>`. Hook installation is manual -- see
480
+ `hooks/README.md` and `hooks/settings-snippet.json`.
481
+
482
+ ## Enabling the commit gate (R1)
483
+
484
+ `install-skill` and `./install.sh` install the review **skills** only -- they
485
+ do not set up enforcement. The R1 pre-commit gate -- the un-fakeable layer that
486
+ runs the test suite on every commit and blocks on new failures, regardless of
487
+ what the in-editor review claims -- is a separate, manual step:
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
+
492
+ 1. Add a `test:` section to `.code-forge/gate.yaml`. Without it, `gate-check`
493
+ exits with `gate.yaml must have a 'test' section`:
494
+
495
+ ```yaml
496
+ test:
497
+ command: [pytest, -q]
498
+ timeout_seconds: 900
499
+ ```
500
+
501
+ `command[0]` must be a known runner (`python3`, `python`, `pytest`, `cargo`,
502
+ `go`, `make`, `npm`, `npx`, `node`); no shell metacharacters are allowed.
503
+
504
+ 2. Install the hook:
505
+
506
+ ```bash
507
+ code-forge install-hooks
508
+ ```
509
+
510
+ This writes `.git/hooks/pre-commit` that runs `code-forge verify` (a receipt
511
+ tamper check) and then `code-forge gate-check` (the test gate).
512
+
513
+ 3. If `git config core.hooksPath` is set, `install-hooks` refuses to write to a
514
+ custom hooks path and prints a manual fallback. Add these two lines to your
515
+ existing pre-commit hook by hand:
516
+
517
+ ```sh
518
+ code-forge verify --quiet 2>/dev/null || exit 1
519
+ exec code-forge gate-check
520
+ ```
521
+
522
+ The skills give you the review passes; this gate is what makes a green verdict
523
+ mean the tests actually pass. Without it, an in-editor review that never ran can
524
+ still reach a commit. Commits that stage only non-code files (docs, config,
525
+ metadata such as `.md`, `.yaml`, `.toml`, `LICENSE`, `README`) are detected by
526
+ the hook and skip the gate automatically -- no receipts and no `--no-verify`
527
+ needed. Any staged file outside that set, including unknown extensions, re-arms
528
+ the gate for the whole commit.
529
+
530
+ ## Hooks (reference implementations)
531
+
532
+ | Hook | Trigger | Purpose |
533
+ |-------------------------------|-----------------------|-------------------------------|
534
+ | `check_worktree.sh` | PreToolUse Edit/Write | Block edits in main worktree |
535
+ | `check_non_ascii.sh` | PreToolUse Write/Edit | Non-ASCII character detection |
536
+ | `check_read_before_edit.sh` | PreToolUse Edit | 1:1 read-before-edit ratio |
537
+ | `check_review_tracker.sh` | PostToolUse Bash | Review cycle state machine |
538
+ | `check_git_commit_review.sh` | PreToolUse Bash | Block unreviewed commits |
539
+ | `check_git_push_review.sh` | PreToolUse Bash | Block unreviewed pushes |
540
+
541
+ Some hooks contain environment-specific logic (Kerberos auth, pattern
542
+ matching) you will need to adapt. See `hooks/README.md`.
543
+
544
+ ## Bash smoke primitives
545
+
546
+ `skills/smoke-test/test-library/shell/` ships 19 reusable bash assertion
547
+ functions with no dependencies beyond `jq`:
548
+
549
+ - `run_and_capture`, `run_concurrent`, `concurrent_wait`
550
+ - `assert_success`, `assert_failure`, `assert_exit_code`
551
+ - `assert_output_contains`, `assert_output_not_contains`
552
+ - `assert_stderr_contains`, `assert_stderr_empty`
553
+ - `assert_file_exists`, `assert_file_not_exists`, `assert_file_contains`
554
+ - `assert_json_valid`
555
+ - `assert_no_zombie`, `assert_temp_clean`
556
+ - `assert_no_command_exec`, `assert_no_command_exec_json`, `assert_no_path_traversal`
557
+
558
+ A backward-compatible symlink at `test-library/` points to
559
+ `skills/smoke-test/test-library/` for users migrating from
560
+ [bash-smoke-primitives](https://github.com/HouMinXi/bash-smoke-primitives).
561
+
562
+ ## Documentation
563
+
564
+ - `evidence/cross-model-complementarity.md` -- why 3 different review passes
565
+ - `evidence/design-iterations.md` -- how the pipeline evolved
566
+ - `evidence/ground-truth-verification.md` -- why smoke tests must inject bugs
567
+ - `evidence/shell-assertion-footguns.md` -- 5 bash-specific traps
568
+ - `evidence/v9-model-coverage-matrix.md` -- 4-model coverage data
569
+ - `hooks/README.md` -- hook installation and adaptation guide
570
+
571
+ ## Contributing
572
+
573
+ Issues and discussion: <https://github.com/HouMinXi/forge/issues>.
574
+
575
+ ## License
576
+
577
+ Apache-2.0