argus-code-review 0.2.11__tar.gz → 0.3.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.
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/CHANGELOG.md +18 -1
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/PKG-INFO +39 -3
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/README.md +38 -2
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/cli.py +49 -5
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/config.py +7 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/graph.py +247 -75
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/models.py +46 -1
- argus_code_review-0.3.0/argus/prompts/pr-review-scope.md +18 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts_runtime.py +3 -2
- argus_code_review-0.3.0/argus/scope.py +199 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/http.py +5 -2
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/golden/review_response.schema.json +159 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_bench_config_guard.py +11 -11
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_cli_post_review.py +13 -1
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_cli_preflight.py +2 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_fetch_diff.py +113 -9
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_precheck.py +8 -4
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_progress.py +147 -130
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_multi_round.py +30 -5
- argus_code_review-0.3.0/tests/test_scope.py +213 -0
- argus_code_review-0.3.0/tests/test_scope_gate.py +688 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/.gitignore +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/LICENSE +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/bench.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/bench_default.toml +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/coverage.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/dotenv_utils.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/gemini_cache.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/gemini_runner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/github_client.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/helpers.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/llm/models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/llm/output_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/llm/pricing.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/llm/usage.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/openai_client.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/openai_runner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/pipeline_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/actions_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/engine.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/eslint_bundle/.gitignore +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/eslint_bundle/README.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/eslint_bundle/eslint.config.js +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/eslint_bundle/package-lock.json +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/eslint_bundle/package.json +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/js_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/migration_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/rules/README.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/sarif.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/scanner_utils.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/secrets_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/shadow.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/terraform_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/precheck/workflow_lint_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-blocking-validator.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-coverage-check.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-cross-cutting.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-feedback-verifier.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-lite.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-planner.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-preflight-router.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-prior-art.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-deployment.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-frontend.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-infra.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-llm-patterns.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-observability.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-orchestration.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-security.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-slackbot.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-specialist-sql.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-subagent.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-tests-and-docs.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/prompts/pr-review-writer.md +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/repo_provision.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/review_tools.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/runners.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/precheck.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/resolver.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/session.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/sql.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/argus/storage/sqlite.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/pyproject.toml +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/008_add_code_reviews.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/009_add_reviewer_version.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/010_add_review_patterns.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/011_add_review_progress_columns.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/015_create_agent_runs.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/016_add_agent_runs_failure_reason.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/017_add_precheck_rules.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/schema/018_widen_agent_runs_failure_reason.sql +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/conftest.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/__init__.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_backend_contract.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_http.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_resolver.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_session.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_sql.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/storage/test_sqlite_backend.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_actions_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_argus_review_local.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_bench.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_catchup_gate.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_cli_args.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_cli_output_contract.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_cli_prompts.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_config.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_conftest.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_gemini_cache.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_gemini_runner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_github_client_checks_signal.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_github_client_write.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_get_llm_temperature.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_http_guards.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_preflight_image_bump.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_storage_resolution.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_graph_timeout_surfacing.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_js_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_llm_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_llm_models_override.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_llm_pricing.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_migration_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_openai_client.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_openai_runner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_output_models.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_packaging.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_plan_review.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_precheck_engine.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_precheck_engine_integration.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_precheck_sarif.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_precheck_shadow.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_precheck_shadow_integration.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_prompts.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_repo_provision.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_review_patterns_integration.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_review_tools.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_runners_context7.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_runners_context_usage.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_runners_helpers.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_runners_new.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_runners_turn_budget.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_scanner_utils.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_secrets_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_specialist_validation.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_stage_costs.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_storage_precheck.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_structured_output_methods.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_terraform_scanner.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_terraform_scanner_integration.py +0 -0
- {argus_code_review-0.2.11 → argus_code_review-0.3.0}/tests/test_workflow_lint_scanner.py +0 -0
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-10-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Scope gate: before the early verifier and preflight (including incremental and lite rounds), a new `pr-review-scope` prompt splits the full pinned PR (`merge-base..head`) into independently mergeable behaviors. More than one behavior halts with `scope_split`. An unverifiable manifest (overlapping, unknown, or unassigned files, cyclic dependencies, a 300-file listing, an oversized or indeterminate input, or any gate error) halts with `scope_unverified`.
|
|
15
|
+
- Workload halts: a plan that needs more reviewers than `ARGUS_REVIEWER_DISPATCH_BUDGET` (default 16, range 3-50) halts with `dispatch_budget_exceeded` before any reviewer starts. More than 50 gap-fill reviewers halts with `gap_fill_cap_exceeded`.
|
|
16
|
+
- `ReviewResponse.scope` (pipeline-generated receipt: `base_sha`, `head_sha`, `behaviors`, `rationale`, `override_reason`) and `ReviewResponse.halt` (`code`, `detail`, `head_sha`, `split_suggestions`, `dispatch_count`, `dispatch_budget`). Both are excluded from LLM-generated output. A halt is always `BLOCKING` with `HIGH` risk and has no findings.
|
|
17
|
+
- CLI `--review-override-sha` and `--review-override-reason`: a human exception for `scope_split` and for a plan over the budget (up to the hard ceiling of 50). The SHA must equal the resolved head. It never overrides `scope_unverified` or `gap_fill_cap_exceeded`.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- The fan-out ceiling of 50 reviewers no longer truncates the plan or the gap-fill list; exceeding it halts the review.
|
|
22
|
+
- A halted round is stored with `verdict = NULL` and `current_stage = completed`, so it never becomes the prior round: the last reviewed SHA and round count do not advance. The HTTP storage client now skips `verdict = null` rounds like the SQL backends. No schema migration.
|
|
23
|
+
- `--commit-status` posts every outcome to the reviewed head (`halt.head_sha` or `scope.head_sha`) instead of re-reading the live head. The scope gate and bench guard share one merge base pinned in `fetch_diff`; an unpinnable base, an empty manifest for a non-empty diff, an empty-file behavior, or untrimmed titles halt `scope_unverified`.
|
|
24
|
+
- `ReviewResponse` JSON schema gains `scope` and `halt` (golden snapshot updated). The stderr summary block is unchanged.
|
|
25
|
+
|
|
10
26
|
## [0.2.11] - 2026-10-12
|
|
11
27
|
|
|
12
28
|
### Fixed
|
|
@@ -407,7 +423,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
407
423
|
packaged set.
|
|
408
424
|
- `argus --version`, `argus prompts list`, and `argus prompts export`.
|
|
409
425
|
|
|
410
|
-
[Unreleased]: https://github.com/redesignhealth/argus-review/compare/v0.
|
|
426
|
+
[Unreleased]: https://github.com/redesignhealth/argus-review/compare/v0.3.0...HEAD
|
|
427
|
+
[0.3.0]: https://github.com/redesignhealth/argus-review/compare/v0.2.11...v0.3.0
|
|
411
428
|
[0.2.11]: https://github.com/redesignhealth/argus-review/compare/v0.2.10...v0.2.11
|
|
412
429
|
[0.2.10]: https://github.com/redesignhealth/argus-review/compare/v0.2.9...v0.2.10
|
|
413
430
|
[0.2.9]: https://github.com/redesignhealth/argus-review/compare/v0.2.8...v0.2.9
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: argus-code-review
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Self-orchestrated PR review agent using LangGraph + Claude Agent SDK
|
|
5
5
|
Project-URL: Repository, https://github.com/redesignhealth/argus-review
|
|
6
6
|
Project-URL: Issues, https://github.com/redesignhealth/argus-review/issues
|
|
@@ -137,10 +137,46 @@ consolidates every finding into one review with a verdict and severity
|
|
|
137
137
|
tags.
|
|
138
138
|
|
|
139
139
|
```
|
|
140
|
-
fetch_diff → plan → [system reviewers ‖ specialists ‖ cross-cutting] (parallel)
|
|
140
|
+
fetch_diff → scope_gate → plan → [system reviewers ‖ specialists ‖ cross-cutting] (parallel)
|
|
141
141
|
→ check_coverage → (fill_gaps if needed) → write_review → persist
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
### Scope and workload halts
|
|
145
|
+
|
|
146
|
+
Before dispatching reviewer sessions, Argus checks the whole PR (merge base to
|
|
147
|
+
head, on every round, including incremental and lite rounds). If the PR
|
|
148
|
+
contains more than one independently mergeable behavior, or Argus cannot
|
|
149
|
+
verify its scope, the review halts with a `BLOCKING` verdict, `HIGH` risk,
|
|
150
|
+
and no findings. The same happens when the plan needs more reviewers than
|
|
151
|
+
`ARGUS_REVIEWER_DISPATCH_BUDGET` (default 16, range 3-50), or when more
|
|
152
|
+
than 50 gap-fill reviewers are needed. The response carries a `halt`
|
|
153
|
+
object with one of these codes: `scope_split`, `scope_unverified`,
|
|
154
|
+
`dispatch_budget_exceeded`, `gap_fill_cap_exceeded`. A successful review
|
|
155
|
+
carries a `scope` receipt pinned to the reviewed head SHA.
|
|
156
|
+
|
|
157
|
+
A halted round is not a reviewed round: it is stored with a null verdict,
|
|
158
|
+
so the next run still diffs from the last reviewed SHA. Argus does not
|
|
159
|
+
revoke approvals issued before this guard was enabled, including stored
|
|
160
|
+
approvals for the same SHA. External merge gates must reject the latest
|
|
161
|
+
halt outcome instead of accepting any historical `APPROVE` row.
|
|
162
|
+
|
|
163
|
+
A human can authorize a multi-behavior PR, or a plan over the budget (up to 50
|
|
164
|
+
reviewers), for one exact head:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
argus review owner/repo --pr 123 \
|
|
168
|
+
--review-override-sha HEAD_SHA \
|
|
169
|
+
--review-override-reason "why this PR stays together"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Both flags are required together. The SHA must equal the head Argus
|
|
173
|
+
resolves, or the run fails before it spends anything (with `--sha`,
|
|
174
|
+
pass the full 40-character SHA). The reason (1-500
|
|
175
|
+
characters) is stored in `scope.override_reason`. These flags exist only
|
|
176
|
+
on the CLI, never on the API request. Agents and skills must not add
|
|
177
|
+
them automatically. They never override `scope_unverified` or
|
|
178
|
+
`gap_fill_cap_exceeded`.
|
|
179
|
+
|
|
144
180
|
Full design rationale is in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
|
|
145
181
|
|
|
146
182
|
## Getting started
|
|
@@ -351,7 +387,7 @@ details are in [`docs/STORAGE.md`](docs/STORAGE.md).
|
|
|
351
387
|
|
|
352
388
|
## Adapting Argus to your team
|
|
353
389
|
|
|
354
|
-
Argus ships with a full set of production review prompts —
|
|
390
|
+
Argus ships with a full set of production review prompts — 21 files, one
|
|
355
391
|
per reviewer role — rather than a thin default. Adapting them to your team
|
|
356
392
|
is the main lever for making Argus *yours*.
|
|
357
393
|
|
|
@@ -86,10 +86,46 @@ consolidates every finding into one review with a verdict and severity
|
|
|
86
86
|
tags.
|
|
87
87
|
|
|
88
88
|
```
|
|
89
|
-
fetch_diff → plan → [system reviewers ‖ specialists ‖ cross-cutting] (parallel)
|
|
89
|
+
fetch_diff → scope_gate → plan → [system reviewers ‖ specialists ‖ cross-cutting] (parallel)
|
|
90
90
|
→ check_coverage → (fill_gaps if needed) → write_review → persist
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
### Scope and workload halts
|
|
94
|
+
|
|
95
|
+
Before dispatching reviewer sessions, Argus checks the whole PR (merge base to
|
|
96
|
+
head, on every round, including incremental and lite rounds). If the PR
|
|
97
|
+
contains more than one independently mergeable behavior, or Argus cannot
|
|
98
|
+
verify its scope, the review halts with a `BLOCKING` verdict, `HIGH` risk,
|
|
99
|
+
and no findings. The same happens when the plan needs more reviewers than
|
|
100
|
+
`ARGUS_REVIEWER_DISPATCH_BUDGET` (default 16, range 3-50), or when more
|
|
101
|
+
than 50 gap-fill reviewers are needed. The response carries a `halt`
|
|
102
|
+
object with one of these codes: `scope_split`, `scope_unverified`,
|
|
103
|
+
`dispatch_budget_exceeded`, `gap_fill_cap_exceeded`. A successful review
|
|
104
|
+
carries a `scope` receipt pinned to the reviewed head SHA.
|
|
105
|
+
|
|
106
|
+
A halted round is not a reviewed round: it is stored with a null verdict,
|
|
107
|
+
so the next run still diffs from the last reviewed SHA. Argus does not
|
|
108
|
+
revoke approvals issued before this guard was enabled, including stored
|
|
109
|
+
approvals for the same SHA. External merge gates must reject the latest
|
|
110
|
+
halt outcome instead of accepting any historical `APPROVE` row.
|
|
111
|
+
|
|
112
|
+
A human can authorize a multi-behavior PR, or a plan over the budget (up to 50
|
|
113
|
+
reviewers), for one exact head:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
argus review owner/repo --pr 123 \
|
|
117
|
+
--review-override-sha HEAD_SHA \
|
|
118
|
+
--review-override-reason "why this PR stays together"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Both flags are required together. The SHA must equal the head Argus
|
|
122
|
+
resolves, or the run fails before it spends anything (with `--sha`,
|
|
123
|
+
pass the full 40-character SHA). The reason (1-500
|
|
124
|
+
characters) is stored in `scope.override_reason`. These flags exist only
|
|
125
|
+
on the CLI, never on the API request. Agents and skills must not add
|
|
126
|
+
them automatically. They never override `scope_unverified` or
|
|
127
|
+
`gap_fill_cap_exceeded`.
|
|
128
|
+
|
|
93
129
|
Full design rationale is in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
|
|
94
130
|
|
|
95
131
|
## Getting started
|
|
@@ -300,7 +336,7 @@ details are in [`docs/STORAGE.md`](docs/STORAGE.md).
|
|
|
300
336
|
|
|
301
337
|
## Adapting Argus to your team
|
|
302
338
|
|
|
303
|
-
Argus ships with a full set of production review prompts —
|
|
339
|
+
Argus ships with a full set of production review prompts — 21 files, one
|
|
304
340
|
per reviewer role — rather than a thin default. Adapting them to your team
|
|
305
341
|
is the main lever for making Argus *yours*.
|
|
306
342
|
|
|
@@ -225,13 +225,22 @@ def _check_settings(settings: "Settings") -> None:
|
|
|
225
225
|
sys.exit(1)
|
|
226
226
|
|
|
227
227
|
|
|
228
|
-
async def run(
|
|
228
|
+
async def run(
|
|
229
|
+
request: "ReviewRequest",
|
|
230
|
+
review_override_sha: str | None = None,
|
|
231
|
+
review_override_reason: str | None = None,
|
|
232
|
+
) -> "ReviewResponse":
|
|
229
233
|
"""Run the review pipeline (storage backend resolved automatically:
|
|
230
234
|
Postgres if ``ARGUS_DB_URL`` is set, HTTP shim if the storage URLs are
|
|
231
235
|
set, else local SQLite)."""
|
|
232
236
|
from argus.graph import run_review
|
|
233
237
|
|
|
234
|
-
return await run_review(
|
|
238
|
+
return await run_review(
|
|
239
|
+
request,
|
|
240
|
+
flow_run_id=None,
|
|
241
|
+
review_override_sha=review_override_sha,
|
|
242
|
+
review_override_reason=review_override_reason,
|
|
243
|
+
)
|
|
235
244
|
|
|
236
245
|
|
|
237
246
|
# Sentinel distinguishing "--specialist-model/--frontier-model not passed at
|
|
@@ -337,6 +346,23 @@ def _add_review_args(parser: argparse.ArgumentParser) -> None:
|
|
|
337
346
|
"success iff verdict is APPROVE). Same token rules as --post."
|
|
338
347
|
),
|
|
339
348
|
)
|
|
349
|
+
parser.add_argument(
|
|
350
|
+
"--review-override-sha",
|
|
351
|
+
dest="review_override_sha",
|
|
352
|
+
default=None,
|
|
353
|
+
help=(
|
|
354
|
+
"Human exception: allow a multi-behavior PR or a reviewer plan over the dispatch "
|
|
355
|
+
"budget (up to the hard ceiling of 50) to proceed. Must equal the 40-character "
|
|
356
|
+
"lowercase HEAD SHA being reviewed, and needs --review-override-reason. Never "
|
|
357
|
+
"overrides an unverified scope or the gap-fill cap."
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
parser.add_argument(
|
|
361
|
+
"--review-override-reason",
|
|
362
|
+
dest="review_override_reason",
|
|
363
|
+
default=None,
|
|
364
|
+
help="Reason for --review-override-sha (1-500 characters); recorded in the scope receipt.",
|
|
365
|
+
)
|
|
340
366
|
parser.add_argument(
|
|
341
367
|
"--no-prompt-overrides",
|
|
342
368
|
action="store_true",
|
|
@@ -457,6 +483,12 @@ def _validate_review_args(parser: argparse.ArgumentParser, args: argparse.Namesp
|
|
|
457
483
|
"""Cross-flag validation that argparse's own declarative options can't express."""
|
|
458
484
|
if args.post and args.sha and not args.pr:
|
|
459
485
|
parser.error("--post requires --pr (a PR to comment on); --sha alone has nowhere to post")
|
|
486
|
+
from argus.scope import validate_override
|
|
487
|
+
|
|
488
|
+
try:
|
|
489
|
+
validate_override(args.review_override_sha, args.review_override_reason)
|
|
490
|
+
except ValueError as exc:
|
|
491
|
+
parser.error(str(exc))
|
|
460
492
|
|
|
461
493
|
|
|
462
494
|
def _check_prerequisites() -> None:
|
|
@@ -545,7 +577,9 @@ def _post_review(repo: str, args: argparse.Namespace, response: "ReviewResponse"
|
|
|
545
577
|
sys.exit(1)
|
|
546
578
|
|
|
547
579
|
if args.commit_status:
|
|
548
|
-
|
|
580
|
+
# Post to the head that was reviewed; a re-read head could approve an unreviewed commit.
|
|
581
|
+
pinned = response.halt or response.scope
|
|
582
|
+
sha = pinned.head_sha if pinned else args.sha
|
|
549
583
|
if not sha and args.pr:
|
|
550
584
|
pr = client.get_pull_request(repo, args.pr)
|
|
551
585
|
sha = pr["head_sha"]
|
|
@@ -553,7 +587,11 @@ def _post_review(repo: str, args: argparse.Namespace, response: "ReviewResponse"
|
|
|
553
587
|
logger.error("--commit-status could not resolve a head SHA (need --pr or --sha)")
|
|
554
588
|
sys.exit(1)
|
|
555
589
|
state = "success" if response.verdict.value == "APPROVE" else "failure"
|
|
556
|
-
description =
|
|
590
|
+
description = (
|
|
591
|
+
f"Argus: HALT {response.halt.code}"
|
|
592
|
+
if response.halt
|
|
593
|
+
else f"Argus: {response.verdict.value} ({response.risk_level.value} risk)"
|
|
594
|
+
)
|
|
557
595
|
try:
|
|
558
596
|
client.set_commit_status(repo, sha, state, description)
|
|
559
597
|
except Exception as exc: # noqa: BLE001 — surface any GitHub API error clearly
|
|
@@ -633,7 +671,13 @@ def _run_review(parser: argparse.ArgumentParser, args: argparse.Namespace) -> No
|
|
|
633
671
|
|
|
634
672
|
start = time.monotonic()
|
|
635
673
|
try:
|
|
636
|
-
response = asyncio.run(
|
|
674
|
+
response = asyncio.run(
|
|
675
|
+
run(
|
|
676
|
+
request,
|
|
677
|
+
review_override_sha=args.review_override_sha,
|
|
678
|
+
review_override_reason=args.review_override_reason,
|
|
679
|
+
)
|
|
680
|
+
)
|
|
637
681
|
except HistoryBackendConnectivityError as exc:
|
|
638
682
|
# Same clean-exit treatment as _check_settings' missing-secrets
|
|
639
683
|
# case -- a bad ARGUS_DB_URL/ARGUS_HISTORY_DB_PATH is a config
|
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
from functools import lru_cache
|
|
11
11
|
|
|
12
|
+
from pydantic import Field
|
|
12
13
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
13
14
|
|
|
14
15
|
# Single source of truth for the reviewer-subprocess wall-clock budget.
|
|
@@ -60,6 +61,10 @@ class Settings(BaseSettings):
|
|
|
60
61
|
name the way prompts are, so there's nothing to merge. Only
|
|
61
62
|
consulted when the ``prechecks`` extra is installed; see
|
|
62
63
|
``argus.precheck``.
|
|
64
|
+
ARGUS_REVIEWER_DISPATCH_BUDGET: Maximum reviewers one round may dispatch
|
|
65
|
+
(system groups, their specialists, plus 2 always-on). Default 16,
|
|
66
|
+
allowed 3-50. A plan over the budget halts with
|
|
67
|
+
``dispatch_budget_exceeded``; the hard ceiling of 50 never moves.
|
|
63
68
|
ARGUS_STOCK_SEMGREP_PACKS: Comma-separated semgrep registry pack IDs
|
|
64
69
|
(e.g. ``"p/secrets"``) to run alongside (or instead of) a custom
|
|
65
70
|
``ARGUS_RULES_DIR`` -- unlike a local rules directory, each pack
|
|
@@ -189,6 +194,8 @@ class Settings(BaseSettings):
|
|
|
189
194
|
|
|
190
195
|
ARGUS_SESSION_TIMEOUT: int = DEFAULT_ARGUS_SESSION_TIMEOUT_S
|
|
191
196
|
|
|
197
|
+
ARGUS_REVIEWER_DISPATCH_BUDGET: int = Field(16, ge=3, le=50)
|
|
198
|
+
|
|
192
199
|
ARGUS_BENCH_FILE: str | None = None
|
|
193
200
|
ARGUS_NO_BENCH_OVERRIDES: bool = False
|
|
194
201
|
|