codegraph-brain 0.14.1__tar.gz → 0.16.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 (336) hide show
  1. codegraph_brain-0.16.0/.github/test-count-baseline +1 -0
  2. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.github/workflows/ci.yml +19 -0
  3. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.github/workflows/guardian.yml +6 -0
  4. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.gitignore +1 -0
  5. codegraph_brain-0.16.0/.release-please-manifest.json +3 -0
  6. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/CHANGELOG.md +19 -0
  7. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/PKG-INFO +1 -1
  8. codegraph_brain-0.16.0/benchmarks/guardian/experiments/246-cross-vendor/README.md +71 -0
  9. codegraph_brain-0.16.0/benchmarks/guardian/experiments/246-cross-vendor/free-nemotron-quota-cutoff.jsonl +74 -0
  10. codegraph_brain-0.16.0/benchmarks/guardian/experiments/401-evidence/README.md +140 -0
  11. codegraph_brain-0.16.0/benchmarks/guardian/experiments/401-evidence/pr-399-control-rows.jsonl +24 -0
  12. codegraph_brain-0.16.0/benchmarks/guardian/experiments/401-evidence/pr-399-recording.json +1 -0
  13. codegraph_brain-0.16.0/benchmarks/guardian/experiments/401-evidence/pr-399-treatment-rows.jsonl +24 -0
  14. codegraph_brain-0.16.0/benchmarks/guardian/experiments/407-no-checker-appeal/README.md +106 -0
  15. codegraph_brain-0.16.0/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-directive-rows.jsonl +24 -0
  16. codegraph_brain-0.16.0/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-prohibition-rows.jsonl +24 -0
  17. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/pyproject.toml +1 -1
  18. codegraph_brain-0.16.0/scripts/check_test_count.py +317 -0
  19. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/guardian_bench.py +43 -5
  20. codegraph_brain-0.16.0/scripts/guardian_replay_skeptic.py +382 -0
  21. codegraph_brain-0.16.0/scripts/recordings_from_corpus.py +207 -0
  22. codegraph_brain-0.16.0/scripts/skeptic_arms.py +400 -0
  23. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/python_extractor.py +48 -10
  24. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/axes.py +7 -1
  25. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/chunked.py +9 -1
  26. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/core.py +8 -1
  27. codegraph_brain-0.16.0/src/cgis/guardian/evidence.py +230 -0
  28. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/providers/base.py +1 -1
  29. codegraph_brain-0.16.0/src/cgis/guardian/providers/openrouter.py +233 -0
  30. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/review_fingerprint.py +2 -2
  31. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/runner.py +125 -42
  32. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/skeptic.py +115 -7
  33. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_backfill_calibration_fingerprint.py +43 -0
  34. codegraph_brain-0.16.0/tests/unit/test_check_test_count.py +427 -0
  35. codegraph_brain-0.16.0/tests/unit/test_guardian_evidence.py +423 -0
  36. codegraph_brain-0.16.0/tests/unit/test_guardian_openrouter.py +246 -0
  37. codegraph_brain-0.16.0/tests/unit/test_guardian_replay_skeptic.py +536 -0
  38. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_runner.py +70 -3
  39. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_skeptic.py +101 -10
  40. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_python_extractor.py +36 -0
  41. codegraph_brain-0.16.0/tests/unit/test_recordings_from_corpus.py +245 -0
  42. codegraph_brain-0.16.0/tests/unit/test_skeptic_arms.py +458 -0
  43. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/uv.lock +1 -1
  44. codegraph_brain-0.14.1/.release-please-manifest.json +0 -3
  45. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.claude-plugin/marketplace.json +0 -0
  46. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.gitattributes +0 -0
  47. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.github/workflows/autodoc.yml +0 -0
  48. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.github/workflows/pr-title.yml +0 -0
  49. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.github/workflows/release-please.yml +0 -0
  50. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.pre-commit-config.yaml +0 -0
  51. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/.python-version +0 -0
  52. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/CLAUDE.md +0 -0
  53. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/CONTRIBUTING.md +0 -0
  54. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/LICENSE +0 -0
  55. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/Makefile +0 -0
  56. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/PRIVACY.md +0 -0
  57. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/README.md +0 -0
  58. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/CURATION.md +0 -0
  59. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/calibration.jsonl +0 -0
  60. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-122.yaml +0 -0
  61. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-140.yaml +0 -0
  62. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-141.yaml +0 -0
  63. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-142.yaml +0 -0
  64. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-143.yaml +0 -0
  65. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-144.yaml +0 -0
  66. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-278.yaml +0 -0
  67. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/pr-313.yaml +0 -0
  68. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/guardian/results.jsonl +0 -0
  69. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/README.md +0 -0
  70. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/cal_dot_com.json +0 -0
  71. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/discourse.json +0 -0
  72. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/grafana.json +0 -0
  73. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/keycloak.json +0 -0
  74. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian/sentry.json +0 -0
  75. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-judged.jsonl +0 -0
  76. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-p3-judged-run1.jsonl +0 -0
  77. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-p3-judged-run1.jsonl.corrupted-backup +0 -0
  78. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-p3-run1.jsonl +0 -0
  79. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-p3-run2.jsonl +0 -0
  80. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-p3-run3.jsonl +0 -0
  81. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-plan.json +0 -0
  82. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-repeat-judged.jsonl +0 -0
  83. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-repeat-reviews.jsonl +0 -0
  84. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/benchmarks/martian-reviews.jsonl +0 -0
  85. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/data/.gitkeep +0 -0
  86. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/AUDIT.md +0 -0
  87. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/CASE_STUDY.md +0 -0
  88. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/GUARDIAN_LOCAL_BENCH.md +0 -0
  89. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/GUARDIAN_REMOTE_OLLAMA.md +0 -0
  90. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/HOW_IT_WORKS.md +0 -0
  91. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/ONTOLOGY.md +0 -0
  92. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/PATTERNS_AND_TRIADS.md +0 -0
  93. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/SELF_PORTRAIT.md +0 -0
  94. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/diagrams/pipeline_flow.mermaid +0 -0
  95. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/architecture/health_badge.json +0 -0
  96. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/assets/.gitignore +0 -0
  97. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/assets/cgis-app-avatar.png +0 -0
  98. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/assets/cgis-app-avatar.svg +0 -0
  99. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/assets/generate_avatar.py +0 -0
  100. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/examples/.gitkeep +0 -0
  101. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/how-to/AGENT_ONBOARDING.md +0 -0
  102. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/how-to/CLI_USAGE.md +0 -0
  103. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/how-to/MCP_REFERENCE.md +0 -0
  104. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/lab-notes/2026-06-11-chunked-review-negative-result.md +0 -0
  105. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/ontology/.gitkeep +0 -0
  106. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/ontology/core.yaml +0 -0
  107. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/ontology/domains.yaml +0 -0
  108. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/ontology/patterns.yaml +0 -0
  109. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/ontology/tolerances.lock +0 -0
  110. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-09-domain-pattern-fingerprint-design.md +0 -0
  111. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-09-pattern-alphabet-motif-basis-design.md +0 -0
  112. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-10-guardian-sprint-design.md +0 -0
  113. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-fastapi-di-edges-design.md +0 -0
  114. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-guardian-chunked-review-design.md +0 -0
  115. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-guardian-chunker-design.md +0 -0
  116. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-mcp-drift-validate-fqn-design.md +0 -0
  117. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-resolver-split-design.md +0 -0
  118. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-11-symbol-import-edges-design.md +0 -0
  119. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-12-drift-empty-domains-design.md +0 -0
  120. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-12-gate-semantics-design.md +0 -0
  121. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-12-init-ontology-design.md +0 -0
  122. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-12-release-please-ci-design.md +0 -0
  123. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-13-suggest-packages-design.md +0 -0
  124. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-06-13-tangle-anti-pattern-design.md +0 -0
  125. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-29-guardian-skeptic-scoring-design.md +0 -0
  126. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-cgis-fractal-design.md +0 -0
  127. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-cgis-fractal-plan.md +0 -0
  128. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-chunk-source-filter-design.md +0 -0
  129. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-chunk-source-filter-plan.md +0 -0
  130. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-genai-client-close-design.md +0 -0
  131. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-genai-client-close-plan.md +0 -0
  132. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-guardian-precision-bench-design.md +0 -0
  133. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-guardian-precision-bench-plan.md +0 -0
  134. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-guardian-timeout-retry-design.md +0 -0
  135. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-30-guardian-timeout-retry-plan.md +0 -0
  136. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-07-31-finder-bug-class-taxonomy.md +0 -0
  137. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-08-01-aura-autoevolution-poc.md +0 -0
  138. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-08-11-guardian-code-review-bench.md +0 -0
  139. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/2026-08-14-review-fingerprint-design.md +0 -0
  140. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/BLUEPRINT.md +0 -0
  141. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/PRD.md +0 -0
  142. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/TDD.md +0 -0
  143. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-09-fingerprint-drift.md +0 -0
  144. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md +0 -0
  145. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-10-guardian-structured-findings-bench.md +0 -0
  146. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-10-motif-basis-part-b.md +0 -0
  147. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-10-unified-pattern-alphabet.md +0 -0
  148. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-11-fastapi-di-edges.md +0 -0
  149. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-11-guardian-chunked-review.md +0 -0
  150. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-11-guardian-chunker.md +0 -0
  151. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-11-mcp-drift-validate-fqn.md +0 -0
  152. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-11-resolver-split.md +0 -0
  153. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-12-drift-empty-domains.md +0 -0
  154. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-12-gate-semantics.md +0 -0
  155. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-12-init-ontology.md +0 -0
  156. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-12-release-please-ci.md +0 -0
  157. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-12-symbol-import-edges.md +0 -0
  158. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-06-13-suggest-packages.md +0 -0
  159. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-07-29-guardian-skeptic-scoring.md +0 -0
  160. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/docs/specs/plans/2026-08-14-review-fingerprint.md +0 -0
  161. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/main.py +0 -0
  162. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/plugin/.claude-plugin/plugin.json +0 -0
  163. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/plugin/.mcp.json +0 -0
  164. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/plugin/README.md +0 -0
  165. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/plugin/skills/cgis/SKILL.md +0 -0
  166. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/plugin/skills/ingest/SKILL.md +0 -0
  167. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/release-please-config.json +0 -0
  168. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/backfill_calibration_fingerprint.py +0 -0
  169. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/backfill_review_fingerprint.py +0 -0
  170. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/check_pytest_raises.py +0 -0
  171. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/colab_bench.sh +0 -0
  172. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/gen_ideal_graph.py +0 -0
  173. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/generate_health.py +0 -0
  174. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/generate_mcp_ref.py +0 -0
  175. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/generate_schema_docs.py +0 -0
  176. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/guardian_calibrate.py +0 -0
  177. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/guardian_martian.py +0 -0
  178. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/guardian_review.py +0 -0
  179. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/inject_readme_graph.py +0 -0
  180. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/ollama_visitor.sh +0 -0
  181. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/probe_closure_gap.py +0 -0
  182. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/scripts/probe_tier_ladder.py +0 -0
  183. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/__init__.py +0 -0
  184. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/__main__.py +0 -0
  185. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/api/.gitkeep +0 -0
  186. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/api/__init__.py +0 -0
  187. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/api/mcp_server.py +0 -0
  188. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/cli.py +0 -0
  189. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/core/.gitkeep +0 -0
  190. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/core/models.py +0 -0
  191. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/.gitkeep +0 -0
  192. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/_python_ast.py +0 -0
  193. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/_python_classes.py +0 -0
  194. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/_python_functions.py +0 -0
  195. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/_python_imports.py +0 -0
  196. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/_python_types.py +0 -0
  197. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/base.py +0 -0
  198. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/registry.py +0 -0
  199. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/extractors/typescript_extractor.py +0 -0
  200. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/__init__.py +0 -0
  201. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/bench.py +0 -0
  202. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/calibrate.py +0 -0
  203. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/chunker.py +0 -0
  204. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/collector.py +0 -0
  205. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/diff_index.py +0 -0
  206. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/findings.py +0 -0
  207. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/github_poster.py +0 -0
  208. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/martian.py +0 -0
  209. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/metrics.py +0 -0
  210. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/prompts.py +0 -0
  211. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/providers/__init__.py +0 -0
  212. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/providers/gemini.py +0 -0
  213. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/providers/mistral.py +0 -0
  214. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/providers/ollama.py +0 -0
  215. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/recording.py +0 -0
  216. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/guardian/render.py +0 -0
  217. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/pipeline.py +0 -0
  218. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/py.typed +0 -0
  219. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/__init__.py +0 -0
  220. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/analyzer.py +0 -0
  221. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/anomaly.py +0 -0
  222. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/cohesion.py +0 -0
  223. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/health.py +0 -0
  224. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/analysis/suggest_service.py +0 -0
  225. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/context/__init__.py +0 -0
  226. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/context/audit.py +0 -0
  227. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/context/context_service.py +0 -0
  228. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/context/prompt.py +0 -0
  229. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/context/snippet.py +0 -0
  230. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/__init__.py +0 -0
  231. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/_scc.py +0 -0
  232. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/drift.py +0 -0
  233. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/drift_service.py +0 -0
  234. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/fingerprint.py +0 -0
  235. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/fractal.py +0 -0
  236. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/ontology_init.py +0 -0
  237. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/quotient.py +0 -0
  238. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/drift/triads.py +0 -0
  239. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/engine.py +0 -0
  240. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/fqn.py +0 -0
  241. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/render/__init__.py +0 -0
  242. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/render/graph_json.py +0 -0
  243. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/render/mermaid.py +0 -0
  244. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/query/render/metrics.py +0 -0
  245. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/.gitkeep +0 -0
  246. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/__init__.py +0 -0
  247. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/engine.py +0 -0
  248. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/indices.py +0 -0
  249. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/symbols.py +0 -0
  250. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/resolver/uplift.py +0 -0
  251. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/storage/.gitkeep +0 -0
  252. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/src/cgis/storage/sqlite_store.py +0 -0
  253. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/integration/.gitkeep +0 -0
  254. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/.gitkeep +0 -0
  255. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/__init__.py +0 -0
  256. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/conftest.py +0 -0
  257. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_architecture.py +0 -0
  258. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_drift.py +0 -0
  259. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_fractal.py +0 -0
  260. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_init_ontology_roundtrip.py +0 -0
  261. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_self_parse.py +0 -0
  262. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_self_parse_ts.py +0 -0
  263. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/self_parsing/test_suggest.py +0 -0
  264. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/.gitkeep +0 -0
  265. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/conftest.py +0 -0
  266. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/guardian_stubs.py +0 -0
  267. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/review_path_inventory.txt +0 -0
  268. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test___main__.py +0 -0
  269. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_analyzer.py +0 -0
  270. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_audit.py +0 -0
  271. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_backfill_review_fingerprint.py +0 -0
  272. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_check_pytest_raises.py +0 -0
  273. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_cli.py +0 -0
  274. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_cohesion.py +0 -0
  275. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_context_service.py +0 -0
  276. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_di_acceptance.py +0 -0
  277. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_drift.py +0 -0
  278. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_drift_service.py +0 -0
  279. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_extractor_registry.py +0 -0
  280. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_fingerprint.py +0 -0
  281. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_fqn.py +0 -0
  282. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_fractal.py +0 -0
  283. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_gen_ideal_graph.py +0 -0
  284. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_generate_mcp_ref.py +0 -0
  285. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_graph_json.py +0 -0
  286. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_axes.py +0 -0
  287. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_bench.py +0 -0
  288. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_bench_script.py +0 -0
  289. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_calibrate.py +0 -0
  290. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_calibrate_script.py +0 -0
  291. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_chunked.py +0 -0
  292. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_chunker.py +0 -0
  293. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_collector.py +0 -0
  294. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_core.py +0 -0
  295. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_diff_index.py +0 -0
  296. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_findings.py +0 -0
  297. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_martian.py +0 -0
  298. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_martian_script.py +0 -0
  299. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_martian_union.py +0 -0
  300. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_metrics.py +0 -0
  301. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_mistral_sampling.py +0 -0
  302. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_ollama_sampling.py +0 -0
  303. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_ollama_truncation.py +0 -0
  304. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_poster.py +0 -0
  305. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_providers.py +0 -0
  306. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_providers_name.py +0 -0
  307. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_recording.py +0 -0
  308. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_render.py +0 -0
  309. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_review_script.py +0 -0
  310. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_guardian_salvage.py +0 -0
  311. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_health_scorer.py +0 -0
  312. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_import_acceptance.py +0 -0
  313. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_mcp_server.py +0 -0
  314. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_mermaid.py +0 -0
  315. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_metrics.py +0 -0
  316. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_models.py +0 -0
  317. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_ontology_compliance.py +0 -0
  318. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_ontology_init.py +0 -0
  319. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_patterns_yaml.py +0 -0
  320. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_pipeline.py +0 -0
  321. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_prompt.py +0 -0
  322. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_quotient.py +0 -0
  323. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_resolver.py +0 -0
  324. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_resolver_indices.py +0 -0
  325. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_resolver_symbols.py +0 -0
  326. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_review_fingerprint_closure.py +0 -0
  327. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_review_fingerprint_contract.py +0 -0
  328. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_review_fingerprint_digest.py +0 -0
  329. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_review_fingerprint_record.py +0 -0
  330. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_snippet.py +0 -0
  331. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_sqlite_store.py +0 -0
  332. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_suggest_service.py +0 -0
  333. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_temperature_source.py +0 -0
  334. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_triads.py +0 -0
  335. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_typescript_extractor.py +0 -0
  336. {codegraph_brain-0.14.1 → codegraph_brain-0.16.0}/tests/unit/test_uplift.py +0 -0
@@ -67,6 +67,25 @@ jobs:
67
67
  uv run --frozen pytest --cov=cgis --cov=scripts
68
68
  --cov-report=term-missing --cov-report=xml
69
69
 
70
+ - name: Test-count floor
71
+ # Deliberately a workflow step and not a test (#405). On 2026-08-17 a
72
+ # stale-tree push deleted 24 test files and 5 modules under src/cgis,
73
+ # and the step above passed: the tests that would have failed went with
74
+ # them. Every floor the repository had lived inside a test file, so the
75
+ # push that tripped them also removed them.
76
+ #
77
+ # The floor is read from the *base branch*, not from this checkout — a
78
+ # stale tree carries a stale baseline, and comparing the branch against
79
+ # its own copy passes the exact incident above. `fetch-depth: 0` on the
80
+ # checkout is what makes origin/<base> readable here.
81
+ #
82
+ # `github.base_ref` is set on pull_request only; on a push to the trunk
83
+ # it is empty and ref_name is the branch being pushed, which is the
84
+ # right comparison there too.
85
+ run: >
86
+ uv run --frozen python scripts/check_test_count.py
87
+ --base-ref "origin/${{ github.base_ref || github.ref_name }}"
88
+
70
89
  - name: Project version for Sonar
71
90
  id: version
72
91
  # Without this every analysis records the version as the literal string
@@ -90,6 +90,12 @@ jobs:
90
90
  GUARDIAN_FEATURES: ${{ vars.GUARDIAN_FEATURES }}
91
91
  GUARDIAN_SKEPTIC: ${{ vars.GUARDIAN_SKEPTIC }}
92
92
  GUARDIAN_SKEPTIC_MODEL: ${{ vars.GUARDIAN_SKEPTIC_MODEL }}
93
+ # Static-evidence pass for the skeptic (#401). Wired but not set:
94
+ # the repository variable is deliberately absent, so enabling it is a
95
+ # decision made in repo settings rather than a code change nobody
96
+ # reviews. An unset variable expands to "", which the flag reads as
97
+ # off — only the literal "1" enables it.
98
+ GUARDIAN_EVIDENCE: ${{ vars.GUARDIAN_EVIDENCE }}
93
99
  run: |
94
100
  uv run --frozen python scripts/guardian_review.py \
95
101
  --output guardian_report.md \
@@ -230,3 +230,4 @@ guardian_metrics.jsonl
230
230
  *.db-wal
231
231
  *.db-shm
232
232
  .martian-workspace/
233
+ .guardian-recordings/
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.16.0"
3
+ }
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.15.0...codegraph-brain-v0.16.0) (2026-08-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * **bench:** a control arm, so an evidence result can be attributed ([#401](https://github.com/zaebee/codegraph-brain/issues/401)) ([#406](https://github.com/zaebee/codegraph-brain/issues/406)) ([241dbae](https://github.com/zaebee/codegraph-brain/commit/241dbae334be897cb6bf3d151d097b64ab5a56e7))
9
+ * **bench:** both skeptics over the same frozen passes, and the evidence bench replay dropped ([#246](https://github.com/zaebee/codegraph-brain/issues/246)) ([#411](https://github.com/zaebee/codegraph-brain/issues/411)) ([2c1d50b](https://github.com/zaebee/codegraph-brain/commit/2c1d50b2abb18b0c0bad1a9b46f71531eebba16c))
10
+ * **ci:** a floor under the size of the test suite itself ([#405](https://github.com/zaebee/codegraph-brain/issues/405)) ([#409](https://github.com/zaebee/codegraph-brain/issues/409)) ([0fbcbac](https://github.com/zaebee/codegraph-brain/commit/0fbcbac573651591750f017e3793b692c05377ce))
11
+ * **guardian:** tell the skeptic when no checker ran, and which verdict that takes ([#407](https://github.com/zaebee/codegraph-brain/issues/407)) ([#410](https://github.com/zaebee/codegraph-brain/issues/410)) ([2470ddb](https://github.com/zaebee/codegraph-brain/commit/2470ddb45a29f19e2abf90d2f6ce5b5fadad09f3))
12
+
13
+ ## [0.15.0](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.14.1...codegraph-brain-v0.15.0) (2026-08-17)
14
+
15
+
16
+ ### Features
17
+
18
+ * **bench:** rebuild frozen finder passes from the corpus, free ([#246](https://github.com/zaebee/codegraph-brain/issues/246)) ([#399](https://github.com/zaebee/codegraph-brain/issues/399)) ([b73f6e0](https://github.com/zaebee/codegraph-brain/commit/b73f6e0d40c5bdc4dadca4acd468d7835670be28))
19
+ * **guardian:** a replay arm that pairs each finding against its own baseline ([#401](https://github.com/zaebee/codegraph-brain/issues/401)) ([#404](https://github.com/zaebee/codegraph-brain/issues/404)) ([b2ab59a](https://github.com/zaebee/codegraph-brain/commit/b2ab59a8d7b5f62a307874b8a0eb9573273fa0ea))
20
+ * **guardian:** let the skeptic see what the checkers say ([#401](https://github.com/zaebee/codegraph-brain/issues/401)) ([#402](https://github.com/zaebee/codegraph-brain/issues/402)) ([af82147](https://github.com/zaebee/codegraph-brain/commit/af821473080bd3a717679e36c90164a43ca07f7b))
21
+
3
22
  ## [0.14.1](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.14.0...codegraph-brain-v0.14.1) (2026-08-16)
4
23
 
5
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codegraph-brain
3
- Version: 0.14.1
3
+ Version: 0.16.0
4
4
  Summary: Semantic code graph for AI agents — deterministic FQN resolution, impact analysis and architectural drift gates, exposed over MCP.
5
5
  Project-URL: Homepage, https://github.com/zaebee/codegraph-brain
6
6
  Project-URL: Repository, https://github.com/zaebee/codegraph-brain
@@ -0,0 +1,71 @@
1
+ # Cross-vendor skeptic: still blocked, and now on measured limits (#246)
2
+
3
+ Two attempts at the third arm, both stopped by the validity gate before any
4
+ number was reported. The gate is the deliverable here; the comparison is not.
5
+
6
+ ## Why a gate at all
7
+
8
+ `judge_finding` contains provider errors per finding and returns None, so a
9
+ spent quota, an HTTP 429, a 402 and unparseable JSON all arrive as **the same
10
+ row shape as a skeptic that refused to refute anything** — which is exactly what
11
+ #246 predicts for a same-vendor skeptic. A broken arm would confirm the
12
+ hypothesis. `MAX_UNRULED_RATE` refuses to print a comparison above 5% unruled,
13
+ keeps the rows, and exits 2.
14
+
15
+ It fired on both attempts. Neither produced a number that could be read.
16
+
17
+ ## Attempt 1 — free tier. The quota is 50 requests per day.
18
+
19
+ `nvidia/nemotron-3-super-120b-a12b:free`, the whole corpus: **96 of 135 findings
20
+ unruled**, and the pattern is a cutoff in time rather than a property of the
21
+ input.
22
+
23
+ | PR | evidence | unruled |
24
+ |---|---|---:|
25
+ | 122 (first) | no | **0 / 29** |
26
+ | 140 | yes | 29 / 39 |
27
+ | 141, 142, 143, 144 | — | **100%** |
28
+
29
+ 39 answered, then silence. With the day's earlier probes (4 candidate calls, 6
30
+ in a smoke run) that is 49 successful requests before the wall — the documented
31
+ free allowance is 50/day, and this is that number arrived at from the data.
32
+
33
+ Rows: `free-nemotron-quota-cutoff.jsonl`.
34
+
35
+ ## Attempt 2 — paid. Two separate faults, one after the other.
36
+
37
+ `qwen/qwen3.7-plus`, chosen because capability has to match: comparing
38
+ `gemini-2.5-flash` against a small free model measures strong-versus-weak and
39
+ calls it same-versus-cross.
40
+
41
+ **First fault — thinking.** 118 of 135 unruled. `qwen3.7-plus` puts its chain of
42
+ thought in a separate `reasoning` field and fills `content` only at the end, so
43
+ on the larger prompts it spent the entire 8,000-token budget thinking and
44
+ returned `content: null`. Raising the budget would have fixed the symptom and
45
+ broken the experiment: the arm it is compared against is not doing extended
46
+ thinking, so the two arms would differ in a dimension nobody chose. The provider
47
+ now sends `reasoning: {"enabled": …}` explicitly in both directions, off by
48
+ default, so a run can state what it did.
49
+
50
+ **Second fault — credits.** The re-run failed on HTTP **402**: the account has
51
+ `total_credits: $0` against `total_usage: $0.159`. The trial allowance is spent;
52
+ paid models are unavailable until it is topped up.
53
+
54
+ The second fault took half an hour to identify because the warning read only
55
+ "Skeptic judgement failed; finding stays unruled" — 118 identical lines, no
56
+ type, no message. It now carries both. A quota, a truncated reasoning model and
57
+ a 402 have three different remedies and all three land in that one `except`.
58
+
59
+ ## To unblock
60
+
61
+ 1. **Top up OpenRouter.** The measured cost of the run with reasoning off is
62
+ ~$0.15: 135 findings × ~2,700 prompt tokens at \$0.32/M, plus short
63
+ completions at \$1.28/M. A dollar covers it several times over.
64
+ 2. **Free tier across three days.** The input is a frozen recording, so the run
65
+ is deterministic and can be split — 50 requests a day, 135 needed. Fragile,
66
+ and it needs resume support the tool does not have.
67
+ 3. A local ollama, which this issue already names as the no-cost option.
68
+
69
+ Everything else is in place: the corpus with both finder orientations, the
70
+ recordings, per-arm models, the scoring, and the gate that stopped two wrong
71
+ answers from being published.
@@ -0,0 +1,74 @@
1
+ {"timestamp": "2026-08-17T13:17:43.517549+00:00", "pr": 122, "pass": "122@2026-06-10T20-22-31.032903+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 0, "confirmed": 3, "unruled": 0, "recall": 0.18181818181818182, "precision": 0.6666666666666666, "noise": 1, "killed_gt": []}
2
+ {"timestamp": "2026-08-17T13:18:05.186110+00:00", "pr": 122, "pass": "122@2026-06-10T20-22-31.032903+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.18181818181818182, "precision": 0.6666666666666666, "noise": 1, "killed_gt": []}
3
+ {"timestamp": "2026-08-17T13:18:15.602819+00:00", "pr": 122, "pass": "122@2026-06-10T20-22-59.496508+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
4
+ {"timestamp": "2026-08-17T13:18:24.136220+00:00", "pr": 122, "pass": "122@2026-06-10T20-22-59.496508+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
5
+ {"timestamp": "2026-08-17T13:18:36.000053+00:00", "pr": 122, "pass": "122@2026-06-10T20-23-51.775172+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.18181818181818182, "precision": 1.0, "noise": 0, "killed_gt": []}
6
+ {"timestamp": "2026-08-17T13:18:50.719370+00:00", "pr": 122, "pass": "122@2026-06-10T20-23-51.775172+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 1, "confirmed": 1, "unruled": 0, "recall": 0.18181818181818182, "precision": 1.0, "noise": 0, "killed_gt": []}
7
+ {"timestamp": "2026-08-17T13:19:01.976110+00:00", "pr": 122, "pass": "122@2026-06-10T20-32-35.483908+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 3, "killed_gt": ["file-container-regression"]}
8
+ {"timestamp": "2026-08-17T13:19:23.184478+00:00", "pr": 122, "pass": "122@2026-06-10T20-32-35.483908+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 2, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 3, "killed_gt": ["file-container-regression"]}
9
+ {"timestamp": "2026-08-17T13:19:36.855990+00:00", "pr": 122, "pass": "122@2026-06-10T20-33-10.513615+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 0, "confirmed": 3, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
10
+ {"timestamp": "2026-08-17T13:20:22.191259+00:00", "pr": 122, "pass": "122@2026-06-10T20-33-10.513615+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
11
+ {"timestamp": "2026-08-17T13:20:35.820094+00:00", "pr": 122, "pass": "122@2026-06-10T21-58-22.314534+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": ["file-container-regression"]}
12
+ {"timestamp": "2026-08-17T13:21:08.068793+00:00", "pr": 122, "pass": "122@2026-06-10T21-58-22.314534+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": false, "findings": 4, "refuted": 1, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.09090909090909091, "precision": 0.3333333333333333, "noise": 2, "killed_gt": ["file-container-regression"]}
13
+ {"timestamp": "2026-08-17T13:21:15.458172+00:00", "pr": 122, "pass": "122@2026-06-11T00-11-53.683357+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
14
+ {"timestamp": "2026-08-17T13:21:21.049843+00:00", "pr": 122, "pass": "122@2026-06-11T00-11-53.683357+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
15
+ {"timestamp": "2026-08-17T13:21:29.468118+00:00", "pr": 122, "pass": "122@2026-06-11T00-12-40.927704+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
16
+ {"timestamp": "2026-08-17T13:21:35.271913+00:00", "pr": 122, "pass": "122@2026-06-11T00-12-40.927704+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
17
+ {"timestamp": "2026-08-17T13:21:46.009233+00:00", "pr": 122, "pass": "122@2026-06-11T00-14-36.809184+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.18181818181818182, "precision": 1.0, "noise": 0, "killed_gt": []}
18
+ {"timestamp": "2026-08-17T13:21:58.953594+00:00", "pr": 122, "pass": "122@2026-06-11T00-14-36.809184+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.18181818181818182, "precision": 1.0, "noise": 0, "killed_gt": []}
19
+ {"timestamp": "2026-08-17T13:22:06.863138+00:00", "pr": 122, "pass": "122@2026-06-11T00-32-51.894263+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
20
+ {"timestamp": "2026-08-17T13:22:18.621710+00:00", "pr": 122, "pass": "122@2026-06-11T00-32-51.894263+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
21
+ {"timestamp": "2026-08-17T13:22:34.978570+00:00", "pr": 122, "pass": "122@2026-06-11T00-36-53.749615+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 1, "uncertain": 0, "confirmed": 0, "unruled": 0, "recall": 0.0, "precision": 1.0, "noise": 0, "killed_gt": ["file-container-regression"]}
22
+ {"timestamp": "2026-08-17T13:23:29.360852+00:00", "pr": 122, "pass": "122@2026-06-11T00-36-53.749615+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
23
+ {"timestamp": "2026-08-17T13:23:35.269160+00:00", "pr": 122, "pass": "122@2026-06-11T00-42-55.162925+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
24
+ {"timestamp": "2026-08-17T13:23:43.563281+00:00", "pr": 122, "pass": "122@2026-06-11T00-42-55.162925+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": []}
25
+ {"timestamp": "2026-08-17T13:23:53.848653+00:00", "pr": 122, "pass": "122@2026-06-11T00-48-45.262981+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 2, "refuted": 1, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.09090909090909091, "precision": 1.0, "noise": 0, "killed_gt": ["file-container-regression"]}
26
+ {"timestamp": "2026-08-17T13:24:05.969279+00:00", "pr": 122, "pass": "122@2026-06-11T00-48-45.262981+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.18181818181818182, "precision": 1.0, "noise": 0, "killed_gt": []}
27
+ {"timestamp": "2026-08-17T13:24:25.419473+00:00", "pr": 140, "pass": "140@2026-06-10T20-24-40.504167+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 3, "refuted": 0, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 3, "killed_gt": []}
28
+ {"timestamp": "2026-08-17T13:25:25.250544+00:00", "pr": 140, "pass": "140@2026-06-10T20-24-40.504167+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 3, "refuted": 0, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 3, "killed_gt": []}
29
+ {"timestamp": "2026-08-17T13:25:47.211803+00:00", "pr": 140, "pass": "140@2026-06-10T20-25-19.261202+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 5, "refuted": 2, "uncertain": 1, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 3, "killed_gt": []}
30
+ {"timestamp": "2026-08-17T13:26:24.777165+00:00", "pr": 140, "pass": "140@2026-06-10T20-25-19.261202+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 5, "refuted": 0, "uncertain": 3, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 5, "killed_gt": []}
31
+ {"timestamp": "2026-08-17T13:26:33.938777+00:00", "pr": 140, "pass": "140@2026-06-10T20-26-01.543236+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 2, "killed_gt": []}
32
+ {"timestamp": "2026-08-17T13:27:08.103278+00:00", "pr": 140, "pass": "140@2026-06-10T20-26-01.543236+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 2, "killed_gt": []}
33
+ {"timestamp": "2026-08-17T13:27:17.614733+00:00", "pr": 140, "pass": "140@2026-06-11T00-16-26.605409+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
34
+ {"timestamp": "2026-08-17T13:27:17.769243+00:00", "pr": 140, "pass": "140@2026-06-11T00-16-26.605409+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
35
+ {"timestamp": "2026-08-17T13:27:27.876729+00:00", "pr": 140, "pass": "140@2026-06-11T00-17-25.717492+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 3, "refuted": 0, "uncertain": 0, "confirmed": 3, "unruled": 0, "recall": 0.06666666666666667, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
36
+ {"timestamp": "2026-08-17T13:27:28.068613+00:00", "pr": 140, "pass": "140@2026-06-11T00-17-25.717492+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 3, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 3, "recall": 0.06666666666666667, "precision": 0.3333333333333333, "noise": 2, "killed_gt": []}
37
+ {"timestamp": "2026-08-17T13:27:38.870523+00:00", "pr": 140, "pass": "140@2026-06-11T00-33-44.053747+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.06666666666666667, "precision": 1.0, "noise": 0, "killed_gt": []}
38
+ {"timestamp": "2026-08-17T13:27:39.001629+00:00", "pr": 140, "pass": "140@2026-06-11T00-33-44.053747+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.06666666666666667, "precision": 1.0, "noise": 0, "killed_gt": []}
39
+ {"timestamp": "2026-08-17T13:27:45.424281+00:00", "pr": 140, "pass": "140@2026-06-11T00-37-50.526658+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
40
+ {"timestamp": "2026-08-17T13:27:45.544269+00:00", "pr": 140, "pass": "140@2026-06-11T00-37-50.526658+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
41
+ {"timestamp": "2026-08-17T13:27:53.801567+00:00", "pr": 140, "pass": "140@2026-06-11T00-50-08.134629+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 1, "confirmed": 0, "unruled": 0, "recall": 0.06666666666666667, "precision": 1.0, "noise": 0, "killed_gt": []}
42
+ {"timestamp": "2026-08-17T13:27:53.921093+00:00", "pr": 140, "pass": "140@2026-06-11T00-50-08.134629+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.06666666666666667, "precision": 1.0, "noise": 0, "killed_gt": []}
43
+ {"timestamp": "2026-08-17T13:29:06.369511+00:00", "pr": 140, "pass": "140@2026-07-29T17-29-19.861365+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 22, "refuted": 10, "uncertain": 2, "confirmed": 10, "unruled": 0, "recall": 0.26666666666666666, "precision": 0.3333333333333333, "noise": 8, "killed_gt": ["count-routers-on-squared", "weights-keyerror-custom-yaml"]}
44
+ {"timestamp": "2026-08-17T13:29:07.917533+00:00", "pr": 140, "pass": "140@2026-07-29T17-29-19.861365+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 22, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 22, "recall": 0.4, "precision": 0.2727272727272727, "noise": 16, "killed_gt": []}
45
+ {"timestamp": "2026-08-17T13:29:21.415626+00:00", "pr": 141, "pass": "141@2026-06-10T20-26-53.683221+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 1.0, "precision": 0.0, "noise": 1, "killed_gt": []}
46
+ {"timestamp": "2026-08-17T13:29:21.527539+00:00", "pr": 141, "pass": "141@2026-06-10T20-26-53.683221+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 1.0, "precision": 0.0, "noise": 1, "killed_gt": []}
47
+ {"timestamp": "2026-08-17T13:29:28.243544+00:00", "pr": 141, "pass": "141@2026-06-10T20-29-48.066882+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 1, "confirmed": 0, "unruled": 0, "recall": 1.0, "precision": 0.0, "noise": 1, "killed_gt": []}
48
+ {"timestamp": "2026-08-17T13:29:28.360785+00:00", "pr": 141, "pass": "141@2026-06-10T20-29-48.066882+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 1.0, "precision": 0.0, "noise": 1, "killed_gt": []}
49
+ {"timestamp": "2026-08-17T13:29:37.370316+00:00", "pr": 141, "pass": "141@2026-06-10T21-59-24.111065+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 1.0, "precision": 0.0, "noise": 0, "killed_gt": []}
50
+ {"timestamp": "2026-08-17T13:29:37.495452+00:00", "pr": 141, "pass": "141@2026-06-10T21-59-24.111065+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 1.0, "precision": 0.0, "noise": 0, "killed_gt": []}
51
+ {"timestamp": "2026-08-17T13:29:49.082379+00:00", "pr": 142, "pass": "142@2026-06-10T20-30-15.605690+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.5, "precision": 1.0, "noise": 0, "killed_gt": []}
52
+ {"timestamp": "2026-08-17T13:29:49.243691+00:00", "pr": 142, "pass": "142@2026-06-10T20-30-15.605690+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.5, "precision": 1.0, "noise": 0, "killed_gt": []}
53
+ {"timestamp": "2026-08-17T13:29:56.956875+00:00", "pr": 142, "pass": "142@2026-06-10T21-52-43.992582+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
54
+ {"timestamp": "2026-08-17T13:29:57.130875+00:00", "pr": 142, "pass": "142@2026-06-10T21-52-43.992582+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 2, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
55
+ {"timestamp": "2026-08-17T13:30:04.860920+00:00", "pr": 142, "pass": "142@2026-06-10T21-53-15.240002+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
56
+ {"timestamp": "2026-08-17T13:30:05.012683+00:00", "pr": 142, "pass": "142@2026-06-10T21-53-15.240002+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": false, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
57
+ {"timestamp": "2026-08-17T13:30:14.805023+00:00", "pr": 142, "pass": "142@2026-06-11T00-45-11.791674+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 3, "confirmed": 0, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
58
+ {"timestamp": "2026-08-17T13:30:14.969320+00:00", "pr": 142, "pass": "142@2026-06-11T00-45-11.791674+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 3, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
59
+ {"timestamp": "2026-08-17T13:30:23.741156+00:00", "pr": 142, "pass": "142@2026-06-11T00-50-52.772949+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 3, "refuted": 2, "uncertain": 1, "confirmed": 0, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
60
+ {"timestamp": "2026-08-17T13:30:23.921669+00:00", "pr": 142, "pass": "142@2026-06-11T00-50-52.772949+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": false, "findings": 3, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 3, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
61
+ {"timestamp": "2026-08-17T13:30:43.638312+00:00", "pr": 143, "pass": "143@2026-06-11T00-46-29.982484+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
62
+ {"timestamp": "2026-08-17T13:30:43.909808+00:00", "pr": 143, "pass": "143@2026-06-11T00-46-29.982484+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
63
+ {"timestamp": "2026-08-17T13:32:21.206192+00:00", "pr": 143, "pass": "143@2026-07-29T17-15-00.138863+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 28, "refuted": 8, "uncertain": 1, "confirmed": 19, "unruled": 0, "recall": 1.0, "precision": 0.3, "noise": 14, "killed_gt": []}
64
+ {"timestamp": "2026-08-17T13:32:22.809114+00:00", "pr": 143, "pass": "143@2026-07-29T17-15-00.138863+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 28, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 28, "recall": 1.0, "precision": 0.21428571428571427, "noise": 22, "killed_gt": []}
65
+ {"timestamp": "2026-08-17T13:32:44.357216+00:00", "pr": 144, "pass": "144@2026-06-10T20-32-21.181637+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 2, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 2, "killed_gt": []}
66
+ {"timestamp": "2026-08-17T13:32:44.503817+00:00", "pr": 144, "pass": "144@2026-06-10T20-32-21.181637+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-2.5-flash", "evidence": true, "findings": 2, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 2, "recall": 0.0, "precision": 0.0, "noise": 2, "killed_gt": []}
67
+ {"timestamp": "2026-08-17T13:32:58.741622+00:00", "pr": 144, "pass": "144@2026-06-11T00-25-01.536057+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 1, "uncertain": 0, "confirmed": 0, "unruled": 0, "recall": 0.0, "precision": 1.0, "noise": 0, "killed_gt": []}
68
+ {"timestamp": "2026-08-17T13:32:58.913488+00:00", "pr": 144, "pass": "144@2026-06-11T00-25-01.536057+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 0, "killed_gt": []}
69
+ {"timestamp": "2026-08-17T13:33:06.869381+00:00", "pr": 144, "pass": "144@2026-06-11T00-47-31.514757+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 1, "uncertain": 0, "confirmed": 0, "unruled": 0, "recall": 0.0, "precision": 1.0, "noise": 0, "killed_gt": []}
70
+ {"timestamp": "2026-08-17T13:33:06.990972+00:00", "pr": 144, "pass": "144@2026-06-11T00-47-31.514757+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
71
+ {"timestamp": "2026-08-17T13:33:14.521992+00:00", "pr": 144, "pass": "144@2026-06-11T00-52-31.320750+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 1, "unruled": 0, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
72
+ {"timestamp": "2026-08-17T13:33:14.623054+00:00", "pr": 144, "pass": "144@2026-06-11T00-52-31.320750+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "gemini-3.5-flash", "evidence": true, "findings": 1, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 1, "recall": 0.0, "precision": 0.0, "noise": 1, "killed_gt": []}
73
+ {"timestamp": "2026-08-17T13:34:10.907748+00:00", "pr": 144, "pass": "144@2026-07-29T17-28-33.271744+00-00", "arm": "gemini", "skeptic_model": "gemini-2.5-flash", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 20, "refuted": 7, "uncertain": 0, "confirmed": 13, "unruled": 0, "recall": 0.6, "precision": 0.23076923076923078, "noise": 5, "killed_gt": []}
74
+ {"timestamp": "2026-08-17T13:34:12.013311+00:00", "pr": 144, "pass": "144@2026-07-29T17-28-33.271744+00-00", "arm": "openrouter", "skeptic_model": "nvidia/nemotron-3-super-120b-a12b:free", "finder_model": "mistral-medium-latest", "evidence": true, "findings": 20, "refuted": 0, "uncertain": 0, "confirmed": 0, "unruled": 20, "recall": 0.6, "precision": 0.15, "noise": 8, "killed_gt": []}
@@ -0,0 +1,140 @@
1
+ # Does checker output change the skeptic's verdicts? (#401)
2
+
3
+ #402 gave the skeptic the repository's `mypy --strict` and `ruff check` output. Whether
4
+ that changes anything was unmeasured, and `GUARDIAN_EVIDENCE=1` was switched on without a
5
+ number behind it. This is the number.
6
+
7
+ ## Design
8
+
9
+ One review, three arms, paired at the level of the individual finding.
10
+
11
+ | arm | what it is |
12
+ |---|---|
13
+ | **baseline** | the verdicts the recorded review actually produced, no evidence |
14
+ | **control** | the same 24 findings re-judged, still no evidence |
15
+ | **treatment** | the same 24 findings re-judged with evidence, collected at the reviewed commit |
16
+
17
+ The finder is never called. The subject is `guardian-finder-399`, the review that motivated
18
+ the RFC: 24 findings, of which the RFC classified exactly one as substantive.
19
+
20
+ **The control arm is not optional rigour.** `gemini.py` sends no temperature and
21
+ `guardian.yml` sets none, so the skeptic runs at the provider default: the recorded verdicts
22
+ are one draw, not a fixed point. Baseline against treatment therefore measures the effect
23
+ *plus* the resampling noise, and only a no-evidence replay separates them. This is the same
24
+ confound the replay arm removes at the finder, reappearing one level down.
25
+
26
+ Evidence is collected in a worktree at `05af753d` — the commit `refs/pull/399/head` pointed
27
+ at when the review ran. **Not** the artifact's `workflow_run.head_sha`: `guardian.yml` is
28
+ triggered by `issue_comment`, so that field is the tip of the trunk (`fd4e53a2`, a release
29
+ commit) and the reviewed files do not exist in it.
30
+
31
+ ## Results
32
+
33
+ Baseline: **19 confirmed / 5 refuted**.
34
+
35
+ | arm | conf→conf | conf→ref | conf→unc | ref→conf | ref→ref | moved | cites a checker |
36
+ |---|---:|---:|---:|---:|---:|---:|---:|
37
+ | control, draw 1 | 17 | 2 | 0 | 2 | 3 | 4 | 6/24 |
38
+ | control, draw 2 | 18 | 1 | 0 | 0 | 5 | 1 | 6/24 |
39
+ | treatment, draw 1 | 11 | 8 | 0 | 0 | 5 | 8 | 7/24 |
40
+ | treatment, draw 2 | 11 | 7 | 1 | 1 | 4 | 9 | 8/24 |
41
+
42
+ Draw 2 of each arm carries the per-finding rows (`pr-399-control-rows.jsonl`,
43
+ `pr-399-treatment-rows.jsonl`); the first draws predate that output and survive only as the
44
+ aggregates above.
45
+
46
+ ### The mechanism works exactly where it was aimed
47
+
48
+ Six findings claimed a mypy rule the repository does not have. **All six were refuted, and
49
+ all six cite the checker output.** The rationale on finding 0 is the RFC's hypothesis
50
+ verbatim:
51
+
52
+ > The project's mypy --strict checker, run as part of the review process, reports 'Success:
53
+ > no issues found', directly contradicting the claim that the use of `Any` is prohibited in
54
+ > strict mypy mode for this code.
55
+
56
+ That answers open question 1. The failure was **capability, not disposition**: shown the
57
+ output, the skeptic withdraws the claim; not shown it, it confirms.
58
+
59
+ ### The one true finding was withdrawn
60
+
61
+ Finding 4 — `git diff` can fail in a way other than the promised `MissingFixtureError`, the
62
+ finding that produced the actual fix in #399 — was refuted, **without citing any checker**:
63
+
64
+ > the code explicitly checks the validity of `base` and `head` SHAs using `git rev-parse`
65
+ > before the `git diff` call … thus the specific failure mode is already handled
66
+
67
+ which reproduces the half of the argument that `diff_for`'s own comment rejects: *"unlikely"
68
+ is not the same as "cannot"*.
69
+
70
+ | | baseline | treatment |
71
+ |---|---:|---:|
72
+ | false findings confirmed | 18 | 12 |
73
+ | true findings confirmed | 1 | **0** |
74
+
75
+ ### What the control arm bought, and how it reversed the first reading
76
+
77
+ The aggregate alone suggested the loss of finding 4 was noise: no checker was cited on it,
78
+ and control draw 1 produced two `confirmed → refuted` flips of its own. **The per-finding
79
+ rows say otherwise.** In the control draw that carries rows, finding 4 was *confirmed*, and
80
+ the rationale is correct:
81
+
82
+ > The `subprocess.run` call for `git diff` includes `check=True`, but the
83
+ > `CalledProcessError` it raises on command failure is not explicitly caught, leading to a
84
+ > different error type than `MissingFixtureError` …
85
+
86
+ That is the defect, stated accurately, by the same model that withdrew it once evidence was
87
+ in the prompt. The single control flip was finding 6, not finding 4.
88
+
89
+ So the loss is **on the evidence arm's side of the ledger**, and the earlier "not
90
+ attributable" reading — published in #406 and in the #401 comment before these rows existed —
91
+ was wrong. It rested on an aggregate, which is exactly the shape of number that cannot
92
+ answer *which*.
93
+
94
+ The two arms separate cleanly per finding:
95
+
96
+ | class | control | treatment |
97
+ |---|---|---|
98
+ | 6 false mypy claims | all confirmed | all refuted, all citing the checker |
99
+ | the 1 true finding | **confirmed, correctly reasoned** | **refuted**, citing no checker |
100
+
101
+ The mechanism on the false claims is visible in the control's own words: it confirmed
102
+ finding 0 on a conditional it could not check — *"**if** `mypy --strict` is configured to
103
+ disallow `Any` explicitly, it would be flagged"*. Evidence turns that hypothetical into a
104
+ reading, which is precisely the RFC's design intent.
105
+
106
+ Why the true finding falls is not explained by the same mechanism, because its refutation
107
+ cites nothing. The unattributed moves are 3 in treatment against 1 in control, which is
108
+ consistent with the evidence section shifting the skeptic toward refutation generally rather
109
+ than only where the output bears — but at these counts that is a hypothesis, not a result.
110
+
111
+ Two draws of the same arm differ in both arms (control 4 vs 1 flips, treatment 8 vs 9), so
112
+ single-draw asymmetries are not results.
113
+
114
+ ## What this does not establish
115
+
116
+ - **The recall denominator is one.** One review, one substantive finding. "Recall went to
117
+ zero" is literally true and statistically nearly weightless.
118
+ - **Attribution by rationale text is a weak proxy.** Citations barely moved between arms
119
+ (6/24 control vs 7–8/24 treatment) while verdicts moved a great deal — and the rows show
120
+ why: the control cites a checker on the *same six findings*, to confirm them.
121
+ - **Only one draw per arm has rows.** Whether finding 4 survives the control reliably or was
122
+ lucky in this draw is unmeasured; control draw 1 had two unidentified `confirmed → refuted`
123
+ flips.
124
+ - **Six of 24 control rationales cite mypy or ruff although no checker output was supplied**
125
+ (#407). Not merely fabricated: fabricated *in support of the wrong verdict*. The same six
126
+ findings carry a checker citation in both arms, confirmed in one and refuted in the other,
127
+ and only one of the two had a checker.
128
+
129
+ ## Reproducing
130
+
131
+ ```bash
132
+ scripts/guardian_replay_skeptic.py --recording pr-399-recording.json \
133
+ --control --out control-rows.jsonl
134
+ scripts/guardian_replay_skeptic.py --recording pr-399-recording.json \
135
+ --at 05af753d8895eab00609e7e58d89aa72ebd1777d --out treatment-rows.jsonl
136
+ ```
137
+
138
+ Requires `GUARDIAN_SKEPTIC=gemini`, `GUARDIAN_SKEPTIC_MODEL=gemini-2.5-flash` and the
139
+ matching key. 24 skeptic calls per arm, no finder calls. The recording is committed here
140
+ because the GitHub artifact it came from expires after seven days.
@@ -0,0 +1,24 @@
1
+ {"index": 0, "file": "scripts/recordings_from_corpus.py", "line": 38, "title": "Use of `Any` in type annotations violates strict mypy mode", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The use of `Any` does indeed bypass strict type checking in mypy, and while common for dynamic data structures (like those parsed from JSON/YAML), it generally indicates a potential for more precise typing or schema definition (e.g., Pydantic models). This is a plausible area for improvement, and if `mypy --strict` is configured to disallow `Any` explicitly, it would be flagged."}
2
+ {"index": 1, "file": "scripts/recordings_from_corpus.py", "line": 41, "title": "Unsafe YAML loading without `safe_load` or `Loader` specification", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The quoted code on line 100 (not 41 as stated) correctly uses `yaml.safe_load`. However, the `import yaml` statement does allow for `yaml.load` to be used elsewhere in the file, which is an unsafe practice without specifying a `Loader`. This is a plausible concern for future maintainability and security, as a developer might accidentally introduce an unsafe load later. The claim is plausible and cannot be disproven."}
3
+ {"index": 2, "file": "scripts/recordings_from_corpus.py", "line": 50, "title": "Function parameter uses `Any` in type annotation", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The quoted code accurately shows `Any` used in the type annotation, which strict mypy typically flags, aligning with the project's policy to score such issues low when covered by tooling."}
4
+ {"index": 3, "file": "scripts/recordings_from_corpus.py", "line": 56, "title": "Function parameter uses `Any` in type annotation", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The quoted code is present. While `mypy --strict` does not inherently disallow explicit `Any` without `disallow_any_explicit`, using `dict[str, Any]` weakens type safety for the `row` parameter, making it a legitimate type-hinting concern that is not 'already covered' by the standard `mypy --strict` checks."}
5
+ {"index": 4, "file": "scripts/recordings_from_corpus.py", "line": 62, "title": "Empty diff raises `MissingFixtureError` but may not be the only failure mode", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The `subprocess.run` call for `git diff` includes `check=True`, but the `CalledProcessError` it raises on command failure is not explicitly caught, leading to a different error type than `MissingFixtureError` which is used for other unresolvable diff scenarios."}
6
+ {"index": 5, "file": "scripts/recordings_from_corpus.py", "line": 80, "title": "Function parameter uses `Any` in type annotation", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The quoted code on line 80 uses `dict[str, Any]` for the `row` parameter, which is correctly identified as a violation by `mypy --disallow-any-type` (part of `--strict`)."}
7
+ {"index": 6, "file": "scripts/recordings_from_corpus.py", "line": 89, "title": "Potential type mismatch in `Finding.model_validate`", "was": "confirmed", "now": "refuted", "cites_a_checker": false, "rationale": "The `Finding.model_validate` method is precisely designed to enforce the schema and will raise a `ValidationError` for type mismatches or unexpected keys (if configured with `extra='forbid'`), or silently drop extra keys (if configured with `extra='ignore'`). The dictionary comprehension correctly strips known annotations before validation, so the code already handles the claimed problem appropriately through Pydantic's intended mechanisms. A `ValidationError` indicates a problem with the input data, not with the validation call itself. Using `model_construct` would bypass essential validation."}
8
+ {"index": 7, "file": "scripts/recordings_from_corpus.py", "line": 95, "title": "No validation that `results` file exists or is readable", "was": "refuted", "now": "refuted", "cites_a_checker": false, "rationale": "The `results.read_text()` call will raise a `FileNotFoundError` or other `IOError` if the file does not exist or is unreadable, preventing the function from silently proceeding without error in those specific cases."}
9
+ {"index": 8, "file": "scripts/recordings_from_corpus.py", "line": 100, "title": "No handling for case where no frozen passes are found", "was": "refuted", "now": "refuted", "cites_a_checker": false, "rationale": "The script correctly handles the scenario where no frozen passes are found by writing zero recordings. The `main` function explicitly reports \"0 recordings written\", which clearly communicates the outcome to the caller, making the behavior expected and not an error. A separate warning is not required for correctness or clarity."}
10
+ {"index": 9, "file": "scripts/recordings_from_corpus.py", "line": 102, "title": "Race condition in directory creation", "was": "refuted", "now": "refuted", "cites_a_checker": false, "rationale": "The `exist_ok=True` argument to `Path.mkdir()` explicitly handles the scenario where the directory already exists, preventing `FileExistsError` and making the operation safe for concurrent calls without a race condition."}
11
+ {"index": 10, "file": "scripts/recordings_from_corpus.py", "line": 110, "title": "No validation that `save_finder_recording` succeeds", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The `build` function does not handle potential failures of `save_finder_recording` (e.g., due to permission issues or disk full), which would either cause the script to crash, or, if `save_finder_recording` fails silently, lead to incorrectly reporting a recording as written when it was not."}
12
+ {"index": 11, "file": "scripts/recordings_from_corpus.py", "line": 117, "title": "No error handling for `build` failures", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The `main` function does not wrap the call to `build` in a try-except block, confirming that exceptions from `build` will propagate and exit the script with a traceback instead of a more user-friendly error message. This impacts script robustness for the end-user."}
13
+ {"index": 12, "file": "tests/unit/test_recordings_from_corpus.py", "line": 12, "title": "Modification of `sys.path` at runtime violates type safety", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The quoted code accurately reflects the diff. Modifying sys.path at runtime is a known pattern that can lead to less predictable import resolution and complicates static analysis tools like MyPy, which is plausibly what the reviewer meant by 'not type-safe.' It's not a critical bug but a maintainability concern."}
14
+ {"index": 13, "file": "tests/unit/test_recordings_from_corpus.py", "line": 15, "title": "Import from a script file may fail in some environments", "was": "refuted", "now": "refuted", "cites_a_checker": false, "rationale": "The claim that the import may fail due to the file not being in `sys.path` is refuted, as line 13 explicitly adds the containing directory to `sys.path`. The claim regarding environments not supporting direct `.py` imports is not generally applicable to functional Python environments. While importing from a script file via `sys.path` manipulation can be an architectural concern, the specific failure conditions stated in the claim are either handled or not plausible."}
15
+ {"index": 14, "file": "tests/unit/test_recordings_from_corpus.py", "line": 20, "title": "Hardcoded path traversal may break in some environments", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The code uses a chain of `.parent` calls to infer the repository root, which is indeed a hardcoded path traversal dependent on the file's exact location (`tests/unit/`), making the claim accurate and a minor robustness concern."}
16
+ {"index": 15, "file": "tests/unit/test_recordings_from_corpus.py", "line": 28, "title": "Function return type uses `Any` in type annotation", "was": "confirmed", "now": "confirmed", "cites_a_checker": true, "rationale": "The quoted code uses `Any` in the return type annotation as claimed. I cannot refute the assertion that this violates a strict mypy rule; if true, it would be caught by mandatory project tooling, leading to a low impact score."}
17
+ {"index": 16, "file": "tests/unit/test_recordings_from_corpus.py", "line": 30, "title": "No validation that `RESULTS` file exists or is readable", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The `_rows` function directly attempts to read `RESULTS.read_text()` without checking for the file's existence, which will indeed raise a `FileNotFoundError` if `results.jsonl` is absent, causing the tests to fail. The claim accurately describes this concrete failure path in the test utility."}
18
+ {"index": 17, "file": "tests/unit/test_recordings_from_corpus.py", "line": 35, "title": "Return type uses `Path` but may include non-Path values", "was": "refuted", "now": "refuted", "cites_a_checker": false, "rationale": "The original reviewer's analysis concludes, 'No action needed; the type is correct. This is a false positive.' This explicitly refutes the claim of a defect, as the type annotation `dict[str, Path]` accurately reflects the dictionary values being `Path` objects."}
19
+ {"index": 18, "file": "tests/unit/test_recordings_from_corpus.py", "line": 50, "title": "Test assumes existence of a judged row in the corpus", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The `next()` call without a default value will raise a `StopIteration` error if the `_rows()` generator yields no matching elements, making the test brittle to changes in the `results.jsonl` corpus data."}
20
+ {"index": 19, "file": "tests/unit/test_recordings_from_corpus.py", "line": 57, "title": "Test assumes existence of an unscored row in the corpus", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The use of `next()` without a default value or preceding check means the test will indeed raise `StopIteration` if the external corpus `results.jsonl` happens to lack a row matching the specified criteria, making the test brittle."}
21
+ {"index": 20, "file": "tests/unit/test_recordings_from_corpus.py", "line": 64, "title": "Test uses a hardcoded PR number (9999) that may not be meaningful", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The test correctly expects a MissingFixtureError for PR 9999, which relies on PR 9999 not having an associated ground-truth fixture. If PR 9999 were to be created and a fixture added in the future, the test would fail, making it fragile."}
22
+ {"index": 21, "file": "tests/unit/test_recordings_from_corpus.py", "line": 75, "title": "Test assumes at least 72 frozen passes exist in the corpus", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The assertion explicitly hardcodes a minimum of 72 frozen passes. If the corpus evolves to contain fewer than 72, the test will fail, regardless of whether the `build` function and related logic are actually correct for the current corpus size, making the test brittle."}
23
+ {"index": 22, "file": "tests/unit/test_recordings_from_corpus.py", "line": 100, "title": "Test assumes existence of `ambiguous_hits` in some rows", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The test explicitly asserts that the rows requiring the pre-#345 precision rule are exactly those carrying `ambiguous_hits`, as stated in the claim and the test's accompanying comments. This is an intentional check to ensure consistency between the corpus data and its documented scoring behavior, meaning a failure would correctly flag an issue with the benchmark data, not necessarily a defect in the test's logic. However, it indicates a tight coupling of the test to a specific data property, which implies a potential maintenance burden if this property of the corpus changes, even for legitimate reasons."}
24
+ {"index": 23, "file": "tests/unit/test_recordings_from_corpus.py", "line": 145, "title": "Floating-point comparison may be too strict for some use cases", "was": "confirmed", "now": "confirmed", "cites_a_checker": false, "rationale": "The claim is plausible because an absolute tolerance of 1e-9, while strict, can lead to false negatives in floating-point comparisons if calculations accumulate tiny errors or if the reference values themselves have slightly different precision than the re-calculated ones. Using math.isclose with both relative and absolute tolerances is generally a more robust approach in such test scenarios to avoid brittleness and potential flakiness."}