argus-code-review 0.3.4__tar.gz → 0.4.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 (162) hide show
  1. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/CHANGELOG.md +8 -1
  2. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/PKG-INFO +1 -1
  3. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/gemini_runner.py +17 -9
  4. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_gemini_runner.py +30 -0
  5. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/.gitignore +0 -0
  6. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/LICENSE +0 -0
  7. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/README.md +0 -0
  8. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/__init__.py +0 -0
  9. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/bench.py +0 -0
  10. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/bench_default.toml +0 -0
  11. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/cli.py +0 -0
  12. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/config.py +0 -0
  13. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/coverage.py +0 -0
  14. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/dotenv_utils.py +0 -0
  15. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/gemini_cache.py +0 -0
  16. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/github_client.py +0 -0
  17. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/graph.py +0 -0
  18. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/helpers.py +0 -0
  19. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/llm/models.py +0 -0
  20. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/llm/output_models.py +0 -0
  21. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/llm/pricing.py +0 -0
  22. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/llm/usage.py +0 -0
  23. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/models.py +0 -0
  24. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/openai_client.py +0 -0
  25. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/openai_runner.py +0 -0
  26. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/pipeline_models.py +0 -0
  27. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/__init__.py +0 -0
  28. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/actions_scanner.py +0 -0
  29. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/engine.py +0 -0
  30. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/eslint_bundle/.gitignore +0 -0
  31. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/eslint_bundle/README.md +0 -0
  32. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/eslint_bundle/eslint.config.js +0 -0
  33. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/eslint_bundle/package-lock.json +0 -0
  34. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/eslint_bundle/package.json +0 -0
  35. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/js_scanner.py +0 -0
  36. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/migration_scanner.py +0 -0
  37. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/rules/README.md +0 -0
  38. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/sarif.py +0 -0
  39. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/scanner_utils.py +0 -0
  40. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/secrets_scanner.py +0 -0
  41. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/shadow.py +0 -0
  42. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/terraform_scanner.py +0 -0
  43. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/precheck/workflow_lint_scanner.py +0 -0
  44. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/__init__.py +0 -0
  45. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-blocking-validator.md +0 -0
  46. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-coverage-check.md +0 -0
  47. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-cross-cutting.md +0 -0
  48. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-feedback-verifier.md +0 -0
  49. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-lite.md +0 -0
  50. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-planner.md +0 -0
  51. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-preflight-router.md +0 -0
  52. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-prior-art.md +0 -0
  53. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-scope.md +0 -0
  54. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-deployment.md +0 -0
  55. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-frontend.md +0 -0
  56. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-infra.md +0 -0
  57. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-llm-patterns.md +0 -0
  58. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-observability.md +0 -0
  59. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-orchestration.md +0 -0
  60. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-security.md +0 -0
  61. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-slackbot.md +0 -0
  62. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-specialist-sql.md +0 -0
  63. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-subagent.md +0 -0
  64. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-tests-and-docs.md +0 -0
  65. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts/pr-review-writer.md +0 -0
  66. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/prompts_runtime.py +0 -0
  67. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/repo_provision.py +0 -0
  68. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/review_tools.py +0 -0
  69. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/runners.py +0 -0
  70. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/scope.py +0 -0
  71. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/__init__.py +0 -0
  72. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/http.py +0 -0
  73. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/models.py +0 -0
  74. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/precheck.py +0 -0
  75. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/resolver.py +0 -0
  76. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/session.py +0 -0
  77. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/sql.py +0 -0
  78. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/argus/storage/sqlite.py +0 -0
  79. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/pyproject.toml +0 -0
  80. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/008_add_code_reviews.sql +0 -0
  81. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/009_add_reviewer_version.sql +0 -0
  82. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/010_add_review_patterns.sql +0 -0
  83. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/011_add_review_progress_columns.sql +0 -0
  84. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/015_create_agent_runs.sql +0 -0
  85. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/016_add_agent_runs_failure_reason.sql +0 -0
  86. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/017_add_precheck_rules.sql +0 -0
  87. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/schema/018_widen_agent_runs_failure_reason.sql +0 -0
  88. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/__init__.py +0 -0
  89. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/conftest.py +0 -0
  90. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/golden/review_response.schema.json +0 -0
  91. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/__init__.py +0 -0
  92. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_backend_contract.py +0 -0
  93. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_http.py +0 -0
  94. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_models.py +0 -0
  95. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_resolver.py +0 -0
  96. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_session.py +0 -0
  97. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_sql.py +0 -0
  98. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/storage/test_sqlite_backend.py +0 -0
  99. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_actions_scanner.py +0 -0
  100. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_argus_review_local.py +0 -0
  101. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_bench.py +0 -0
  102. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_bench_config_guard.py +0 -0
  103. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_catchup_gate.py +0 -0
  104. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_cli_args.py +0 -0
  105. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_cli_output_contract.py +0 -0
  106. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_cli_post_review.py +0 -0
  107. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_cli_preflight.py +0 -0
  108. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_cli_prompts.py +0 -0
  109. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_config.py +0 -0
  110. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_conftest.py +0 -0
  111. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_dotenv_utils.py +0 -0
  112. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_failure_diagnostics.py +0 -0
  113. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_gemini_cache.py +0 -0
  114. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_gemini_http_retry.py +0 -0
  115. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_github_client_checks_signal.py +0 -0
  116. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_github_client_write.py +0 -0
  117. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_fetch_diff.py +0 -0
  118. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_get_llm_temperature.py +0 -0
  119. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_http_guards.py +0 -0
  120. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_precheck.py +0 -0
  121. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_preflight_image_bump.py +0 -0
  122. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_progress.py +0 -0
  123. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_storage_resolution.py +0 -0
  124. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_graph_timeout_surfacing.py +0 -0
  125. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_js_scanner.py +0 -0
  126. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_llm_models.py +0 -0
  127. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_llm_models_override.py +0 -0
  128. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_llm_pricing.py +0 -0
  129. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_migration_scanner.py +0 -0
  130. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_models.py +0 -0
  131. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_multi_round.py +0 -0
  132. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_openai_client.py +0 -0
  133. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_openai_runner.py +0 -0
  134. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_output_models.py +0 -0
  135. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_packaging.py +0 -0
  136. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_plan_review.py +0 -0
  137. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_precheck_engine.py +0 -0
  138. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_precheck_engine_integration.py +0 -0
  139. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_precheck_sarif.py +0 -0
  140. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_precheck_shadow.py +0 -0
  141. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_precheck_shadow_integration.py +0 -0
  142. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_prompts.py +0 -0
  143. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_repo_provision.py +0 -0
  144. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_review_patterns_integration.py +0 -0
  145. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_review_tools.py +0 -0
  146. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_runners_context7.py +0 -0
  147. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_runners_context_usage.py +0 -0
  148. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_runners_helpers.py +0 -0
  149. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_runners_new.py +0 -0
  150. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_runners_turn_budget.py +0 -0
  151. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_scanner_utils.py +0 -0
  152. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_scope.py +0 -0
  153. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_scope_gate.py +0 -0
  154. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_sdk_bundled_cli_version.py +0 -0
  155. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_secrets_scanner.py +0 -0
  156. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_specialist_validation.py +0 -0
  157. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_stage_costs.py +0 -0
  158. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_storage_precheck.py +0 -0
  159. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_structured_output_methods.py +0 -0
  160. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_terraform_scanner.py +0 -0
  161. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_terraform_scanner_integration.py +0 -0
  162. {argus_code_review-0.3.4 → argus_code_review-0.4.0}/tests/test_workflow_lint_scanner.py +0 -0
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-10-28
11
+
12
+ ### Changed
13
+
14
+ - Gemini `caching = "auto"` (the packaged default for the bulk reviewers) no longer creates an explicit context cache; only `"on"` does. Explicit caching held just the system prompt and tools (about 1-3k tokens) and Gemini then reported only that slice as cached on every turn, while the growing conversation (the bulk of each request) was billed uncached. With no explicit cache, Gemini's automatic prefix caching applies to the whole repeated prefix. In paired live runs of the same PR the reported cached share of prompt tokens went from about 7% to about 90% (total prompt tokens about equal, verdicts and finding counts equivalent), and Argus's own cost estimate for the review fell from $12.66 to $3.20. That estimate is computed from the reported `cached_content_token_count`, not from a billing export, and Google does not document how automatic cache hits interact with `cached_content`, so treat the savings as unconfirmed. Because the default behavior of `auto` changes, this ships as a minor release (0.4.0). `caching = "on"` keeps the previous explicit-cache behavior.
15
+
10
16
  ## [0.3.4] - 2026-10-23
11
17
 
12
18
  ### Fixed
@@ -457,7 +463,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
457
463
  packaged set.
458
464
  - `argus --version`, `argus prompts list`, and `argus prompts export`.
459
465
 
460
- [Unreleased]: https://github.com/redesignhealth/argus-review/compare/v0.3.4...HEAD
466
+ [Unreleased]: https://github.com/redesignhealth/argus-review/compare/v0.4.0...HEAD
467
+ [0.4.0]: https://github.com/redesignhealth/argus-review/compare/v0.3.4...v0.4.0
461
468
  [0.3.4]: https://github.com/redesignhealth/argus-review/compare/v0.3.3...v0.3.4
462
469
  [0.3.3]: https://github.com/redesignhealth/argus-review/compare/v0.3.2...v0.3.3
463
470
  [0.3.2]: https://github.com/redesignhealth/argus-review/compare/v0.3.1...v0.3.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: argus-code-review
3
- Version: 0.3.4
3
+ Version: 0.4.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
@@ -54,7 +54,7 @@ key so that function's own ``group_name`` fallback still applies
54
54
  (this runner has no access to the caller's ``group.name`` -- only to
55
55
  ``entry.role``, which is a different, bench-level identifier).
56
56
 
57
- Explicit context caching (``entry.caching in {"auto", "on"}``) is
57
+ Explicit context caching (``entry.caching == "on"``) is
58
58
  strictly best-effort: Gemini's explicit-cache API has a minimum
59
59
  content-size requirement a short prompt plus this small a toolset might
60
60
  not clear, so any exception raised while creating/reusing a cache is
@@ -177,14 +177,22 @@ logger = logging.getLogger(__name__)
177
177
 
178
178
  _MAX_TURNS_GEMINI = 100 # raised from 45 -- see TECH-6558
179
179
 
180
- # Both "auto" and "on" attempt explicit caching today -- there is no
181
- # separate heuristic distinguishing them yet (Track 1 defined the
182
- # `caching` values without one; see argus.bench's `_VALID_CACHING`). The
183
- # graceful-degradation try/except in `_maybe_activate_cache` is what
184
- # actually protects a caller who set "auto" against a too-small
185
- # prompt+toolset that can't clear Gemini's minimum cache-content-size
186
- # requirement. "off" skips caching entirely.
187
- _CACHE_ENABLED_VALUES = frozenset({"auto", "on"})
180
+ # Only "on" creates an explicit cache. "auto" (the packaged default) and "off"
181
+ # both send the whole request inline and leave caching to Gemini's own
182
+ # automatic prefix caching, which is enabled by default on current models.
183
+ #
184
+ # Why "auto" is not explicit: an explicit cache holds only what is placed in
185
+ # it at creation time (here the system prompt, tools and tool config, about
186
+ # 1-3k tokens), and a request that references it ("cached_content=") must
187
+ # not also carry those three fields. Every turn's growing conversation
188
+ # (the diff plus all prior tool results) is then sent as ordinary
189
+ # `contents`. In live A/B runs of the same PR,
190
+ # explicit caching reported ~7% cached prompt tokens (exactly the cache size
191
+ # on every turn) while caching="off" reported ~90%, with the same total
192
+ # prompt volume. The graceful-degradation try/except in
193
+ # `_maybe_activate_cache` still protects a caller who sets "on" against a
194
+ # prompt+toolset that cannot clear Gemini's minimum cache size.
195
+ _CACHE_ENABLED_VALUES = frozenset({"on"})
188
196
 
189
197
  _DEFAULT_READ_LIMIT = 2000 # mirrors argus.review_tools._DEFAULT_READ_LIMIT
190
198
 
@@ -606,6 +606,36 @@ class TestCacheActivation:
606
606
  assert request_config.tools is None
607
607
  assert request_config.tool_config is None
608
608
 
609
+ async def test_cache_auto_never_calls_caches_create(self) -> None:
610
+ # "auto" leaves caching to Gemini's automatic prefix caching: it must
611
+ # NOT create or reference an explicit cache, because a request that
612
+ # references one carries only the cache's static prefix and the
613
+ # growing conversation is then billed uncached.
614
+ entry = _make_entry(caching="auto")
615
+ settings = _make_settings()
616
+
617
+ response = _make_response(calls=[("finish_review", {"files_explored": []})])
618
+ fake_client = _make_fake_client([response], cache_name="cachedContents/should-not-be-used")
619
+
620
+ with patch("argus.gemini_runner.genai.Client", return_value=fake_client):
621
+ await run_session_gemini(
622
+ entry=entry,
623
+ system_prompt="sys",
624
+ user_message="msg",
625
+ settings=settings,
626
+ repo_root="/tmp/does-not-need-to-exist",
627
+ )
628
+
629
+ fake_client.caches.create.assert_not_called()
630
+ generate_kwargs = fake_client.aio.models.generate_content.await_args.kwargs
631
+ assert generate_kwargs["config"].system_instruction == _with_turn_budget_line("sys")
632
+ assert generate_kwargs["config"].cached_content is None
633
+ # With no cache to carry them, tools and the forced tool_config must be
634
+ # sent inline on the request.
635
+ assert generate_kwargs["config"].tools is not None
636
+ assert generate_kwargs["config"].tool_config is not None
637
+ assert generate_kwargs["config"].tool_config.function_calling_config.mode == "ANY"
638
+
609
639
  async def test_cache_off_never_calls_caches_create(self) -> None:
610
640
  entry = _make_entry(caching="off")
611
641
  settings = _make_settings()