codegraph-brain 0.23.0__tar.gz → 0.23.1__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 (368) hide show
  1. codegraph_brain-0.23.1/.release-please-manifest.json +3 -0
  2. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/CHANGELOG.md +13 -0
  3. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/PKG-INFO +1 -1
  4. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/how-to/MCP_REFERENCE.md +56 -53
  5. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/pyproject.toml +1 -1
  6. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/server.json +2 -2
  7. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/api/mcp_server.py +6 -2
  8. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/cli.py +15 -9
  9. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/audit.py +86 -8
  10. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_audit.py +98 -2
  11. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_cli.py +13 -0
  12. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_mcp_server.py +9 -0
  13. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/uv.lock +1 -1
  14. codegraph_brain-0.23.0/.release-please-manifest.json +0 -3
  15. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.claude-plugin/marketplace.json +0 -0
  16. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.gitattributes +0 -0
  17. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/test-count-baseline +0 -0
  18. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/workflows/autodoc.yml +0 -0
  19. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/workflows/ci.yml +0 -0
  20. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/workflows/guardian.yml +0 -0
  21. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/workflows/pr-title.yml +0 -0
  22. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.github/workflows/release-please.yml +0 -0
  23. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.gitignore +0 -0
  24. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.pre-commit-config.yaml +0 -0
  25. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/.python-version +0 -0
  26. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/CLAUDE.md +0 -0
  27. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/CONTRIBUTING.md +0 -0
  28. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/LICENSE +0 -0
  29. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/Makefile +0 -0
  30. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/PRIVACY.md +0 -0
  31. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/README.md +0 -0
  32. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/CURATION.md +0 -0
  33. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/calibration.jsonl +0 -0
  34. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/246-cross-vendor/README.md +0 -0
  35. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/246-cross-vendor/free-nemotron-quota-cutoff.jsonl +0 -0
  36. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/401-evidence/README.md +0 -0
  37. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/401-evidence/pr-399-control-rows.jsonl +0 -0
  38. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/401-evidence/pr-399-recording.json +0 -0
  39. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/401-evidence/pr-399-treatment-rows.jsonl +0 -0
  40. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/407-no-checker-appeal/README.md +0 -0
  41. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-directive-rows.jsonl +0 -0
  42. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-prohibition-rows.jsonl +0 -0
  43. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-122.yaml +0 -0
  44. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-140.yaml +0 -0
  45. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-141.yaml +0 -0
  46. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-142.yaml +0 -0
  47. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-143.yaml +0 -0
  48. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-144.yaml +0 -0
  49. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-278.yaml +0 -0
  50. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/pr-313.yaml +0 -0
  51. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/guardian/results.jsonl +0 -0
  52. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/README.md +0 -0
  53. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/cal_dot_com.json +0 -0
  54. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/discourse.json +0 -0
  55. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/grafana.json +0 -0
  56. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/keycloak.json +0 -0
  57. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian/sentry.json +0 -0
  58. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-judged.jsonl +0 -0
  59. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-p3-judged-run1.jsonl +0 -0
  60. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-p3-judged-run1.jsonl.corrupted-backup +0 -0
  61. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-p3-run1.jsonl +0 -0
  62. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-p3-run2.jsonl +0 -0
  63. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-p3-run3.jsonl +0 -0
  64. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-plan.json +0 -0
  65. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-repeat-judged.jsonl +0 -0
  66. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-repeat-reviews.jsonl +0 -0
  67. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/benchmarks/martian-reviews.jsonl +0 -0
  68. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/data/.gitkeep +0 -0
  69. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/AUDIT.md +0 -0
  70. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/CASE_STUDY.md +0 -0
  71. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/GUARDIAN_LOCAL_BENCH.md +0 -0
  72. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/GUARDIAN_REMOTE_OLLAMA.md +0 -0
  73. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/HOW_IT_WORKS.md +0 -0
  74. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/ONTOLOGY.md +0 -0
  75. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/PATTERNS_AND_TRIADS.md +0 -0
  76. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/SELF_PORTRAIT.md +0 -0
  77. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/diagrams/pipeline_flow.mermaid +0 -0
  78. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/architecture/health_badge.json +0 -0
  79. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/assets/.gitignore +0 -0
  80. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/assets/cgis-app-avatar.png +0 -0
  81. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/assets/cgis-app-avatar.svg +0 -0
  82. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/assets/generate_avatar.py +0 -0
  83. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/examples/.gitkeep +0 -0
  84. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/how-to/AGENT_ONBOARDING.md +0 -0
  85. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/how-to/CLI_USAGE.md +0 -0
  86. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/lab-notes/2026-06-11-chunked-review-negative-result.md +0 -0
  87. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/ontology/.gitkeep +0 -0
  88. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/ontology/core.yaml +0 -0
  89. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/ontology/domains.yaml +0 -0
  90. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/ontology/patterns.yaml +0 -0
  91. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/ontology/tolerances.lock +0 -0
  92. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/plans/2026-09-09-graph-freshness.md +0 -0
  93. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-09-domain-pattern-fingerprint-design.md +0 -0
  94. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-09-pattern-alphabet-motif-basis-design.md +0 -0
  95. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-10-guardian-sprint-design.md +0 -0
  96. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-fastapi-di-edges-design.md +0 -0
  97. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-guardian-chunked-review-design.md +0 -0
  98. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-guardian-chunker-design.md +0 -0
  99. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-mcp-drift-validate-fqn-design.md +0 -0
  100. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-resolver-split-design.md +0 -0
  101. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-11-symbol-import-edges-design.md +0 -0
  102. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-12-drift-empty-domains-design.md +0 -0
  103. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-12-gate-semantics-design.md +0 -0
  104. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-12-init-ontology-design.md +0 -0
  105. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-12-release-please-ci-design.md +0 -0
  106. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-13-suggest-packages-design.md +0 -0
  107. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-06-13-tangle-anti-pattern-design.md +0 -0
  108. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-29-guardian-skeptic-scoring-design.md +0 -0
  109. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-cgis-fractal-design.md +0 -0
  110. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-cgis-fractal-plan.md +0 -0
  111. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-chunk-source-filter-design.md +0 -0
  112. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-chunk-source-filter-plan.md +0 -0
  113. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-genai-client-close-design.md +0 -0
  114. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-genai-client-close-plan.md +0 -0
  115. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-guardian-precision-bench-design.md +0 -0
  116. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-guardian-precision-bench-plan.md +0 -0
  117. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-guardian-timeout-retry-design.md +0 -0
  118. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-30-guardian-timeout-retry-plan.md +0 -0
  119. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-07-31-finder-bug-class-taxonomy.md +0 -0
  120. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-08-01-aura-autoevolution-poc.md +0 -0
  121. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-08-11-guardian-code-review-bench.md +0 -0
  122. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-08-14-review-fingerprint-design.md +0 -0
  123. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-09-05-annotation-graph-design.md +0 -0
  124. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/2026-09-09-graph-freshness-design.md +0 -0
  125. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/BLUEPRINT.md +0 -0
  126. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/PRD.md +0 -0
  127. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/TDD.md +0 -0
  128. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-09-fingerprint-drift.md +0 -0
  129. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md +0 -0
  130. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-10-guardian-structured-findings-bench.md +0 -0
  131. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-10-motif-basis-part-b.md +0 -0
  132. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-10-unified-pattern-alphabet.md +0 -0
  133. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-11-fastapi-di-edges.md +0 -0
  134. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-11-guardian-chunked-review.md +0 -0
  135. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-11-guardian-chunker.md +0 -0
  136. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-11-mcp-drift-validate-fqn.md +0 -0
  137. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-11-resolver-split.md +0 -0
  138. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-12-drift-empty-domains.md +0 -0
  139. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-12-gate-semantics.md +0 -0
  140. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-12-init-ontology.md +0 -0
  141. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-12-release-please-ci.md +0 -0
  142. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-12-symbol-import-edges.md +0 -0
  143. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-06-13-suggest-packages.md +0 -0
  144. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-07-29-guardian-skeptic-scoring.md +0 -0
  145. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-08-14-review-fingerprint.md +0 -0
  146. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-09-05-annotation-graph-pr1.md +0 -0
  147. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/docs/specs/plans/2026-09-05-annotation-graph-pr2.md +0 -0
  148. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/glama.json +0 -0
  149. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/main.py +0 -0
  150. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/plugin/.claude-plugin/plugin.json +0 -0
  151. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/plugin/.mcp.json +0 -0
  152. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/plugin/README.md +0 -0
  153. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/plugin/skills/cgis/SKILL.md +0 -0
  154. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/plugin/skills/ingest/SKILL.md +0 -0
  155. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/release-please-config.json +0 -0
  156. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/backfill_calibration_fingerprint.py +0 -0
  157. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/backfill_review_fingerprint.py +0 -0
  158. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/check_pytest_raises.py +0 -0
  159. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/check_test_count.py +0 -0
  160. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/colab_bench.sh +0 -0
  161. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/gen_ideal_graph.py +0 -0
  162. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/generate_health.py +0 -0
  163. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/generate_mcp_ref.py +0 -0
  164. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/generate_schema_docs.py +0 -0
  165. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/guardian_bench.py +0 -0
  166. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/guardian_calibrate.py +0 -0
  167. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/guardian_martian.py +0 -0
  168. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/guardian_replay_skeptic.py +0 -0
  169. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/guardian_review.py +0 -0
  170. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/inject_architecture_graph.py +0 -0
  171. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/ollama_visitor.sh +0 -0
  172. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/probe_closure_gap.py +0 -0
  173. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/probe_tier_ladder.py +0 -0
  174. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/recordings_from_corpus.py +0 -0
  175. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/scripts/skeptic_arms.py +0 -0
  176. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/__init__.py +0 -0
  177. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/__main__.py +0 -0
  178. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/api/.gitkeep +0 -0
  179. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/api/__init__.py +0 -0
  180. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/.gitkeep +0 -0
  181. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/coverage.py +0 -0
  182. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/freshness.py +0 -0
  183. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/generated.py +0 -0
  184. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/js_globals.py +0 -0
  185. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/models.py +0 -0
  186. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/core/paths.py +0 -0
  187. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/.gitkeep +0 -0
  188. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_annotations.py +0 -0
  189. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_ast.py +0 -0
  190. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_classes.py +0 -0
  191. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_functions.py +0 -0
  192. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_imports.py +0 -0
  193. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_python_types.py +0 -0
  194. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/_typescript_bindings.py +0 -0
  195. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/base.py +0 -0
  196. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/python_extractor.py +0 -0
  197. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/registry.py +0 -0
  198. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/extractors/typescript_extractor.py +0 -0
  199. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/__init__.py +0 -0
  200. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/axes.py +0 -0
  201. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/bench.py +0 -0
  202. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/calibrate.py +0 -0
  203. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/chunked.py +0 -0
  204. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/chunker.py +0 -0
  205. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/collector.py +0 -0
  206. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/core.py +0 -0
  207. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/diff_index.py +0 -0
  208. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/evidence.py +0 -0
  209. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/findings.py +0 -0
  210. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/github_poster.py +0 -0
  211. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/martian.py +0 -0
  212. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/metrics.py +0 -0
  213. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/prompts.py +0 -0
  214. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/__init__.py +0 -0
  215. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/base.py +0 -0
  216. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/gemini.py +0 -0
  217. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/mistral.py +0 -0
  218. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/ollama.py +0 -0
  219. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/providers/openrouter.py +0 -0
  220. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/recording.py +0 -0
  221. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/render.py +0 -0
  222. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/review_fingerprint.py +0 -0
  223. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/runner.py +0 -0
  224. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/guardian/skeptic.py +0 -0
  225. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/pipeline.py +0 -0
  226. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/py.typed +0 -0
  227. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/__init__.py +0 -0
  228. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/analyzer.py +0 -0
  229. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/anomaly.py +0 -0
  230. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/cohesion.py +0 -0
  231. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/health.py +0 -0
  232. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/analysis/suggest_service.py +0 -0
  233. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/__init__.py +0 -0
  234. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/context_service.py +0 -0
  235. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/orphans.py +0 -0
  236. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/prompt.py +0 -0
  237. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/context/snippet.py +0 -0
  238. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/__init__.py +0 -0
  239. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/_scc.py +0 -0
  240. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/drift.py +0 -0
  241. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/drift_service.py +0 -0
  242. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/fingerprint.py +0 -0
  243. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/fractal.py +0 -0
  244. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/ontology_init.py +0 -0
  245. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/quotient.py +0 -0
  246. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/drift/triads.py +0 -0
  247. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/engine.py +0 -0
  248. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/fqn.py +0 -0
  249. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/render/__init__.py +0 -0
  250. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/render/graph_json.py +0 -0
  251. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/render/mermaid.py +0 -0
  252. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/query/render/metrics.py +0 -0
  253. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/.gitkeep +0 -0
  254. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/__init__.py +0 -0
  255. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/engine.py +0 -0
  256. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/indices.py +0 -0
  257. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/js_builtins.py +0 -0
  258. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/symbols.py +0 -0
  259. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/resolver/uplift.py +0 -0
  260. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/storage/.gitkeep +0 -0
  261. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/src/cgis/storage/sqlite_store.py +0 -0
  262. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/integration/.gitkeep +0 -0
  263. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/.gitkeep +0 -0
  264. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/__init__.py +0 -0
  265. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/conftest.py +0 -0
  266. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_annotation_calibration.py +0 -0
  267. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_architecture.py +0 -0
  268. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_drift.py +0 -0
  269. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_fractal.py +0 -0
  270. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_init_ontology_roundtrip.py +0 -0
  271. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_receiver_resolution.py +0 -0
  272. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_self_parse.py +0 -0
  273. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_self_parse_ts.py +0 -0
  274. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/self_parsing/test_suggest.py +0 -0
  275. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/.gitkeep +0 -0
  276. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/conftest.py +0 -0
  277. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/guardian_stubs.py +0 -0
  278. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/review_path_inventory.txt +0 -0
  279. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test___main__.py +0 -0
  280. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_analyzer.py +0 -0
  281. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_annotation_edges.py +0 -0
  282. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_backfill_calibration_fingerprint.py +0 -0
  283. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_backfill_review_fingerprint.py +0 -0
  284. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_check_pytest_raises.py +0 -0
  285. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_check_test_count.py +0 -0
  286. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_cohesion.py +0 -0
  287. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_context_service.py +0 -0
  288. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_di_acceptance.py +0 -0
  289. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_drift.py +0 -0
  290. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_drift_service.py +0 -0
  291. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_extractor_registry.py +0 -0
  292. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_fingerprint.py +0 -0
  293. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_fqn.py +0 -0
  294. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_fractal.py +0 -0
  295. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_freshness.py +0 -0
  296. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_gen_ideal_graph.py +0 -0
  297. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_generate_mcp_ref.py +0 -0
  298. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_generated.py +0 -0
  299. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_graph_json.py +0 -0
  300. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_axes.py +0 -0
  301. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_bench.py +0 -0
  302. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_bench_script.py +0 -0
  303. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_calibrate.py +0 -0
  304. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_calibrate_script.py +0 -0
  305. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_chunked.py +0 -0
  306. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_chunker.py +0 -0
  307. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_collector.py +0 -0
  308. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_core.py +0 -0
  309. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_diff_index.py +0 -0
  310. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_evidence.py +0 -0
  311. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_findings.py +0 -0
  312. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_martian.py +0 -0
  313. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_martian_script.py +0 -0
  314. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_martian_union.py +0 -0
  315. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_metrics.py +0 -0
  316. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_mistral_sampling.py +0 -0
  317. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_ollama_sampling.py +0 -0
  318. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_ollama_truncation.py +0 -0
  319. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_openrouter.py +0 -0
  320. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_poster.py +0 -0
  321. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_providers.py +0 -0
  322. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_providers_name.py +0 -0
  323. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_recording.py +0 -0
  324. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_render.py +0 -0
  325. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_replay_skeptic.py +0 -0
  326. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_review_script.py +0 -0
  327. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_runner.py +0 -0
  328. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_salvage.py +0 -0
  329. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_guardian_skeptic.py +0 -0
  330. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_health_scorer.py +0 -0
  331. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_import_acceptance.py +0 -0
  332. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_inject_architecture_graph.py +0 -0
  333. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_mcp_tool_schemas.py +0 -0
  334. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_mermaid.py +0 -0
  335. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_metrics.py +0 -0
  336. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_models.py +0 -0
  337. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_name_load_positions.py +0 -0
  338. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_ontology_compliance.py +0 -0
  339. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_ontology_init.py +0 -0
  340. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_orphans.py +0 -0
  341. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_paths.py +0 -0
  342. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_patterns_yaml.py +0 -0
  343. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_pipeline.py +0 -0
  344. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_pipeline_incremental_symbols.py +0 -0
  345. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_prompt.py +0 -0
  346. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_python_annotations.py +0 -0
  347. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_python_extractor.py +0 -0
  348. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_query_coverage.py +0 -0
  349. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_quotient.py +0 -0
  350. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_recordings_from_corpus.py +0 -0
  351. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_resolver.py +0 -0
  352. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_resolver_indices.py +0 -0
  353. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_resolver_js_builtins.py +0 -0
  354. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_resolver_language_scope.py +0 -0
  355. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_resolver_symbols.py +0 -0
  356. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_review_fingerprint_closure.py +0 -0
  357. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_review_fingerprint_contract.py +0 -0
  358. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_review_fingerprint_digest.py +0 -0
  359. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_review_fingerprint_record.py +0 -0
  360. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_self_types.py +0 -0
  361. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_skeptic_arms.py +0 -0
  362. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_snippet.py +0 -0
  363. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_sqlite_store.py +0 -0
  364. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_suggest_service.py +0 -0
  365. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_temperature_source.py +0 -0
  366. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_triads.py +0 -0
  367. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_typescript_extractor.py +0 -0
  368. {codegraph_brain-0.23.0 → codegraph_brain-0.23.1}/tests/unit/test_uplift.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.23.1"
3
+ }
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.23.1](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.23.0...codegraph-brain-v0.23.1) (2026-09-17)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **audit:** an audit that selects no sources is an error, not an empty pass ([#472](https://github.com/zaebee/codegraph-brain/issues/472)) ([9f93010](https://github.com/zaebee/codegraph-brain/commit/9f93010c286d0b189f3c3350833a5cf557316d8f))
9
+
10
+
11
+ ### Documentation
12
+
13
+ * auto-sync architecture graph and MCP reference ([#468](https://github.com/zaebee/codegraph-brain/issues/468)) ([4c02171](https://github.com/zaebee/codegraph-brain/commit/4c021719776d00ae2f3539409ba847995f79c48e))
14
+ * auto-sync architecture graph and MCP reference ([#473](https://github.com/zaebee/codegraph-brain/issues/473)) ([567b091](https://github.com/zaebee/codegraph-brain/commit/567b09190c61ab5fc2b5b26c0b445bff2cbe5a12))
15
+
3
16
  ## [0.23.0](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.22.0...codegraph-brain-v0.23.0) (2026-09-17)
4
17
 
5
18
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codegraph-brain
3
- Version: 0.23.0
3
+ Version: 0.23.1
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
@@ -20,10 +20,10 @@ Analyse transitive upstream callers of a specific FQN.
20
20
 
21
21
  | Argument | Type | Required | Description |
22
22
  | :--- | :--- | :---: | :--- |
23
- | `fqn` | `string` | ✓ | |
24
- | `db_path` | `string` | | |
25
- | `depth` | `integer` | | |
26
- | `output_format` | `string` | | |
23
+ | `fqn` | `string` | ✓ | Fully qualified name, e.g. pkg.module.Class.method. A unique dot-boundary suffix also resolves; an ambiguous one returns candidates. Use cgis_find_symbol to look a name up. |
24
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
25
+ | `depth` | `integer` | | Maximum edge hops upstream. Every edge type counts as a hop — CALLS, but also IMPORTS, CONTAINS and REFERENCES — so modules importing the target and the file containing it appear alongside its callers. |
26
+ | `output_format` | `string` | | "mermaid" for a diagram, or "json" for a payload with real FQNs (case-insensitive). Any other value returns an error. |
27
27
 
28
28
  ---
29
29
 
@@ -41,13 +41,16 @@ Reachability/authorization audit — which sources never reach a checkpoint (#17
41
41
  ``fqn``/``file``/``line``. Generalizes to validators, event tracking, or
42
42
  service-layer-boundary rules by pointing ``target`` at the required node.
43
43
 
44
+ A selection that matches no source returns a ❌ message, not an empty
45
+ ``{covered: [], gaps: []}`` that would read as a passing audit (#467).
46
+
44
47
  | Argument | Type | Required | Description |
45
48
  | :--- | :--- | :---: | :--- |
46
- | `target` | `string` | ✓ | |
47
- | `db_path` | `string` | | |
48
- | `from_type` | `any` | | |
49
- | `from_prefix` | `any` | | |
50
- | `depth` | `integer` | | |
49
+ | `target` | `string` | ✓ | FQN of the checkpoint every source must reach, e.g. an ownership check. A unique dot-boundary suffix also resolves. |
50
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
51
+ | `from_type` | `any` | | NodeType of the sources to audit, e.g. ROUTE_HANDLER, API_ENDPOINT or FUNCTION (any case). Give this, from_prefix, or both. |
52
+ | `from_prefix` | `any` | | Only audit sources at or under this FQN prefix, matched on whole dot-segments. A selection matching no source is an error naming the whole-segment prefixes it may have meant. Combined with from_type when both are given. |
53
+ | `depth` | `integer` | | Maximum reachability depth; a longer path is reported as a gap. |
51
54
 
52
55
  ---
53
56
 
@@ -70,10 +73,10 @@ Compile an agent-facing GraphRAG context package for a focal FQN (#19).
70
73
 
71
74
  | Argument | Type | Required | Description |
72
75
  | :--- | :--- | :---: | :--- |
73
- | `fqn` | `string` | ✓ | |
74
- | `db_path` | `string` | | |
75
- | `depth` | `integer` | | |
76
- | `source_root` | `string` | | |
76
+ | `fqn` | `string` | ✓ | Fully qualified name, e.g. pkg.module.Class.method. A unique dot-boundary suffix also resolves; an ambiguous one returns candidates. Use cgis_find_symbol to look a name up. |
77
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
78
+ | `depth` | `integer` | | Call hops around the focal node; 1 means direct callers and callees. |
79
+ | `source_root` | `string` | | Directory the graph's stored file paths are relative to — normally the project_path given to cgis_ingest; prefer an absolute path. Empty means the server's working directory, so source shows as unavailable when the server runs elsewhere. |
77
80
 
78
81
  ---
79
82
 
@@ -102,11 +105,11 @@ Report per-domain architectural drift against declared ideal patterns.
102
105
 
103
106
  | Argument | Type | Required | Description |
104
107
  | :--- | :--- | :---: | :--- |
105
- | `db_path` | `string` | | |
106
- | `patterns_path` | `string` | | |
107
- | `max_drift` | `number` | | |
108
- | `profile` | `any` | | |
109
- | `max_residual` | `number` | | |
108
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
109
+ | `patterns_path` | `string` | | patterns.yaml (.yaml or .yml) declaring each domain's expected pattern and tolerance, relative to the server's working directory. cgis_init_ontology proposes one. |
110
+ | `max_drift` | `number` | | Drift tolerance for domains that declare no drift_tolerance of their own. |
111
+ | `profile` | `any` | | Score only domains with this profile, plus profile-less ones — e.g. one language when patterns.yaml mixes several. |
112
+ | `max_residual` | `number` | | Distance to the nearest template beyond which a domain's fit band is "none" (no template fits). |
110
113
 
111
114
  ---
112
115
 
@@ -150,10 +153,10 @@ Classes nothing in production builds, extends or names — dead-code candidates
150
153
 
151
154
  | Argument | Type | Required | Description |
152
155
  | :--- | :--- | :---: | :--- |
153
- | `db_path` | `string` | | |
154
- | `prefix` | `any` | | |
155
- | `include_tests` | `boolean` | | |
156
- | `include_generated` | `boolean` | | |
156
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
157
+ | `prefix` | `any` | | Only consider classes under this FQN prefix, cut on a dot boundary. |
158
+ | `include_tests` | `boolean` | | Count test code as a user, so the report means "unreachable from anywhere". |
159
+ | `include_generated` | `boolean` | | Include machine-generated classes, which are hidden by default. |
157
160
 
158
161
  ---
159
162
 
@@ -170,11 +173,11 @@ Resolve a partial symbol name to candidate FQNs (substring match, ranked).
170
173
 
171
174
  | Argument | Type | Required | Description |
172
175
  | :--- | :--- | :---: | :--- |
173
- | `query` | `string` | ✓ | |
174
- | `db_path` | `string` | | |
175
- | `kind` | `any` | | |
176
- | `fqn_prefix` | `any` | | |
177
- | `limit` | `integer` | | |
176
+ | `query` | `string` | ✓ | Leaf symbol name to search for, without dots (e.g. get_flow_result) — not an FQN. Case-insensitive substring match, ranked exact > prefix > substring. |
177
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
178
+ | `kind` | `any` | | Only return this node type, e.g. FUNCTION, METHOD or CLASS (any case). An unknown type matches nothing rather than raising an error. |
179
+ | `fqn_prefix` | `any` | | Only return symbols at or under this FQN prefix, matched on whole dot-segments: app.svc does not match app.svc_alt, and a partial segment matches nothing. |
180
+ | `limit` | `integer` | | Maximum number of candidates to return. |
178
181
 
179
182
  ---
180
183
 
@@ -200,7 +203,7 @@ Report the motif census across the repository's structural tiers.
200
203
 
201
204
  | Argument | Type | Required | Description |
202
205
  | :--- | :--- | :---: | :--- |
203
- | `db_path` | `string` | | |
206
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
204
207
 
205
208
  ---
206
209
 
@@ -215,10 +218,10 @@ Show the structural layout (CONTAINS/DECLARES) of a module or class.
215
218
 
216
219
  | Argument | Type | Required | Description |
217
220
  | :--- | :--- | :---: | :--- |
218
- | `fqn` | `string` | ✓ | |
219
- | `db_path` | `string` | | |
220
- | `depth` | `integer` | | |
221
- | `output_format` | `string` | | |
221
+ | `fqn` | `string` | ✓ | Fully qualified name, e.g. pkg.module.Class.method. A unique dot-boundary suffix also resolves; an ambiguous one returns candidates. Use cgis_find_symbol to look a name up. |
222
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
223
+ | `depth` | `integer` | | Maximum containment levels to descend (module → class → method). |
224
+ | `output_format` | `string` | | "mermaid" for a diagram, or "json" for a payload with real FQNs (case-insensitive). Any other value returns an error. |
222
225
 
223
226
  ---
224
227
 
@@ -245,9 +248,9 @@ Scan a local directory, extract all symbols, resolve links, and build the graph
245
248
 
246
249
  | Argument | Type | Required | Description |
247
250
  | :--- | :--- | :---: | :--- |
248
- | `project_path` | `string` | ✓ | |
249
- | `db_path` | `string` | | |
250
- | `full_rebuild` | `boolean` | | |
251
+ | `project_path` | `string` | ✓ | Root directory of the project to scan. A relative path resolves against the MCP server's working directory. |
252
+ | `db_path` | `string` | | Where to write the graph: must end in .db, .sqlite or .sqlite3, in a directory that already exists, and must not be an existing non-SQLite file. A relative path resolves against the server's working directory. |
253
+ | `full_rebuild` | `boolean` | | Re-scan every file from scratch instead of the incremental default. |
251
254
 
252
255
  ---
253
256
 
@@ -263,10 +266,10 @@ Propose a starter patterns.yaml from the measured graph (read-only).
263
266
 
264
267
  | Argument | Type | Required | Description |
265
268
  | :--- | :--- | :---: | :--- |
266
- | `db_path` | `string` | | |
267
- | `margin` | `number` | | |
268
- | `min_nodes` | `integer` | | |
269
- | `depth` | `any` | | |
269
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
270
+ | `margin` | `number` | | Headroom added to each measured score to form the proposed tolerance. |
271
+ | `min_nodes` | `integer` | | Domains with fewer nodes stay hygiene-only instead of getting a label. |
272
+ | `depth` | `any` | | Fixed FQN segment depth for domain discovery (positive); omit to pick it automatically. |
270
273
 
271
274
  ---
272
275
 
@@ -297,10 +300,10 @@ Whole-graph architectural metrics — coupling bottlenecks + God classes (#16).
297
300
 
298
301
  | Argument | Type | Required | Description |
299
302
  | :--- | :--- | :---: | :--- |
300
- | `db_path` | `string` | | |
301
- | `limit` | `integer` | | |
302
- | `exclude` | `any` | | |
303
- | `scope` | `any` | | |
303
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
304
+ | `limit` | `integer` | | Top-N rows returned per section. |
305
+ | `exclude` | `any` | | Drop nodes whose FQN contains any of these dot-segments, e.g. ["tests"]; they are removed from PageRank propagation too. |
306
+ | `scope` | `any` | | Keep only nodes under any of these dot-prefixes, e.g. ["domains.billing"]; rank still propagates over the whole graph. |
304
307
 
305
308
  ---
306
309
 
@@ -319,10 +322,10 @@ Suggest sub-package boundaries for a package from its dependency communities.
319
322
 
320
323
  | Argument | Type | Required | Description |
321
324
  | :--- | :--- | :---: | :--- |
322
- | `db_path` | `string` | | |
323
- | `prefix` | `any` | | |
324
- | `with_calls` | `boolean` | | |
325
- | `min_q` | `number` | | |
325
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
326
+ | `prefix` | `any` | | FQN prefix of the package to analyse, e.g. cgis.query, matched on whole dot-segments. Needed in practice: without it the verdict is no_signal. |
327
+ | `with_calls` | `boolean` | | Use the combined import + call graph instead of imports only. |
328
+ | `min_q` | `number` | | Modularity threshold: at or above it, a package whose layout disagrees with its communities is flagged split (or consolidate, if over-split). |
326
329
 
327
330
  ---
328
331
 
@@ -341,10 +344,10 @@ Trace the execution call-graph starting from a specific FQN downwards.
341
344
 
342
345
  | Argument | Type | Required | Description |
343
346
  | :--- | :--- | :---: | :--- |
344
- | `fqn` | `string` | ✓ | |
345
- | `db_path` | `string` | | |
346
- | `depth` | `integer` | | |
347
- | `output_format` | `string` | | |
347
+ | `fqn` | `string` | ✓ | Fully qualified name, e.g. pkg.module.Class.method. A unique dot-boundary suffix also resolves; an ambiguous one returns candidates. Use cgis_find_symbol to look a name up. |
348
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
349
+ | `depth` | `integer` | | Maximum edge hops downstream. Every edge type counts as a hop — CALLS, but also IMPORTS, CONTAINS and REFERENCES — so from a module the first hops are mostly imports and structure. |
350
+ | `output_format` | `string` | | "mermaid" for a diagram, or "json" for a payload with real FQNs (case-insensitive). Any other value returns an error. |
348
351
 
349
352
  ---
350
353
 
@@ -357,7 +360,7 @@ Report graph integrity as JSON: edge resolution stats + health verdict.
357
360
 
358
361
  | Argument | Type | Required | Description |
359
362
  | :--- | :--- | :---: | :--- |
360
- | `db_path` | `string` | | |
361
- | `threshold` | `number` | | |
363
+ | `db_path` | `string` | | SQLite graph built by cgis_ingest. A relative path resolves against the MCP server's working directory, not the agent's — prefer an absolute path. |
364
+ | `threshold` | `number` | | Highest unresolved-edge ratio (0-1) still reported as healthy. |
362
365
 
363
366
  ---
@@ -7,7 +7,7 @@ packages = ["src/cgis"]
7
7
 
8
8
  [project]
9
9
  name = "codegraph-brain"
10
- version = "0.23.0"
10
+ version = "0.23.1"
11
11
  description = "Semantic code graph for AI agents — deterministic FQN resolution, impact analysis and architectural drift gates, exposed over MCP."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.12"
@@ -8,13 +8,13 @@
8
8
  "source": "github",
9
9
  "id": "1260843154"
10
10
  },
11
- "version": "0.23.0",
11
+ "version": "0.23.1",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "registryBaseUrl": "https://pypi.org",
16
16
  "identifier": "codegraph-brain",
17
- "version": "0.23.0",
17
+ "version": "0.23.1",
18
18
  "runtimeHint": "uvx",
19
19
  "transport": {
20
20
  "type": "stdio"
@@ -966,8 +966,9 @@ def cgis_audit_reachability(
966
966
  str | None,
967
967
  Field(
968
968
  description="Only audit sources at or under this FQN prefix, matched on whole "
969
- "dot-segments — a partial segment selects nothing and returns an empty audit, "
970
- "not a clean one. Combined with from_type when both are given."
969
+ "dot-segments. A selection matching no source is an error naming the "
970
+ "whole-segment prefixes it may have meant. Combined with from_type when both "
971
+ "are given."
971
972
  ),
972
973
  ] = None,
973
974
  depth: Annotated[
@@ -986,6 +987,9 @@ def cgis_audit_reachability(
986
987
  one is required. Returns JSON ``{target, covered, gaps}`` where each gap carries
987
988
  ``fqn``/``file``/``line``. Generalizes to validators, event tracking, or
988
989
  service-layer-boundary rules by pointing ``target`` at the required node.
990
+
991
+ A selection that matches no source returns a ❌ message, not an empty
992
+ ``{covered: [], gaps: []}`` that would read as a passing audit (#467).
989
993
  """
990
994
  if blank := _blank_fqn_error(target):
991
995
  return blank
@@ -42,7 +42,7 @@ from cgis.query.analysis.analyzer import AnalyzerEngine
42
42
  from cgis.query.analysis.anomaly import AnomalyType, ArchitecturalAnomaly
43
43
  from cgis.query.analysis.health import HealthScorer
44
44
  from cgis.query.analysis.suggest_service import SuggestReport, report_to_dict, suggest_packages
45
- from cgis.query.context.audit import ReachabilityAudit, audit_reachability
45
+ from cgis.query.context.audit import NoAuditSourcesError, ReachabilityAudit, audit_reachability
46
46
  from cgis.query.context.context_service import build_context
47
47
  from cgis.query.context.orphans import OrphanReport, find_orphan_classes
48
48
  from cgis.query.drift.drift import DriftReport, FitQuality
@@ -1445,7 +1445,7 @@ def audit(
1445
1445
  help="Only audit nodes of this type (e.g. ROUTE_HANDLER, API_ENDPOINT).",
1446
1446
  ),
1447
1447
  from_prefix: str | None = typer.Option(
1448
- None, "--from-prefix", help="Only audit nodes whose FQN starts with this prefix."
1448
+ None, "--from-prefix", help="Only audit nodes under this FQN prefix (whole dot-segments)."
1449
1449
  ),
1450
1450
  db: str = typer.Option(_DEFAULT_DB, "--db", "-d", help=_DEFAULT_DB_HELP),
1451
1451
  depth: int = typer.Option(
@@ -1487,13 +1487,19 @@ def audit(
1487
1487
 
1488
1488
  with SQLiteStore(db) as store:
1489
1489
  resolved = _resolve_checkpoint(store, target)
1490
- result = audit_reachability(
1491
- store,
1492
- target_fqn=resolved,
1493
- from_type=from_type,
1494
- from_prefix=from_prefix,
1495
- max_depth=depth,
1496
- )
1490
+ try:
1491
+ result = audit_reachability(
1492
+ store,
1493
+ target_fqn=resolved,
1494
+ from_type=from_type,
1495
+ from_prefix=from_prefix,
1496
+ max_depth=depth,
1497
+ )
1498
+ except NoAuditSourcesError as exc:
1499
+ # Exit 2 like a bad selector: exit 0 here let a typo'd prefix pass a CI gate (#467).
1500
+ # stderr, like _resolve_checkpoint: `--format json` stdout stays a clean payload.
1501
+ err_console.print(f"[bold red]❌ {escape(str(exc))}[/bold red]")
1502
+ raise typer.Exit(code=2) from exc
1497
1503
 
1498
1504
  if output_format == OutputFormat.JSON:
1499
1505
  typer.echo(_json.dumps(dataclasses.asdict(result), indent=2))
@@ -51,29 +51,100 @@ class ReachabilityAudit:
51
51
  gaps: list[NodeRef]
52
52
 
53
53
 
54
+ class NoAuditSourcesError(ValueError):
55
+ """The selectors matched no source to audit, so there is no result to report (#467).
56
+
57
+ Raised instead of returning empty ``covered``/``gaps``: callers — and CI gates
58
+ reading ``gaps == []`` — would otherwise take an audit of nothing for a clean one.
59
+ """
60
+
61
+
62
+ _SUGGESTION_LIMIT = 5
63
+
64
+
65
+ def _describe_selection(from_type: NodeType | None, from_prefix: str | None) -> str:
66
+ """Render the selectors the way a caller passed them, for the error message."""
67
+ parts = []
68
+ if from_type is not None:
69
+ parts.append(f"from_type={from_type.value}")
70
+ if from_prefix is not None:
71
+ parts.append(f"from_prefix={from_prefix!r}")
72
+ return " and ".join(parts)
73
+
74
+
54
75
  def _prefix_matches(fqn: str, prefix: str) -> bool:
55
76
  """Dot-boundary prefix match — ``app.routes`` matches ``app.routes.x``, not ``app.routesX``."""
56
77
  return fqn == prefix or fqn.startswith(f"{prefix}.")
57
78
 
58
79
 
80
+ def _is_candidate(node: Node, from_type: NodeType | None, target_fqn: str) -> bool:
81
+ """An INTERNAL node of the requested type that is not the checkpoint — a possible source."""
82
+ return (
83
+ node.namespace == NodeNamespace.INTERNAL
84
+ and (from_type is None or node.type == from_type)
85
+ and node.id != target_fqn
86
+ )
87
+
88
+
59
89
  def _select_sources(
60
- store: SQLiteStore, from_type: NodeType | None, from_prefix: str | None
90
+ nodes: list[Node], target_fqn: str, from_type: NodeType | None, from_prefix: str | None
61
91
  ) -> list[Node]:
62
92
  """Select INTERNAL source nodes by node type and/or dot-boundary FQN prefix (AND-combined).
63
93
 
64
94
  Restricted to INTERNAL nodes so the audit never flags stdlib/third-party
65
95
  code, and the prefix is boundary-aware so a name overlap (``app.routesX``)
66
- can't sneak into an ``app.routes`` selection.
96
+ can't sneak into an ``app.routes`` selection. The checkpoint is never its
97
+ own source.
67
98
  """
68
99
  return [
69
100
  node
70
- for node in store.get_all_nodes()
71
- if node.namespace == NodeNamespace.INTERNAL
72
- and (from_type is None or node.type == from_type)
101
+ for node in nodes
102
+ if _is_candidate(node, from_type, target_fqn)
73
103
  and (from_prefix is None or _prefix_matches(node.id, from_prefix))
74
104
  ]
75
105
 
76
106
 
107
+ def _empty_selection_hint(
108
+ nodes: list[Node], target_fqn: str, from_type: NodeType | None, from_prefix: str | None
109
+ ) -> str:
110
+ """Explain an empty selection: the whole-segment prefix meant, or what the prefix does hold.
111
+
112
+ Suggestions come from the same candidates ``_select_sources`` would accept, so
113
+ every suggested prefix selects at least one source. That also means the input
114
+ is never offered back: a candidate completing to ``from_prefix`` would itself
115
+ have been selected. A trailing dot is dropped first: ``app.routes.`` meant
116
+ ``app.routes``.
117
+ """
118
+ if from_prefix is None:
119
+ return ""
120
+ stem = from_prefix.rstrip(".")
121
+ suggestions: set[str] = set()
122
+ for node in nodes:
123
+ if _is_candidate(node, from_type, target_fqn) and node.id.startswith(stem):
124
+ next_dot = node.id.find(".", len(stem))
125
+ suggestions.add(node.id if next_dot == -1 else node.id[:next_dot])
126
+ if suggestions:
127
+ listing = ", ".join(sorted(suggestions)[:_SUGGESTION_LIMIT])
128
+ return f"Prefixes match whole dot-segments; did you mean: {listing}?"
129
+ under = [
130
+ n for n in nodes if n.namespace == NodeNamespace.INTERNAL and _prefix_matches(n.id, stem)
131
+ ]
132
+ if under and all(n.id == target_fqn for n in under):
133
+ return "Only the checkpoint itself is under that prefix, and it is never its own source."
134
+ if under and from_type is not None:
135
+ return f"There are nodes under that prefix, but none of type {from_type.value}."
136
+ return ""
137
+
138
+
139
+ def _no_sources_error(
140
+ nodes: list[Node], target_fqn: str, from_type: NodeType | None, from_prefix: str | None
141
+ ) -> NoAuditSourcesError:
142
+ """Build the error for an empty selection, with a hint when one can be given."""
143
+ msg = f"No sources matched {_describe_selection(from_type, from_prefix)} — nothing was audited."
144
+ hint = _empty_selection_hint(nodes, target_fqn, from_type, from_prefix)
145
+ return NoAuditSourcesError(f"{msg} {hint}" if hint else msg)
146
+
147
+
77
148
  def _ref(node: Node) -> NodeRef:
78
149
  """Build a located reference from a node."""
79
150
  return NodeRef(fqn=node.id, file=node.file_path, line=node.start_line)
@@ -112,11 +183,20 @@ def audit_reachability(
112
183
  already-injected instance — so a dependency-injected collaborator looks like
113
184
  a gap. Target the specific method (or the constructor) when auditing "does X
114
185
  use this collaborator".
186
+
187
+ Raises:
188
+ NoAuditSourcesError: The selectors match no source other than the checkpoint
189
+ itself. An empty ``covered``/``gaps`` pair would read as a passing audit.
115
190
  """
116
191
  from_prefix = from_prefix.strip() or None if from_prefix is not None else None
117
192
  if from_type is None and from_prefix is None:
118
193
  msg = "audit_reachability requires from_type or a non-empty from_prefix to select sources."
119
194
  raise ValueError(msg)
195
+ nodes = store.get_all_nodes()
196
+ # Select before traversing: an empty selection has nothing to prove.
197
+ sources = _select_sources(nodes, target_fqn, from_type, from_prefix)
198
+ if not sources:
199
+ raise _no_sources_error(nodes, target_fqn, from_type, from_prefix)
120
200
  engine = QueryEngine(store)
121
201
  # `is not None`, not `or`: an explicit empty frozenset (no-traversal, target-only)
122
202
  # is a valid intent and must not be overridden by the enforcement default.
@@ -127,8 +207,6 @@ def audit_reachability(
127
207
  reaching = {node.id for node in upstream_nodes}
128
208
  covered: list[NodeRef] = []
129
209
  gaps: list[NodeRef] = []
130
- for source in sorted(_select_sources(store, from_type, from_prefix), key=lambda n: n.id):
131
- if source.id == target_fqn:
132
- continue
210
+ for source in sorted(sources, key=lambda n: n.id):
133
211
  (covered if source.id in reaching else gaps).append(_ref(source))
134
212
  return ReachabilityAudit(target=target_fqn, covered=covered, gaps=gaps)
@@ -4,8 +4,8 @@ from pathlib import Path
4
4
 
5
5
  import pytest
6
6
 
7
- from cgis.core.models import Edge, EdgeType, Node, NodeType
8
- from cgis.query.context.audit import audit_reachability
7
+ from cgis.core.models import Edge, EdgeType, Node, NodeNamespace, NodeType
8
+ from cgis.query.context.audit import NoAuditSourcesError, audit_reachability
9
9
  from cgis.storage.sqlite_store import SQLiteStore
10
10
 
11
11
 
@@ -105,6 +105,102 @@ def test_audit_from_prefix_selects_sources(tmp_path: Path) -> None:
105
105
  assert {r.fqn for r in result.gaps} == {"app.routes.h3"}
106
106
 
107
107
 
108
+ @pytest.mark.parametrize(
109
+ ("selector", "named"),
110
+ [
111
+ ({"from_prefix": "app.rou"}, "from_prefix='app.rou'"), # partial dot-segment
112
+ ({"from_prefix": "nope"}, "from_prefix='nope'"),
113
+ ({"from_type": NodeType.API_ENDPOINT}, "from_type=API_ENDPOINT"),
114
+ ({"from_type": NodeType.ROUTE_HANDLER, "from_prefix": "app.svc"}, "from_prefix='app.svc'"),
115
+ ],
116
+ )
117
+ def test_audit_selecting_no_sources_raises_instead_of_an_empty_result(
118
+ tmp_path: Path, selector: dict[str, object], named: str
119
+ ) -> None:
120
+ """Zero audited sources is not a clean audit — `gaps == []` would pass a CI gate (#467)."""
121
+ db = _store(tmp_path, *_graph())
122
+ with SQLiteStore(db) as store, pytest.raises(NoAuditSourcesError) as excinfo:
123
+ audit_reachability(store, target_fqn="app.verify_owner", **selector) # type: ignore[arg-type]
124
+ message = str(excinfo.value)
125
+ assert "nothing was audited" in message
126
+ assert named in message
127
+
128
+
129
+ def test_audit_no_sources_error_suggests_whole_segment_prefixes(tmp_path: Path) -> None:
130
+ """A partial last segment names the dot-complete prefixes that would have matched."""
131
+ db = _store(tmp_path, *_graph())
132
+ with (
133
+ SQLiteStore(db) as store,
134
+ pytest.raises(NoAuditSourcesError, match=r"did you mean: app\.routes\?"),
135
+ ):
136
+ audit_reachability(store, target_fqn="app.verify_owner", from_prefix="app.rou")
137
+
138
+
139
+ @pytest.mark.parametrize(
140
+ ("selector", "hint"),
141
+ [
142
+ # Whole segment, wrong type: the fix is the type, not the prefix.
143
+ (
144
+ {"from_type": NodeType.ROUTE_HANDLER, "from_prefix": "app.svc"},
145
+ "none of type ROUTE_HANDLER",
146
+ ),
147
+ # Whole segment naming the checkpoint: nothing else lives there.
148
+ ({"from_prefix": "app.verify_owner"}, "Only the checkpoint itself"),
149
+ ],
150
+ )
151
+ def test_audit_no_sources_error_never_suggests_the_prefix_back(
152
+ tmp_path: Path, selector: dict[str, object], hint: str
153
+ ) -> None:
154
+ """A suggestion equal to the input is noise; say why the whole segment selected nothing."""
155
+ db = _store(tmp_path, *_graph())
156
+ with SQLiteStore(db) as store, pytest.raises(NoAuditSourcesError) as excinfo:
157
+ audit_reachability(store, target_fqn="app.verify_owner", **selector) # type: ignore[arg-type]
158
+ message = str(excinfo.value)
159
+ assert "did you mean" not in message
160
+ assert hint in message
161
+
162
+
163
+ def test_audit_no_sources_suggestions_respect_type_and_namespace(tmp_path: Path) -> None:
164
+ """Suggest only prefixes that would select sources: same type, INTERNAL only."""
165
+ nodes, edges = _graph()
166
+ nodes.append(
167
+ Node(
168
+ id="app.roulette.spin",
169
+ type=NodeType.ROUTE_HANDLER,
170
+ name="spin",
171
+ file_path="<stdlib>",
172
+ start_line=0,
173
+ end_line=0,
174
+ namespace=NodeNamespace.STDLIB,
175
+ )
176
+ )
177
+ nodes.append(_node("app.robots.index", NodeType.FUNCTION, 80))
178
+ db = _store(tmp_path, nodes, edges)
179
+ with SQLiteStore(db) as store, pytest.raises(NoAuditSourcesError) as excinfo:
180
+ audit_reachability(
181
+ store,
182
+ target_fqn="app.verify_owner",
183
+ from_type=NodeType.ROUTE_HANDLER,
184
+ from_prefix="app.ro",
185
+ )
186
+ assert "did you mean: app.routes?" in str(excinfo.value)
187
+
188
+
189
+ def test_audit_trailing_dot_suggests_the_prefix_without_it(tmp_path: Path) -> None:
190
+ """`app.routes.` meant `app.routes`, not a list of its children."""
191
+ db = _store(tmp_path, *_graph())
192
+ with SQLiteStore(db) as store, pytest.raises(NoAuditSourcesError) as excinfo:
193
+ audit_reachability(store, target_fqn="app.verify_owner", from_prefix="app.routes.")
194
+ assert "did you mean: app.routes?" in str(excinfo.value)
195
+
196
+
197
+ def test_audit_selecting_only_the_target_raises(tmp_path: Path) -> None:
198
+ """The checkpoint is never its own source, so a selection of just it audits nothing."""
199
+ db = _store(tmp_path, *_graph())
200
+ with SQLiteStore(db) as store, pytest.raises(NoAuditSourcesError):
201
+ audit_reachability(store, target_fqn="app.verify_owner", from_prefix="app.verify_owner")
202
+
203
+
108
204
  def test_audit_empty_prefix_is_treated_as_unset(tmp_path: Path) -> None:
109
205
  """A whitespace-only from_prefix is treated as unset — error if it's the only selector."""
110
206
  db = _store(tmp_path, *_graph())
@@ -1393,6 +1393,19 @@ def test_audit_requires_a_selector(tmp_path: Path) -> None:
1393
1393
  assert "from-type" in result.output
1394
1394
 
1395
1395
 
1396
+ @pytest.mark.parametrize("output_format", ["text", "json"])
1397
+ def test_audit_selecting_no_sources_fails_the_gate(tmp_path: Path, output_format: str) -> None:
1398
+ """Zero sources exits 2 — before #467 it exited 0, so a typo'd prefix passed CI."""
1399
+ db = _audit_db(tmp_path)
1400
+ result = runner.invoke(
1401
+ app,
1402
+ ["audit", "verify_owner", "--from-prefix", "app.h", "--db", db, "--format", output_format],
1403
+ )
1404
+ assert result.exit_code == 2
1405
+ assert "nothing was audited" in result.stderr
1406
+ assert "nothing was audited" not in result.stdout # keeps --format json stdout clean
1407
+
1408
+
1396
1409
  # --- suggest-packages command tests ---
1397
1410
 
1398
1411
 
@@ -829,6 +829,15 @@ def test_cgis_audit_whitespace_prefix_is_rejected(tmp_path: Path) -> None:
829
829
  assert "from_type or from_prefix" in result
830
830
 
831
831
 
832
+ def test_cgis_audit_selecting_no_sources_is_an_error_not_an_empty_audit(tmp_path: Path) -> None:
833
+ """A partial prefix must not come back as JSON with empty covered/gaps (#467)."""
834
+ db = _audit_graph_db(tmp_path)
835
+ result = cgis_audit_reachability("app.guard", db, from_prefix="ap")
836
+ assert result.startswith("❌")
837
+ assert "nothing was audited" in result
838
+ assert '"gaps"' not in result
839
+
840
+
832
841
  def test_cgis_audit_none_params_do_not_crash(tmp_path: Path) -> None:
833
842
  """JSON null for from_type/from_prefix must not crash on .strip() (#236)."""
834
843
  db = _audit_graph_db(tmp_path)
@@ -261,7 +261,7 @@ wheels = [
261
261
 
262
262
  [[package]]
263
263
  name = "codegraph-brain"
264
- version = "0.23.0"
264
+ version = "0.23.1"
265
265
  source = { editable = "." }
266
266
  dependencies = [
267
267
  { name = "httpx" },
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.23.0"
3
- }