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.
- {code_review_forge-2.4.0/src/code_review_forge.egg-info → code_review_forge-2.9.0}/PKG-INFO +240 -12
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/README.md +233 -10
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/pyproject.toml +10 -3
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/__init__.py +3 -1
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/__main__.py +4 -2
- code_review_forge-2.9.0/src/code_forge/advisory.py +112 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/autofix.py +18 -1
- code_review_forge-2.9.0/src/code_forge/backend.py +1130 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/baseline.py +18 -3
- code_review_forge-2.9.0/src/code_forge/basis.py +134 -0
- code_review_forge-2.9.0/src/code_forge/canary.py +186 -0
- code_review_forge-2.9.0/src/code_forge/canary_gen.py +420 -0
- code_review_forge-2.9.0/src/code_forge/claim.py +52 -0
- code_review_forge-2.9.0/src/code_forge/cli.py +4389 -0
- code_review_forge-2.9.0/src/code_forge/contract_loader.py +433 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/conventions_resolver.py +2 -2
- code_review_forge-2.9.0/src/code_forge/cross_repo.py +449 -0
- code_review_forge-2.9.0/src/code_forge/cross_repo_impact.py +342 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/daemon_state.py +16 -8
- code_review_forge-2.9.0/src/code_forge/dead_code.py +328 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/delta.py +21 -3
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/detect.py +156 -12
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/diagnose.py +12 -0
- code_review_forge-2.9.0/src/code_forge/diff.py +499 -0
- code_review_forge-2.9.0/src/code_forge/diff_grouping.py +469 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/disposition.py +4 -0
- code_review_forge-2.9.0/src/code_forge/doctor.py +571 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/e2e_check.py +30 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/errors.py +24 -0
- code_review_forge-2.9.0/src/code_forge/eval/corpus.py +196 -0
- code_review_forge-2.9.0/src/code_forge/eval/export.py +608 -0
- code_review_forge-2.9.0/src/code_forge/eval/runner.py +781 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/eval/scorer.py +183 -8
- code_review_forge-2.9.0/src/code_forge/evidence.py +67 -0
- code_review_forge-2.9.0/src/code_forge/exec_falsify.py +426 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/exit_codes.py +8 -1
- code_review_forge-2.9.0/src/code_forge/factories.py +852 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/falsify.py +1 -1
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/falsify_real.py +15 -10
- code_review_forge-2.9.0/src/code_forge/findings.py +24 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/fixval.py +13 -9
- code_review_forge-2.9.0/src/code_forge/flow_contract.py +33 -0
- code_review_forge-2.9.0/src/code_forge/gate.schema.json +430 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/gate_check.py +409 -8
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/git.py +24 -13
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/graph_triage.py +99 -50
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/hold.py +5 -2
- code_review_forge-2.9.0/src/code_forge/init_template.py +217 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/install_hooks.py +259 -42
- code_review_forge-2.9.0/src/code_forge/ledger.py +210 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/legacy.py +14 -15
- code_review_forge-2.9.0/src/code_forge/llm_invoke.py +2282 -0
- code_review_forge-2.9.0/src/code_forge/lock.py +455 -0
- code_review_forge-2.9.0/src/code_forge/machine.py +2182 -0
- code_review_forge-2.9.0/src/code_forge/manifest.py +382 -0
- code_review_forge-2.9.0/src/code_forge/mcp_jobs.py +350 -0
- code_review_forge-2.9.0/src/code_forge/mcp_server.py +1472 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/mutation.py +117 -6
- code_review_forge-2.9.0/src/code_forge/outlet_c.py +225 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/outlet_resolver.py +60 -21
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/__init__.py +3 -2
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/_sarif.py +19 -8
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/base.py +1 -18
- code_review_forge-2.9.0/src/code_forge/parsers/eslint.py +64 -0
- code_review_forge-2.9.0/src/code_forge/proc.py +120 -0
- code_review_forge-2.9.0/src/code_forge/progress.py +72 -0
- code_review_forge-2.9.0/src/code_forge/receipt.py +278 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/registry.py +2 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/reporter.py +1 -1
- code_review_forge-2.9.0/src/code_forge/reviewer_json.py +191 -0
- code_review_forge-2.9.0/src/code_forge/rulepack.py +620 -0
- code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/meta.yaml +45 -0
- code_review_forge-2.9.0/src/code_forge/rules/packs/vercel-react/rules.yaml +55 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/runner.py +39 -16
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/runtime.py +41 -19
- code_review_forge-2.9.0/src/code_forge/sarif.py +381 -0
- code_review_forge-2.9.0/src/code_forge/setup_mcp.py +269 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/SKILL.md +50 -15
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/snapshot.py +2 -2
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/state.py +109 -4
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/taint.py +4 -4
- code_review_forge-2.9.0/src/code_forge/trust.py +369 -0
- code_review_forge-2.9.0/src/code_forge/user_config.py +111 -0
- code_review_forge-2.9.0/src/code_forge/verify.py +904 -0
- code_review_forge-2.9.0/src/code_forge/workspace.py +51 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0/src/code_review_forge.egg-info}/PKG-INFO +240 -12
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/SOURCES.txt +98 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/entry_points.txt +1 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/requires.txt +7 -1
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/top_level.txt +0 -1
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_advisory.py +99 -33
- code_review_forge-2.9.0/tests/test_backend.py +2156 -0
- code_review_forge-2.9.0/tests/test_backend_attribution.py +123 -0
- code_review_forge-2.9.0/tests/test_basis.py +224 -0
- code_review_forge-2.9.0/tests/test_canary.py +218 -0
- code_review_forge-2.9.0/tests/test_canary_cli.py +431 -0
- code_review_forge-2.9.0/tests/test_canary_gen.py +510 -0
- code_review_forge-2.9.0/tests/test_canary_smoke.py +394 -0
- code_review_forge-2.9.0/tests/test_chunking.py +278 -0
- code_review_forge-2.9.0/tests/test_claim_type.py +226 -0
- code_review_forge-2.9.0/tests/test_cli_advisory_wiring.py +117 -0
- code_review_forge-2.9.0/tests/test_cli_banner.py +349 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_e2e_check.py +162 -2
- code_review_forge-2.9.0/tests/test_cli_empty_diff.py +115 -0
- code_review_forge-2.9.0/tests/test_cli_entrypoint.py +44 -0
- code_review_forge-2.9.0/tests/test_cli_eval.py +929 -0
- code_review_forge-2.9.0/tests/test_cli_grouping_wiring.py +52 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_hold_resume.py +64 -9
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_init.py +6 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_integration.py +39 -9
- code_review_forge-2.9.0/tests/test_cli_internal_error.py +69 -0
- code_review_forge-2.9.0/tests/test_cli_l2_wiring.py +78 -0
- code_review_forge-2.9.0/tests/test_cli_ledger.py +770 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_parser.py +9 -37
- code_review_forge-2.9.0/tests/test_cli_pending_exit.py +25 -0
- code_review_forge-2.9.0/tests/test_cli_phase1_compat.py +38 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_sarif.py +38 -14
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_trust.py +206 -23
- code_review_forge-2.9.0/tests/test_cli_verify_required_cycles.py +179 -0
- code_review_forge-2.9.0/tests/test_contract_flag.py +611 -0
- code_review_forge-2.9.0/tests/test_contract_loader.py +719 -0
- code_review_forge-2.9.0/tests/test_contract_wiring.py +415 -0
- code_review_forge-2.9.0/tests/test_cross_repo.py +1241 -0
- code_review_forge-2.9.0/tests/test_cross_repo_contracts.py +549 -0
- code_review_forge-2.9.0/tests/test_cross_repo_impact.py +604 -0
- code_review_forge-2.9.0/tests/test_cross_repo_impact_integration.py +568 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_daemon_state.py +122 -22
- code_review_forge-2.9.0/tests/test_dead_code.py +697 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_detect.py +104 -0
- code_review_forge-2.9.0/tests/test_detect_c.py +88 -0
- code_review_forge-2.9.0/tests/test_detect_cpp.py +88 -0
- code_review_forge-2.9.0/tests/test_detect_java.py +96 -0
- code_review_forge-2.9.0/tests/test_detect_js.py +96 -0
- code_review_forge-2.9.0/tests/test_diff.py +898 -0
- code_review_forge-2.9.0/tests/test_diff_grouping.py +478 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_disposition.py +3 -3
- code_review_forge-2.9.0/tests/test_doctor.py +805 -0
- code_review_forge-2.9.0/tests/test_doctor_tool_audit.py +224 -0
- code_review_forge-2.9.0/tests/test_dogfood.py +372 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_e2e_check.py +25 -0
- code_review_forge-2.9.0/tests/test_encoding_conformance.py +190 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_corpus.py +1 -1
- code_review_forge-2.9.0/tests/test_eval_corpus_findings.py +823 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_runner.py +127 -54
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_eval_scorer.py +2 -2
- code_review_forge-2.9.0/tests/test_evidence.py +91 -0
- code_review_forge-2.9.0/tests/test_exec_falsify.py +603 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_exit_codes.py +35 -4
- code_review_forge-2.9.0/tests/test_export_eval.py +1118 -0
- code_review_forge-2.9.0/tests/test_f3_legacy_exit.py +311 -0
- code_review_forge-2.9.0/tests/test_factories.py +1549 -0
- code_review_forge-2.9.0/tests/test_falsify_real.py +317 -0
- code_review_forge-2.9.0/tests/test_fast_fail.py +378 -0
- code_review_forge-2.9.0/tests/test_findings.py +28 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fixval_integration.py +8 -1
- code_review_forge-2.9.0/tests/test_flow_contract_drift.py +90 -0
- code_review_forge-2.9.0/tests/test_focus.py +224 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_gate_check.py +197 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_git.py +43 -2
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_graph_triage.py +58 -7
- code_review_forge-2.9.0/tests/test_hook_carveout.py +528 -0
- code_review_forge-2.9.0/tests/test_hook_failclosed.py +115 -0
- code_review_forge-2.9.0/tests/test_infra_convergence.py +228 -0
- code_review_forge-2.9.0/tests/test_inline_delegated.py +69 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_install_hooks.py +310 -45
- code_review_forge-2.9.0/tests/test_ledger.py +341 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_legacy.py +25 -2
- code_review_forge-2.9.0/tests/test_llm_invoke.py +5825 -0
- code_review_forge-2.9.0/tests/test_lock.py +802 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_advisory.py +8 -8
- code_review_forge-2.9.0/tests/test_machine_ci.py +228 -0
- code_review_forge-2.9.0/tests/test_machine_l0_crash_guard.py +93 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_l2.py +277 -3
- code_review_forge-2.9.0/tests/test_machine_ledger.py +875 -0
- code_review_forge-2.9.0/tests/test_machine_local.py +902 -0
- code_review_forge-2.9.0/tests/test_machine_mutation_launch.py +367 -0
- code_review_forge-2.9.0/tests/test_manifest.py +266 -0
- code_review_forge-2.9.0/tests/test_mcp_jobs.py +1068 -0
- code_review_forge-2.9.0/tests/test_mcp_pdeathsig.py +194 -0
- code_review_forge-2.9.0/tests/test_mcp_server.py +3101 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_outlet_c.py +71 -0
- code_review_forge-2.9.0/tests/test_outlet_c_cli.py +466 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_outlet_resolver.py +120 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_parsers.py +1 -0
- code_review_forge-2.9.0/tests/test_post_image_window.py +302 -0
- code_review_forge-2.9.0/tests/test_progress.py +55 -0
- code_review_forge-2.9.0/tests/test_realpath_ledger.py +116 -0
- code_review_forge-2.9.0/tests/test_receipt.py +502 -0
- code_review_forge-2.9.0/tests/test_receipt_partial.py +285 -0
- code_review_forge-2.9.0/tests/test_reviewer_json.py +119 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_round.py +8 -2
- code_review_forge-2.9.0/tests/test_rulepack_blocking.py +143 -0
- code_review_forge-2.9.0/tests/test_rulepack_loader.py +224 -0
- code_review_forge-2.9.0/tests/test_rulepack_matrix.py +110 -0
- code_review_forge-2.9.0/tests/test_rulepack_runner.py +241 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runner.py +8 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime.py +146 -52
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_drift.py +4 -4
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_eval.py +4 -4
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_runtime_machine.py +6 -6
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_sarif.py +239 -39
- code_review_forge-2.9.0/tests/test_schema_corpus.py +867 -0
- code_review_forge-2.9.0/tests/test_setup_mcp.py +270 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_schema.py +30 -2
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint.py +1 -1
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_trust.py +24 -11
- code_review_forge-2.9.0/tests/test_trust_empty_backends.py +84 -0
- code_review_forge-2.9.0/tests/test_user_config.py +313 -0
- code_review_forge-2.9.0/tests/test_verify.py +2270 -0
- code_review_forge-2.4.0/src/code_forge/advisory.py +0 -78
- code_review_forge-2.4.0/src/code_forge/backend.py +0 -532
- code_review_forge-2.4.0/src/code_forge/cli.py +0 -2154
- code_review_forge-2.4.0/src/code_forge/diff.py +0 -254
- code_review_forge-2.4.0/src/code_forge/eval/corpus.py +0 -79
- code_review_forge-2.4.0/src/code_forge/eval/runner.py +0 -464
- code_review_forge-2.4.0/src/code_forge/factories.py +0 -338
- code_review_forge-2.4.0/src/code_forge/init_template.py +0 -72
- code_review_forge-2.4.0/src/code_forge/llm_invoke.py +0 -675
- code_review_forge-2.4.0/src/code_forge/lock.py +0 -162
- code_review_forge-2.4.0/src/code_forge/machine.py +0 -1213
- code_review_forge-2.4.0/src/code_forge/outlet_c.py +0 -102
- code_review_forge-2.4.0/src/code_forge/receipt.py +0 -134
- code_review_forge-2.4.0/src/code_forge/reviewer_json.py +0 -111
- code_review_forge-2.4.0/src/code_forge/sarif.py +0 -243
- code_review_forge-2.4.0/src/code_forge/trust.py +0 -178
- code_review_forge-2.4.0/src/code_forge/verify.py +0 -381
- code_review_forge-2.4.0/tests/test_backend.py +0 -1061
- code_review_forge-2.4.0/tests/test_cli_eval.py +0 -326
- code_review_forge-2.4.0/tests/test_cli_phase1_compat.py +0 -191
- code_review_forge-2.4.0/tests/test_diff.py +0 -324
- code_review_forge-2.4.0/tests/test_factories.py +0 -332
- code_review_forge-2.4.0/tests/test_falsify_real.py +0 -55
- code_review_forge-2.4.0/tests/test_hook_carveout.py +0 -245
- code_review_forge-2.4.0/tests/test_llm_invoke.py +0 -1080
- code_review_forge-2.4.0/tests/test_lock.py +0 -174
- code_review_forge-2.4.0/tests/test_machine_ci.py +0 -133
- code_review_forge-2.4.0/tests/test_machine_local.py +0 -384
- code_review_forge-2.4.0/tests/test_receipt.py +0 -88
- code_review_forge-2.4.0/tests/test_verify.py +0 -305
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/LICENSE +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/MANIFEST.in +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/setup.cfg +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/conventions.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/coverage.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/env_resolver.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/eval/__init__.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/mode_resolver.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/checkpatch.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/clippy.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/flake8.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/non_ascii.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/pylint.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/ruff.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/semgrep.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/parsers/shellcheck.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/rules/forge-taint.yaml +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/adversarial-qe/SKILL.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass1-qodo.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass2-expert.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/passes/pass3-adversarial.md +0 -0
- {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
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/removal-plan.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/security-checklist.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-forge/references/solid-checklist.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/code-review-expert/SKILL.md +0 -0
- {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
- {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
- {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
- {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
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/kernel-fp-verify/SKILL.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/qodo-review/SKILL.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/SKILL.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/boundary-cases.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/concurrency-patterns.md +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/skills/smoke-test/references/injection-payloads.md +0 -0
- {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
- {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
- {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
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/source.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_forge/verdict.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/src/code_review_forge.egg-info/dependency_links.txt +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_baseline.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_baseline_integration.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_backend_propagation.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_detect.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_install_skill.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_lock.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_cli_mutation_check.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_consecutive_clean.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_conventions.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_conventions_resolver.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_coverage.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_daemon_state_drift.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_delta.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_diagnose.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo04_lifecycle.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo05_promotion.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_dispo06_revert.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_env_resolver.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_escalated_frozen.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_falsify_stub.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fixval.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_fresh_start.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_hold_entry.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_hold_ui.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_integration.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_legacy_integration.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_lock_signals.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_coverage.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_machine_e2e.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_mode_resolver.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_mutation.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_ordering.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_pass_determinism.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_phase1_migration.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_phase3.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_promotion_tracking.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_pseudo_refs.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_r1_e2e.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_registry.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_smoke_receipt.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_snapshot.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_source_hash.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_04_extensions.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_state_extensions.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint_integration.py +0 -0
- {code_review_forge-2.4.0 → code_review_forge-2.9.0}/tests/test_taint_rule.py +0 -0
- {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.
|
|
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.
|
|
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
|
-
[](https://pypi.org/project/code-review-forge/)
|
|
32
|
-
[](https://pypi.org/project/code-review-forge/)
|
|
36
|
+
[](https://pypi.org/project/code-review-forge/)
|
|
37
|
+
[](https://pypi.org/project/code-review-forge/)
|
|
33
38
|
[](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 `
|
|
99
|
-
| `FORGE_OUTLET` | Force outlet: `
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
[](https://pypi.org/project/code-review-forge/)
|
|
4
|
-
[](https://pypi.org/project/code-review-forge/)
|
|
3
|
+
[](https://pypi.org/project/code-review-forge/)
|
|
4
|
+
[](https://pypi.org/project/code-review-forge/)
|
|
5
5
|
[](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 `
|
|
71
|
-
| `FORGE_OUTLET` | Force outlet: `
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
|