codegraph-brain 0.16.0__tar.gz → 0.17.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.
- codegraph_brain-0.17.0/.github/test-count-baseline +1 -0
- codegraph_brain-0.17.0/.release-please-manifest.json +3 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/CHANGELOG.md +17 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/PKG-INFO +18 -5
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/README.md +17 -4
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/diagrams/pipeline_flow.mermaid +12 -2
- codegraph_brain-0.17.0/docs/specs/2026-09-05-annotation-graph-design.md +382 -0
- codegraph_brain-0.17.0/docs/specs/plans/2026-09-05-annotation-graph-pr1.md +1042 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/pyproject.toml +1 -1
- codegraph_brain-0.17.0/src/cgis/extractors/_python_annotations.py +139 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/_python_ast.py +54 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/_python_functions.py +186 -11
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/python_extractor.py +65 -2
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/render/mermaid.py +14 -1
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/engine.py +34 -6
- codegraph_brain-0.17.0/tests/self_parsing/test_annotation_calibration.py +93 -0
- codegraph_brain-0.17.0/tests/unit/test_annotation_edges.py +197 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_mermaid.py +54 -0
- codegraph_brain-0.17.0/tests/unit/test_python_annotations.py +250 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_resolver.py +26 -5
- codegraph_brain-0.17.0/tests/unit/test_self_types.py +177 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/uv.lock +1 -1
- codegraph_brain-0.16.0/.github/test-count-baseline +0 -1
- codegraph_brain-0.16.0/.release-please-manifest.json +0 -3
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.claude-plugin/marketplace.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.gitattributes +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.github/workflows/autodoc.yml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.github/workflows/ci.yml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.github/workflows/guardian.yml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.github/workflows/pr-title.yml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.github/workflows/release-please.yml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.gitignore +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.pre-commit-config.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/.python-version +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/CLAUDE.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/CONTRIBUTING.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/LICENSE +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/Makefile +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/PRIVACY.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/CURATION.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/calibration.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/246-cross-vendor/README.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/246-cross-vendor/free-nemotron-quota-cutoff.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/401-evidence/README.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/401-evidence/pr-399-control-rows.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/401-evidence/pr-399-recording.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/401-evidence/pr-399-treatment-rows.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/407-no-checker-appeal/README.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-directive-rows.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-prohibition-rows.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-122.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-140.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-141.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-142.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-143.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-144.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-278.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/pr-313.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/guardian/results.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/README.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/cal_dot_com.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/discourse.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/grafana.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/keycloak.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian/sentry.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-judged.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-p3-judged-run1.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-p3-judged-run1.jsonl.corrupted-backup +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-p3-run1.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-p3-run2.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-p3-run3.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-plan.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-repeat-judged.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-repeat-reviews.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/benchmarks/martian-reviews.jsonl +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/data/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/AUDIT.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/CASE_STUDY.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/GUARDIAN_LOCAL_BENCH.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/GUARDIAN_REMOTE_OLLAMA.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/HOW_IT_WORKS.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/ONTOLOGY.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/PATTERNS_AND_TRIADS.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/SELF_PORTRAIT.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/health_badge.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/assets/.gitignore +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/assets/cgis-app-avatar.png +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/assets/cgis-app-avatar.svg +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/assets/generate_avatar.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/examples/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/how-to/AGENT_ONBOARDING.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/how-to/CLI_USAGE.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/how-to/MCP_REFERENCE.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/lab-notes/2026-06-11-chunked-review-negative-result.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/ontology/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/ontology/core.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/ontology/domains.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/ontology/patterns.yaml +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/ontology/tolerances.lock +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-09-domain-pattern-fingerprint-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-09-pattern-alphabet-motif-basis-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-10-guardian-sprint-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-fastapi-di-edges-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-guardian-chunked-review-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-guardian-chunker-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-mcp-drift-validate-fqn-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-resolver-split-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-11-symbol-import-edges-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-12-drift-empty-domains-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-12-gate-semantics-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-12-init-ontology-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-12-release-please-ci-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-13-suggest-packages-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-06-13-tangle-anti-pattern-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-29-guardian-skeptic-scoring-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-cgis-fractal-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-cgis-fractal-plan.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-chunk-source-filter-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-chunk-source-filter-plan.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-genai-client-close-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-genai-client-close-plan.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-guardian-precision-bench-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-guardian-precision-bench-plan.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-guardian-timeout-retry-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-30-guardian-timeout-retry-plan.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-07-31-finder-bug-class-taxonomy.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-08-01-aura-autoevolution-poc.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-08-11-guardian-code-review-bench.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/2026-08-14-review-fingerprint-design.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/BLUEPRINT.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/PRD.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/TDD.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-09-fingerprint-drift.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-10-guardian-structured-findings-bench.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-10-motif-basis-part-b.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-10-unified-pattern-alphabet.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-11-fastapi-di-edges.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-11-guardian-chunked-review.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-11-guardian-chunker.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-11-mcp-drift-validate-fqn.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-11-resolver-split.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-12-drift-empty-domains.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-12-gate-semantics.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-12-init-ontology.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-12-release-please-ci.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-12-symbol-import-edges.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-06-13-suggest-packages.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-07-29-guardian-skeptic-scoring.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/specs/plans/2026-08-14-review-fingerprint.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/main.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/plugin/.claude-plugin/plugin.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/plugin/.mcp.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/plugin/README.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/plugin/skills/cgis/SKILL.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/plugin/skills/ingest/SKILL.md +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/release-please-config.json +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/backfill_calibration_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/backfill_review_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/check_pytest_raises.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/check_test_count.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/colab_bench.sh +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/gen_ideal_graph.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/generate_health.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/generate_mcp_ref.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/generate_schema_docs.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/guardian_bench.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/guardian_calibrate.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/guardian_martian.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/guardian_replay_skeptic.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/guardian_review.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/inject_readme_graph.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/ollama_visitor.sh +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/probe_closure_gap.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/probe_tier_ladder.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/recordings_from_corpus.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/scripts/skeptic_arms.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/__main__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/api/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/api/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/api/mcp_server.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/cli.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/core/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/core/models.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/_python_classes.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/_python_imports.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/_python_types.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/base.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/registry.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/extractors/typescript_extractor.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/axes.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/bench.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/calibrate.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/chunked.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/chunker.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/collector.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/core.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/diff_index.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/evidence.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/findings.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/github_poster.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/martian.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/metrics.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/prompts.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/base.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/gemini.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/mistral.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/ollama.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/providers/openrouter.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/recording.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/render.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/review_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/runner.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/guardian/skeptic.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/pipeline.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/py.typed +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/analyzer.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/anomaly.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/cohesion.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/health.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/analysis/suggest_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/context/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/context/audit.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/context/context_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/context/prompt.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/context/snippet.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/_scc.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/drift.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/drift_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/fractal.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/ontology_init.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/quotient.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/drift/triads.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/engine.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/fqn.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/render/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/render/graph_json.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/query/render/metrics.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/indices.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/symbols.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/resolver/uplift.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/storage/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/src/cgis/storage/sqlite_store.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/integration/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/__init__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/conftest.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_architecture.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_drift.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_fractal.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_init_ontology_roundtrip.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_self_parse.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_self_parse_ts.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/self_parsing/test_suggest.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/.gitkeep +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/conftest.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/guardian_stubs.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/review_path_inventory.txt +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test___main__.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_analyzer.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_audit.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_backfill_calibration_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_backfill_review_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_check_pytest_raises.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_check_test_count.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_cli.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_cohesion.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_context_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_di_acceptance.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_drift.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_drift_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_extractor_registry.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_fingerprint.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_fqn.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_fractal.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_gen_ideal_graph.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_generate_mcp_ref.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_graph_json.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_axes.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_bench.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_bench_script.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_calibrate.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_calibrate_script.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_chunked.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_chunker.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_collector.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_core.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_diff_index.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_evidence.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_findings.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_martian.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_martian_script.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_martian_union.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_metrics.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_mistral_sampling.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_ollama_sampling.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_ollama_truncation.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_openrouter.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_poster.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_providers.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_providers_name.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_recording.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_render.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_replay_skeptic.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_review_script.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_runner.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_salvage.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_guardian_skeptic.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_health_scorer.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_import_acceptance.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_mcp_server.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_metrics.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_models.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_ontology_compliance.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_ontology_init.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_patterns_yaml.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_pipeline.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_prompt.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_python_extractor.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_quotient.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_recordings_from_corpus.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_resolver_indices.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_resolver_symbols.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_review_fingerprint_closure.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_review_fingerprint_contract.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_review_fingerprint_digest.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_review_fingerprint_record.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_skeptic_arms.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_snippet.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_sqlite_store.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_suggest_service.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_temperature_source.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_triads.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_typescript_extractor.py +0 -0
- {codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/tests/unit/test_uplift.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2110
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.17.0](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.16.0...codegraph-brain-v0.17.0) (2026-09-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **extractors:** record what annotations say — self_types and REFERENCES edges ([#414](https://github.com/zaebee/codegraph-brain/issues/414), [#415](https://github.com/zaebee/codegraph-brain/issues/415)) ([#418](https://github.com/zaebee/codegraph-brain/issues/418)) ([eeaa60b](https://github.com/zaebee/codegraph-brain/commit/eeaa60b831956bb85fff88c987789ea179c2dc71))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **render:** draw one arrow per distinct triple in a mermaid diagram ([#421](https://github.com/zaebee/codegraph-brain/issues/421)) ([19a6067](https://github.com/zaebee/codegraph-brain/commit/19a6067f7c98d84f9d0a3e02e132f85ba0791817))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* auto-sync architecture graph after the annotation-edge work ([#420](https://github.com/zaebee/codegraph-brain/issues/420)) ([061843d](https://github.com/zaebee/codegraph-brain/commit/061843dd0ba997d2fd7549acaa72e7290b10f9cf))
|
|
19
|
+
|
|
3
20
|
## [0.16.0](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.15.0...codegraph-brain-v0.16.0) (2026-08-17)
|
|
4
21
|
|
|
5
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: codegraph-brain
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.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
|
|
@@ -197,6 +197,10 @@ classDef defaultNode fill:#fafafa,stroke:#9e9e9e,stroke-width:1.5px,color:#21212
|
|
|
197
197
|
classDef stdlibNode fill:#eceff1,stroke:#607d8b,stroke-width:1px,color:#455a64;
|
|
198
198
|
classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dasharray: 3 3,color:#bf360c;
|
|
199
199
|
|
|
200
|
+
subgraph sg_models["models.py"]
|
|
201
|
+
models_Edge["Edge (models.py:117)"]:::classNode
|
|
202
|
+
models_Node["Node (models.py:83)"]:::classNode
|
|
203
|
+
end
|
|
200
204
|
subgraph sg_pipeline["pipeline.py"]
|
|
201
205
|
pipeline_IngestionPipeline_get_extractor["_get_extractor (pipeline.py:245)"]:::methodNode
|
|
202
206
|
pipeline_IngestionPipeline_is_noop_incremental["_is_noop_incremental (pipeline.py:185)"]:::methodNode
|
|
@@ -205,13 +209,19 @@ classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dashar
|
|
|
205
209
|
pipeline_IngestionPipeline_run["run (pipeline.py:51)"]:::methodNode
|
|
206
210
|
end
|
|
207
211
|
subgraph sg_engine["engine.py"]
|
|
208
|
-
engine_ResolverEngine["ResolverEngine (engine.py:
|
|
209
|
-
engine_ResolverEngine_resolve["resolve (engine.py:
|
|
212
|
+
engine_ResolverEngine["ResolverEngine (engine.py:19)"]:::classNode
|
|
213
|
+
engine_ResolverEngine_resolve["resolve (engine.py:36)"]:::methodNode
|
|
210
214
|
end
|
|
211
215
|
subgraph sg_uplift["uplift.py"]
|
|
212
216
|
uplift_SemanticUpliftEngine["SemanticUpliftEngine (uplift.py:66)"]:::classNode
|
|
213
217
|
uplift_SemanticUpliftEngine_execute_uplift["execute_uplift (uplift.py:91)"]:::methodNode
|
|
214
218
|
end
|
|
219
|
+
subgraph sg_sqlite_store["sqlite_store.py"]
|
|
220
|
+
sqlite_store_SQLiteStore["SQLiteStore (sqlite_store.py:28)"]:::classNode
|
|
221
|
+
end
|
|
222
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Node
|
|
223
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Edge
|
|
224
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| sqlite_store_SQLiteStore
|
|
215
225
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_get_extractor
|
|
216
226
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_process_file
|
|
217
227
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_is_noop_incremental
|
|
@@ -224,15 +234,18 @@ classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dashar
|
|
|
224
234
|
|
|
225
235
|
| Symbol | Type | File |
|
|
226
236
|
|--------|------|------|
|
|
237
|
+
| `Node` | CLASS | [`models.py:83`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/core/models.py#L83) |
|
|
238
|
+
| `Edge` | CLASS | [`models.py:117`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/core/models.py#L117) |
|
|
227
239
|
| `run` | METHOD | [`pipeline.py:51`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L51) |
|
|
228
240
|
| `_process_file` | METHOD | [`pipeline.py:155`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L155) |
|
|
229
241
|
| `_is_noop_incremental` | METHOD | [`pipeline.py:185`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L185) |
|
|
230
242
|
| `_persist_incremental` | METHOD | [`pipeline.py:204`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L204) |
|
|
231
243
|
| `_get_extractor` | METHOD | [`pipeline.py:245`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L245) |
|
|
232
|
-
| `ResolverEngine` | CLASS | [`engine.py:
|
|
233
|
-
| `resolve` | METHOD | [`engine.py:
|
|
244
|
+
| `ResolverEngine` | CLASS | [`engine.py:19`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/engine.py#L19) |
|
|
245
|
+
| `resolve` | METHOD | [`engine.py:36`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/engine.py#L36) |
|
|
234
246
|
| `SemanticUpliftEngine` | CLASS | [`uplift.py:66`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/uplift.py#L66) |
|
|
235
247
|
| `execute_uplift` | METHOD | [`uplift.py:91`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/uplift.py#L91) |
|
|
248
|
+
| `SQLiteStore` | CLASS | [`sqlite_store.py:28`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/storage/sqlite_store.py#L28) |
|
|
236
249
|
<!-- END_CGIS_GRAPH -->
|
|
237
250
|
|
|
238
251
|
---
|
|
@@ -147,6 +147,10 @@ classDef defaultNode fill:#fafafa,stroke:#9e9e9e,stroke-width:1.5px,color:#21212
|
|
|
147
147
|
classDef stdlibNode fill:#eceff1,stroke:#607d8b,stroke-width:1px,color:#455a64;
|
|
148
148
|
classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dasharray: 3 3,color:#bf360c;
|
|
149
149
|
|
|
150
|
+
subgraph sg_models["models.py"]
|
|
151
|
+
models_Edge["Edge (models.py:117)"]:::classNode
|
|
152
|
+
models_Node["Node (models.py:83)"]:::classNode
|
|
153
|
+
end
|
|
150
154
|
subgraph sg_pipeline["pipeline.py"]
|
|
151
155
|
pipeline_IngestionPipeline_get_extractor["_get_extractor (pipeline.py:245)"]:::methodNode
|
|
152
156
|
pipeline_IngestionPipeline_is_noop_incremental["_is_noop_incremental (pipeline.py:185)"]:::methodNode
|
|
@@ -155,13 +159,19 @@ classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dashar
|
|
|
155
159
|
pipeline_IngestionPipeline_run["run (pipeline.py:51)"]:::methodNode
|
|
156
160
|
end
|
|
157
161
|
subgraph sg_engine["engine.py"]
|
|
158
|
-
engine_ResolverEngine["ResolverEngine (engine.py:
|
|
159
|
-
engine_ResolverEngine_resolve["resolve (engine.py:
|
|
162
|
+
engine_ResolverEngine["ResolverEngine (engine.py:19)"]:::classNode
|
|
163
|
+
engine_ResolverEngine_resolve["resolve (engine.py:36)"]:::methodNode
|
|
160
164
|
end
|
|
161
165
|
subgraph sg_uplift["uplift.py"]
|
|
162
166
|
uplift_SemanticUpliftEngine["SemanticUpliftEngine (uplift.py:66)"]:::classNode
|
|
163
167
|
uplift_SemanticUpliftEngine_execute_uplift["execute_uplift (uplift.py:91)"]:::methodNode
|
|
164
168
|
end
|
|
169
|
+
subgraph sg_sqlite_store["sqlite_store.py"]
|
|
170
|
+
sqlite_store_SQLiteStore["SQLiteStore (sqlite_store.py:28)"]:::classNode
|
|
171
|
+
end
|
|
172
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Node
|
|
173
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Edge
|
|
174
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| sqlite_store_SQLiteStore
|
|
165
175
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_get_extractor
|
|
166
176
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_process_file
|
|
167
177
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_is_noop_incremental
|
|
@@ -174,15 +184,18 @@ classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dashar
|
|
|
174
184
|
|
|
175
185
|
| Symbol | Type | File |
|
|
176
186
|
|--------|------|------|
|
|
187
|
+
| `Node` | CLASS | [`models.py:83`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/core/models.py#L83) |
|
|
188
|
+
| `Edge` | CLASS | [`models.py:117`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/core/models.py#L117) |
|
|
177
189
|
| `run` | METHOD | [`pipeline.py:51`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L51) |
|
|
178
190
|
| `_process_file` | METHOD | [`pipeline.py:155`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L155) |
|
|
179
191
|
| `_is_noop_incremental` | METHOD | [`pipeline.py:185`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L185) |
|
|
180
192
|
| `_persist_incremental` | METHOD | [`pipeline.py:204`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L204) |
|
|
181
193
|
| `_get_extractor` | METHOD | [`pipeline.py:245`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/pipeline.py#L245) |
|
|
182
|
-
| `ResolverEngine` | CLASS | [`engine.py:
|
|
183
|
-
| `resolve` | METHOD | [`engine.py:
|
|
194
|
+
| `ResolverEngine` | CLASS | [`engine.py:19`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/engine.py#L19) |
|
|
195
|
+
| `resolve` | METHOD | [`engine.py:36`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/engine.py#L36) |
|
|
184
196
|
| `SemanticUpliftEngine` | CLASS | [`uplift.py:66`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/uplift.py#L66) |
|
|
185
197
|
| `execute_uplift` | METHOD | [`uplift.py:91`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/resolver/uplift.py#L91) |
|
|
198
|
+
| `SQLiteStore` | CLASS | [`sqlite_store.py:28`](https://github.com/zaebee/codegraph-brain/blob/main/src/cgis/storage/sqlite_store.py#L28) |
|
|
186
199
|
<!-- END_CGIS_GRAPH -->
|
|
187
200
|
|
|
188
201
|
---
|
{codegraph_brain-0.16.0 → codegraph_brain-0.17.0}/docs/architecture/diagrams/pipeline_flow.mermaid
RENAMED
|
@@ -7,6 +7,10 @@ classDef defaultNode fill:#fafafa,stroke:#9e9e9e,stroke-width:1.5px,color:#21212
|
|
|
7
7
|
classDef stdlibNode fill:#eceff1,stroke:#607d8b,stroke-width:1px,color:#455a64;
|
|
8
8
|
classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dasharray: 3 3,color:#bf360c;
|
|
9
9
|
|
|
10
|
+
subgraph sg_models["models.py"]
|
|
11
|
+
models_Edge["Edge (models.py:117)"]:::classNode
|
|
12
|
+
models_Node["Node (models.py:83)"]:::classNode
|
|
13
|
+
end
|
|
10
14
|
subgraph sg_pipeline["pipeline.py"]
|
|
11
15
|
pipeline_IngestionPipeline_get_extractor["_get_extractor (pipeline.py:245)"]:::methodNode
|
|
12
16
|
pipeline_IngestionPipeline_is_noop_incremental["_is_noop_incremental (pipeline.py:185)"]:::methodNode
|
|
@@ -15,13 +19,19 @@ classDef externalNode fill:#fff3e0,stroke:#e65100,stroke-width:1px,stroke-dashar
|
|
|
15
19
|
pipeline_IngestionPipeline_run["run (pipeline.py:51)"]:::methodNode
|
|
16
20
|
end
|
|
17
21
|
subgraph sg_engine["engine.py"]
|
|
18
|
-
engine_ResolverEngine["ResolverEngine (engine.py:
|
|
19
|
-
engine_ResolverEngine_resolve["resolve (engine.py:
|
|
22
|
+
engine_ResolverEngine["ResolverEngine (engine.py:19)"]:::classNode
|
|
23
|
+
engine_ResolverEngine_resolve["resolve (engine.py:36)"]:::methodNode
|
|
20
24
|
end
|
|
21
25
|
subgraph sg_uplift["uplift.py"]
|
|
22
26
|
uplift_SemanticUpliftEngine["SemanticUpliftEngine (uplift.py:66)"]:::classNode
|
|
23
27
|
uplift_SemanticUpliftEngine_execute_uplift["execute_uplift (uplift.py:91)"]:::methodNode
|
|
24
28
|
end
|
|
29
|
+
subgraph sg_sqlite_store["sqlite_store.py"]
|
|
30
|
+
sqlite_store_SQLiteStore["SQLiteStore (sqlite_store.py:28)"]:::classNode
|
|
31
|
+
end
|
|
32
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Node
|
|
33
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| models_Edge
|
|
34
|
+
pipeline_IngestionPipeline_run -->|REFERENCES| sqlite_store_SQLiteStore
|
|
25
35
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_get_extractor
|
|
26
36
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_process_file
|
|
27
37
|
pipeline_IngestionPipeline_run -->|CALLS| pipeline_IngestionPipeline_is_noop_incremental
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# Annotation-aware graph: receiver resolution (#414) and orphan classes (#415)
|
|
2
|
+
|
|
3
|
+
Status: approved design, revised after independent fact-check
|
|
4
|
+
Issues: [#414](https://github.com/zaebee/codegraph-brain/issues/414), [#415](https://github.com/zaebee/codegraph-brain/issues/415)
|
|
5
|
+
|
|
6
|
+
## Problem
|
|
7
|
+
|
|
8
|
+
Two reports, one missing capability underneath both: the graph does not record
|
|
9
|
+
what a name's *type annotation* says.
|
|
10
|
+
|
|
11
|
+
**#414** — a call through an injected collaborator (`self.client.search(...)`)
|
|
12
|
+
never resolves. The edge lands on a placeholder node named `self.client.search`,
|
|
13
|
+
so a dependency-injected layer reads as calling nothing.
|
|
14
|
+
|
|
15
|
+
**#415** — there is no query for "classes nothing constructs or extends", and it
|
|
16
|
+
cannot be precise without an annotation edge: an abstract port that three modules
|
|
17
|
+
type against but nobody constructs looks identical to dead code.
|
|
18
|
+
|
|
19
|
+
## Measurement basis
|
|
20
|
+
|
|
21
|
+
All figures below are from `src/cgis/` at HEAD and a graph ingested from it:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
uv run cgis ingest src --source-root src --output <scratch>.db
|
|
25
|
+
→ 1 563 nodes / 5 011 edges
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Do not use the repo-root `graph.db` for these numbers.** It is untracked,
|
|
29
|
+
gitignored, and dated 2026-07-29 — the v0.4.0 ingest, 113 commits behind. An
|
|
30
|
+
earlier draft of this spec mixed counts from that stale graph with counts from
|
|
31
|
+
HEAD source, and every graph-derived figure in it was wrong. Any future
|
|
32
|
+
re-measurement must re-ingest first.
|
|
33
|
+
|
|
34
|
+
| Measurement | Value |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Total edges | 5 011 |
|
|
37
|
+
| `self.*` placeholder edges | 139 |
|
|
38
|
+
| …classified `INTERNAL` (i.e. counted as **resolved**) | 139 / 139 |
|
|
39
|
+
| …with exactly two segments after `self` (in scope for D8) | 118 |
|
|
40
|
+
| …deeper or shallower (out of scope for D8) | 21 |
|
|
41
|
+
| `self.<attr>.<method>()` call sites in source | 117 |
|
|
42
|
+
| …receiver resolvable from an annotation | 105 (90%) |
|
|
43
|
+
| Annotation positions (param / return / AnnAssign) | 2 328 |
|
|
44
|
+
| …naming at least one internal CLASS | 577 |
|
|
45
|
+
| `REFERENCES` edges emitted (D9 rule) | **583 measured** (predicted 596) |
|
|
46
|
+
| Current `unresolved_ratio` | 0.2030 |
|
|
47
|
+
| Projected after PR2 | 0.2095 (gate: 0.30) |
|
|
48
|
+
| Projected after PR1's edges also land | 0.1873 |
|
|
49
|
+
|
|
50
|
+
Positions exclude 106 bare `-> None` returns, which name no type.
|
|
51
|
+
|
|
52
|
+
### Validated on owner-api
|
|
53
|
+
|
|
54
|
+
The implemented feature was run against `Ownima/owner-api` (`ownima-backend/app`,
|
|
55
|
+
15 928 nodes / 65 792 edges, ~11s) — the DI-heavy codebase #414 was filed from:
|
|
56
|
+
|
|
57
|
+
| Measurement | Value |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `REFERENCES` edges | 2 004 (0 pointing at a non-CLASS node) |
|
|
60
|
+
| classes carrying `self_types` | 677 (2 847 attributes) |
|
|
61
|
+
| `self.<attr>.<method>` sites, **production only** | 554 |
|
|
62
|
+
| …receiver resolvable | **476 (86%)** |
|
|
63
|
+
| …same, tests only | 445 / 1 732 (26%) |
|
|
64
|
+
|
|
65
|
+
86% against the 66% #414 predicted from its two-source rule: the two sources this
|
|
66
|
+
design adds (`self.x: T = ...` and `self.x = SomeClass()`) are worth ~20 points on
|
|
67
|
+
the very repository the issue was filed from. The 26% in tests is 876 unannotated
|
|
68
|
+
`self.client` (httpx) fixtures, which the rule correctly declines to guess at —
|
|
69
|
+
exactly as #414 anticipated. A figure blending the two reads as 40% and is
|
|
70
|
+
meaningless; #414 measured production only, and so must any comparison to it.
|
|
71
|
+
|
|
72
|
+
**The clearest evidence for D9:** of 367 production classes with no incoming
|
|
73
|
+
production `CALLS`/`EXTENDS`, **180 are held alive solely by the new annotation
|
|
74
|
+
edges**. Without D9 all 180 would read as dead code.
|
|
75
|
+
|
|
76
|
+
### Two findings that change the issues as filed
|
|
77
|
+
|
|
78
|
+
**The placeholder is INTERNAL, so it improves the health verdict.**
|
|
79
|
+
`SymbolIndex.classify_fqn` (`resolver/indices.py:91`) returns `INTERNAL` for any
|
|
80
|
+
FQN starting with `self.`, and `get_edge_stats` (`storage/sqlite_store.py:511`)
|
|
81
|
+
counts `INTERNAL` as resolved. All 139 placeholder edges are counted on the good
|
|
82
|
+
side of `unresolved_ratio`. The metric moves the *wrong way* as a codebase adopts
|
|
83
|
+
more DI. #414 filed this as "resolved-to-EXTERNAL"; it is worse than that.
|
|
84
|
+
|
|
85
|
+
**The rule as filed reaches 19%, not 66%.** Attributing each of the 117 call
|
|
86
|
+
sites to the construct that would let its receiver resolve:
|
|
87
|
+
|
|
88
|
+
| attr → type source | sites | in #414 as filed |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `__init__(self, x: T)` + `self.x = x` | 17 | yes |
|
|
91
|
+
| class-body annotation `x: T` | 5 | yes |
|
|
92
|
+
| `self.x: T = ...` (annotated assignment) | 68 | **no** |
|
|
93
|
+
| `self.x = SomeClass(...)` (constructor assignment) | 15 | **no** |
|
|
94
|
+
| **total** | **105 / 117 (90%)** | 22 / 117 (19%) |
|
|
95
|
+
|
|
96
|
+
One site carries both an `__init__` parameter and a class-body annotation; it is
|
|
97
|
+
counted once, under class-body. The 66% reported on `owner-api` reflects that
|
|
98
|
+
repo's DI style. On code that annotates attributes directly, the dominant
|
|
99
|
+
construct is the annotated assignment, which the proposed rule does not mention.
|
|
100
|
+
|
|
101
|
+
## Decisions
|
|
102
|
+
|
|
103
|
+
### D1 — `attr → type` map lives in CLASS node metadata as `self_types`
|
|
104
|
+
|
|
105
|
+
Exact mirror of `local_types`, which already lives in FUNCTION/METHOD node
|
|
106
|
+
metadata and is already read by `_resolve_local_type_call`
|
|
107
|
+
(`resolver/symbols.py:147`). No new index, no new storage shape.
|
|
108
|
+
|
|
109
|
+
For a generic attribute (`items: list[Node]`), `self_types` records the
|
|
110
|
+
*container*, not the argument — `{"items": "pkg.mod.list"}` — because
|
|
111
|
+
`local_types` semantics (what type is this attribute for method-resolution
|
|
112
|
+
purposes) are correct for it, unlike D9's annotation-edge collection below.
|
|
113
|
+
|
|
114
|
+
### D2 — annotation edges reuse `REFERENCES`; no new EdgeType
|
|
115
|
+
|
|
116
|
+
`REFERENCES` already exists and already carries a property this work needs: it is
|
|
117
|
+
deliberately excluded from `_ENFORCEMENT_EDGE_TYPES` (`query/context/audit.py:31`),
|
|
118
|
+
documented as protection against a false "covered" verdict in an authz audit.
|
|
119
|
+
|
|
120
|
+
A new EdgeType inherits nothing. `BEHAVIORAL_EDGE_TYPES` (`query/engine.py:8-11`)
|
|
121
|
+
is defined as *everything that is not structural*, so any new type silently joins
|
|
122
|
+
every default traversal, and each consumer would have to be re-audited to restore
|
|
123
|
+
the safety `REFERENCES` already has.
|
|
124
|
+
|
|
125
|
+
**Drift exposure, stated precisely.** The fingerprint's *censuses* read only
|
|
126
|
+
`IMPORTS` and `CALLS` (`query/drift/fingerprint.py:331-332`), and `quotient.py`
|
|
127
|
+
and `fractal.py` likewise — so `t_imports`/`t_calls` cannot move. But
|
|
128
|
+
`edge_count = len(internal_edges)` (`fingerprint.py:346`) counts **every** edge
|
|
129
|
+
type, and `drift.py:365` returns `status="no_signal"` when it is zero. A
|
|
130
|
+
`REFERENCES` edge can therefore flip a domain from `no_signal` to scored. No
|
|
131
|
+
realistic domain is exposed (anything with a file and a child already has
|
|
132
|
+
`CONTAINS` edges), but "cannot move a drift baseline" is stronger than the code
|
|
133
|
+
guarantees, and PR1 must check the self-drift status column rather than assume.
|
|
134
|
+
|
|
135
|
+
### D3 — emit an annotation edge only when the type resolves to an INTERNAL node
|
|
136
|
+
|
|
137
|
+
Stdlib, external, and unresolved annotations are dropped. Edging every position
|
|
138
|
+
regardless of namespace would add 2 328 edges (+46%) of `str`/`dict`/library
|
|
139
|
+
noise and swamp every metric; an `x: str` annotation says nothing about orphan
|
|
140
|
+
classes. Scoped to internal classes it is 583 edges (+11.6%), measured on the
|
|
141
|
+
implemented feature; the 596 in an earlier draft was an AST prediction.
|
|
142
|
+
|
|
143
|
+
### D4 — annotation positions: parameter, return, `AnnAssign`
|
|
144
|
+
|
|
145
|
+
Parameters already traverse most of the path: `collect_param_type`
|
|
146
|
+
(`extractors/_python_functions.py:267`) emits `raw_dep:<Type>`, and
|
|
147
|
+
`_resolved_dep_edge` (`resolver/engine.py:103`) drops it unless it resolves to a
|
|
148
|
+
VARIABLE. The resolution branch is an extension, not a new mechanism:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
raw_dep:<T> → VARIABLE (DI alias) → DEPENDS_ON (unchanged)
|
|
152
|
+
→ internal CLASS → REFERENCES (new)
|
|
153
|
+
→ anything else → dropped (unchanged)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Return and `AnnAssign` positions reuse that road with new emissions. **What they
|
|
157
|
+
cannot reuse is the type-name extraction — see D9.**
|
|
158
|
+
|
|
159
|
+
**Deliberately excluded: `response_model=SomeSchema`.** That is a value in a call
|
|
160
|
+
keyword, not an annotation — a different extraction path. Request schemas are
|
|
161
|
+
caught as parameter annotations; **response schemas will not be**. #415 reports
|
|
162
|
+
that 11 of its 14 `app/domains` findings are request/response schemas, so this
|
|
163
|
+
leaves a known precision gap on the response half. It is measured in PR3, where
|
|
164
|
+
the false positives it causes are observable, rather than guessed at now.
|
|
165
|
+
|
|
166
|
+
### D5 — `is_test` is a column, populated at ingest from one `is_test_path()` helper
|
|
167
|
+
|
|
168
|
+
cgis has no notion of a test source today. `_TEST_FILE_PATTERN`
|
|
169
|
+
(`pipeline.py:243`) matches only `foo.test.py` — a JS convention — while
|
|
170
|
+
`tests/`, `test_*.py` and `conftest.py` are ingested as ordinary code. Verified
|
|
171
|
+
on a fixture: a test's construction of a class becomes an ordinary `CALLS` edge,
|
|
172
|
+
identical in every column but source and location. #415's own table shows that
|
|
173
|
+
without this filter all six of its rows read as live, including both real orphans.
|
|
174
|
+
|
|
175
|
+
A column follows the `namespace` precedent exactly, including the `ALTER TABLE`
|
|
176
|
+
path in `_migrate()` (`storage/sqlite_store.py:113`). The decision itself lives in
|
|
177
|
+
a single `is_test_path()` function so that "what is a test" has one definition;
|
|
178
|
+
the column is its cached result, visible to the schema and filterable in SQL.
|
|
179
|
+
|
|
180
|
+
Patterns are hardcoded: any path segment named `tests`, plus `test_*.py`,
|
|
181
|
+
`*_test.py`, `conftest.py`. That covers both repositories that exist —
|
|
182
|
+
`codegraph-brain/tests/` and `owner-api/app/tests/_shared/`. Configuration is
|
|
183
|
+
deferred until a third layout gives it something concrete to express.
|
|
184
|
+
|
|
185
|
+
**Scope limit, deliberate.** The existing `_get_extractor` drop of `.test.py` /
|
|
186
|
+
`.test.ts` files is left alone. Marking Python tests is purely additive — no node
|
|
187
|
+
appears or disappears, so every existing metric is byte-identical and a drift
|
|
188
|
+
movement cannot be blamed on this work. Unifying the drop would add nodes to the
|
|
189
|
+
`ui/` TypeScript graph and move its fingerprint in the same diff, making both
|
|
190
|
+
changes unmeasurable. The inconsistency that remains (Python tests marked, JS
|
|
191
|
+
tests dropped) gets an explanatory comment at `_TEST_FILE_PATTERN` and a
|
|
192
|
+
follow-up issue — it is not left silent.
|
|
193
|
+
|
|
194
|
+
### D6 — resolution confidence 0.9, not 0.8
|
|
195
|
+
|
|
196
|
+
In `_resolved_call_edge` (`resolver/engine.py:84`), the `0.8` at line 100 is the
|
|
197
|
+
value assigned on resolution *failure*. Reusing it for an annotation-based
|
|
198
|
+
success would make the two indistinguishable on the column that `min_confidence`
|
|
199
|
+
traversal filters read.
|
|
200
|
+
|
|
201
|
+
### D7 — reuse the existing hierarchy walk and phantom-method policy
|
|
202
|
+
|
|
203
|
+
`_resolve_method_on_class_hierarchy` (`resolver/symbols.py:115`) already walks
|
|
204
|
+
EXTENDS with cycle protection. `_resolve_local_type_call` (`symbols.py:147`)
|
|
205
|
+
already implements the policy #414 needs for its motivating bug: a method that
|
|
206
|
+
does not exist is kept only when the receiver's type is EXTERNAL or STDLIB, and
|
|
207
|
+
dropped for internal *and unknown* types rather than fabricated. Routing
|
|
208
|
+
`self.<attr>.<method>` through that path is what makes a
|
|
209
|
+
deleted-`# type: ignore[attr-defined]`-shaped call visible, and it needs no new
|
|
210
|
+
policy.
|
|
211
|
+
|
|
212
|
+
### D8 — receiver resolution covers exactly two segments after `self`
|
|
213
|
+
|
|
214
|
+
`self.<attr>.<method>` only — 118 of the 139 placeholder edges. The remaining 21
|
|
215
|
+
are deeper chains (`self._conn.execute(...).fetchall()`, which the extractor
|
|
216
|
+
flattens to target `self._conn.execute.fetchall`) or bare `self._pick_source_root`
|
|
217
|
+
attribute calls.
|
|
218
|
+
|
|
219
|
+
**Those 21 do not keep their current behavior.** PR2's `classify_fqn` split (see
|
|
220
|
+
PR2 below) reclassifies *every* `self.`-prefixed FQN, so all 21 flip from
|
|
221
|
+
counting as resolved to counting as unresolved, even though no resolution is
|
|
222
|
+
attempted for them. That is the honest accounting — they were never resolved —
|
|
223
|
+
but it is a change, and the projected ratio above includes it: 12 unresolvable
|
|
224
|
+
two-segment sites plus 21 out-of-scope placeholders, `(1017+33)/5011 = 0.2095`.
|
|
225
|
+
|
|
226
|
+
### D9 — an annotation names every internal class inside it, not its cleaned head
|
|
227
|
+
|
|
228
|
+
`clean_python_type_string` (`extractors/_python_types.py:44`) reduces `list[Node]`
|
|
229
|
+
to `list`: it answers "what type is this variable" — correct for `local_types`,
|
|
230
|
+
where the receiver of `x.append()` really is a `list`. It is the wrong question
|
|
231
|
+
for a reference edge.
|
|
232
|
+
|
|
233
|
+
Measured on HEAD: of 577 annotation positions naming an internal class, that
|
|
234
|
+
function surfaces the class in only 247. **330 (57%) are swallowed by a generic
|
|
235
|
+
wrapper** — `list[...]` (211), `tuple[...]` (33), `dict[...]` (30), `frozenset`
|
|
236
|
+
(16), `Sequence` (15) and others. Eleven internal classes are referenced *only*
|
|
237
|
+
from inside generics and would receive zero annotation edges:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
AmbiguousEntry, ArchitecturalAnomaly, Bridge, Community, DuckDBAnalyzer,
|
|
241
|
+
GoldenComment, NodeMetric, PrPlan, SliceCounts, _IdAllocator
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
(An earlier draft listed `UnionRun` here too. That was wrong: its only
|
|
245
|
+
external-looking mention is the self-referencing return annotation described
|
|
246
|
+
above, so it is a genuine orphan candidate rather than a D9 rescue.)
|
|
247
|
+
|
|
248
|
+
Any of those that is also constructed only from tests would be reported as a
|
|
249
|
+
false orphan by #415 — the exact failure the annotation edge exists to prevent.
|
|
250
|
+
|
|
251
|
+
So annotation extraction collects **all** type names appearing in the annotation
|
|
252
|
+
(walking `Name`/`Attribute` nodes, and parsing string annotations), emitting one
|
|
253
|
+
`REFERENCES` edge per distinct internal class. `clean_python_type_string` is left
|
|
254
|
+
untouched and keeps serving `local_types`. This is what raises the edge count
|
|
255
|
+
from 247 to 583.
|
|
256
|
+
|
|
257
|
+
**Two exclusions, discovered during implementation and not in the original
|
|
258
|
+
design.** "Every name in the annotation" is too literal on its own:
|
|
259
|
+
|
|
260
|
+
* **Typing wrappers unwrap rather than count.** `Optional`, `Union` and
|
|
261
|
+
`Annotated` are not classes anyone would reference, so they are dropped while
|
|
262
|
+
their arguments are kept — `Optional[Node]` yields `Node`, not both. Qualified
|
|
263
|
+
forms (`typing.Optional[X]`) unwrap identically; the module prefix is stripped
|
|
264
|
+
before the wrapper test, matching `clean_python_type_string`. Note that
|
|
265
|
+
tree-sitter parses `Optional[X]` as `generic_type` but `typing.Optional[X]` as
|
|
266
|
+
`subscript`, so both shapes must be handled — an early implementation handled
|
|
267
|
+
only the first and leaked `raw_dep:typing.Optional`.
|
|
268
|
+
* **Call nodes are skipped.** In `Annotated[Session, Depends(get_db)]` the second
|
|
269
|
+
argument is metadata, not a type; collecting it would emit candidates for
|
|
270
|
+
`Depends` and `get_db`. The annotation yields `Session` alone.
|
|
271
|
+
|
|
272
|
+
Ordinary containers are NOT wrappers and keep both parts: `list[Node]` yields
|
|
273
|
+
`list` and `Node`, which is the entire point of D9. A dotted non-wrapper base is
|
|
274
|
+
preserved whole — `collections.abc.Sequence[Node]` yields both.
|
|
275
|
+
|
|
276
|
+
**A self-reference is not a reference.** `-> "UnionRun"` on `UnionRun`'s own
|
|
277
|
+
classmethod produces no incoming edge for `UnionRun`. This is implemented, not
|
|
278
|
+
emergent: `_resolved_dep_edge` (`resolver/engine.py`) drops the candidate when
|
|
279
|
+
`edge.source` equals the resolved class target or lives inside it (a method,
|
|
280
|
+
or a nested class — checked as `edge.source.startswith(f"{class_target}.")`,
|
|
281
|
+
a dot-boundary test so `Foo` is not treated as inside `FooBar`). A class
|
|
282
|
+
naming itself is not evidence anyone uses it, and counting it would
|
|
283
|
+
manufacture a false negative in the orphan query.
|
|
284
|
+
|
|
285
|
+
## Work breakdown
|
|
286
|
+
|
|
287
|
+
Three sequential PRs. Each merges before the next starts.
|
|
288
|
+
|
|
289
|
+
### PR1 — extractor foundation
|
|
290
|
+
|
|
291
|
+
* `self_types` on CLASS node metadata, from all four sources in the table above.
|
|
292
|
+
* Type-name collection per D9, separate from `clean_python_type_string`.
|
|
293
|
+
* `raw_dep:` emission extended to return and `AnnAssign` positions.
|
|
294
|
+
* `_resolved_dep_edge` gains the internal-CLASS → `REFERENCES` branch (D4).
|
|
295
|
+
* Check the self-drift `status` column for any domain moving off `no_signal` (D2).
|
|
296
|
+
|
|
297
|
+
Serves both issues; neither can be precise without it.
|
|
298
|
+
|
|
299
|
+
### PR2 — #414 receiver resolution
|
|
300
|
+
|
|
301
|
+
* `resolve_self_call` handles the dotted form: split `client.search` into
|
|
302
|
+
receiver and method, look up `self_types`, then delegate to the existing
|
|
303
|
+
hierarchy walk (D7).
|
|
304
|
+
* `classify_fqn` stops reporting `self.`-prefixed FQNs as `INTERNAL`. The
|
|
305
|
+
leading-`.` (relative import) branch is unchanged; the two currently share one
|
|
306
|
+
condition (`indices.py:91`) and must be split.
|
|
307
|
+
* Fixes the placeholder collision as a consequence: two unrelated classes with a
|
|
308
|
+
same-named attribute no longer share one vertex.
|
|
309
|
+
|
|
310
|
+
### PR3 — #415 orphan query
|
|
311
|
+
|
|
312
|
+
* `is_test_path()` + `Node.is_test` + column migration (D5).
|
|
313
|
+
* Orphans query: internal CLASS nodes with no incoming `CALLS` or `EXTENDS` from
|
|
314
|
+
a non-test source. `IMPORTS_SYMBOL` excluded.
|
|
315
|
+
* Surfaced as a CLI command and an MCP tool, following the existing
|
|
316
|
+
`audit_reachability` shape.
|
|
317
|
+
* Measure the `response_model=` precision gap (D4) and decide it here.
|
|
318
|
+
|
|
319
|
+
## Testing
|
|
320
|
+
|
|
321
|
+
Every assertion below must be able to fail. The paired "would fail if" is part of
|
|
322
|
+
the test, not commentary — a self-parsing assertion that merely counts nodes
|
|
323
|
+
passes whether or not the feature works. Counts are calibrated against HEAD and
|
|
324
|
+
must be re-derived from a fresh ingest, never from the stale root `graph.db`.
|
|
325
|
+
|
|
326
|
+
| Test | Would fail if |
|
|
327
|
+
|---|---|
|
|
328
|
+
| Fixture: `VehicleAdapter.search` resolves to `SearchClient.search` | receiver resolution regresses to a placeholder |
|
|
329
|
+
| Fixture: `self.client.search_available_vehicles` resolves to nothing and is dropped | the phantom-method policy (D7) stops applying to `self.` receivers |
|
|
330
|
+
| Fixture: two classes with a same-named attribute produce two distinct targets | the placeholder collision returns |
|
|
331
|
+
| Self-parse: `self.*` placeholder edges drop 139 → ≤ 33 | any of the four `self_types` sources stops being collected |
|
|
332
|
+
| Self-parse: `unresolved_ratio` stays under the 0.30 gate | the `classify_fqn` split miscounts |
|
|
333
|
+
| Self-parse: `REFERENCES` edge count is 583 ± 60 | D3's internal-only filter or D9's collection breaks in either direction |
|
|
334
|
+
| Fixture: a class referenced only as `list[OnlyInGeneric]` is **not** an orphan | D9 regresses to `clean_python_type_string` |
|
|
335
|
+
| Fixture: a class constructed only from `tests/` is reported as an orphan | the `is_test` filter stops being applied |
|
|
336
|
+
| Fixture: a class referenced only by a parameter annotation is **not** an orphan | the annotation edge stops being emitted |
|
|
337
|
+
|
|
338
|
+
The last two are the pair #415 identifies as load-bearing: without the first all
|
|
339
|
+
six of its rows read as live, and without the second every abstract port reads as
|
|
340
|
+
dead. The `list[...]` case is the one this spec's fact-check added — it fails
|
|
341
|
+
against the design as originally written.
|
|
342
|
+
|
|
343
|
+
## Risks
|
|
344
|
+
|
|
345
|
+
* **`classify_fqn` split (PR2).** Changing what counts as INTERNAL touches
|
|
346
|
+
virtual-node creation and every namespace-filtered query, and moves 21 edges
|
|
347
|
+
that D8 does not otherwise address. The `.`-prefixed relative-import case
|
|
348
|
+
shares the condition and must keep its current behavior. Verify each
|
|
349
|
+
`NodeNamespace.INTERNAL` consumer before the split.
|
|
350
|
+
* **Traversal density (PR1).** `impact` and `trace_flow` apply no edge-type
|
|
351
|
+
filter by default, so +583 `REFERENCES` edges will widen their results.
|
|
352
|
+
Arguably correct — an annotation is a real dependency — but it changes existing
|
|
353
|
+
output and should be stated in the PR, not discovered.
|
|
354
|
+
* **Response-schema precision (PR3).** Known and deliberate (D4). PR3 must report
|
|
355
|
+
the measured false-positive rate rather than ship silently.
|
|
356
|
+
* **`self_types` is wrong in two rare shapes — PR2 reads this map, so its author
|
|
357
|
+
must know.** Both were found by an adversarial pass over the extractor's
|
|
358
|
+
heuristics and both measure **zero occurrences** across this repository and
|
|
359
|
+
`owner-api`, which is why they are recorded rather than fixed:
|
|
360
|
+
- An unannotated `self.x = name` in a method other than `__init__` takes its
|
|
361
|
+
type from `__init__`'s parameter of the same name, even when the enclosing
|
|
362
|
+
method annotates it differently — the right answer is sitting in that
|
|
363
|
+
method's own `local_types`. The same lookup is order-dependent: a method
|
|
364
|
+
written above `__init__` sees an empty map. Wrongly *accepted* in the first
|
|
365
|
+
half, wrongly rejected in the second.
|
|
366
|
+
- The constructor heuristic accepts `self.x = HANDLERS[key]()` (the subscript's
|
|
367
|
+
container name is ALL-CAPS and passes the capitalisation test) and
|
|
368
|
+
`self.x = Registry.Instance()` (an uppercase-named classmethod on an imported
|
|
369
|
+
class). It rejects a caseless-script class name (`类`) and a parenthesised
|
|
370
|
+
construction `(Widget())`. The first two write a phantom type; `local_types`
|
|
371
|
+
and `self_types` disagree on the third.
|
|
372
|
+
* **Measurement basis.** Every number here has a five-week-stale twin in the root
|
|
373
|
+
`graph.db`. Re-ingest before re-measuring.
|
|
374
|
+
* **Module-level construction is invisible — [#416](https://github.com/zaebee/codegraph-brain/issues/416).**
|
|
375
|
+
A constructor called at module level emits no `CALLS` edge at all: `_walk`
|
|
376
|
+
dispatches a call node only when there is an enclosing function. A class built
|
|
377
|
+
only in a registry dict, a singleton, or DI wiring therefore has no incoming
|
|
378
|
+
`CALLS`, and PR3's orphan query would report it as dead. On this repository
|
|
379
|
+
`PythonExtractor` and `TypeScriptExtractor` are already in that state. This is
|
|
380
|
+
a **second** precision limit alongside the `response_model=` gap in D4, and
|
|
381
|
+
probably the larger one — it was found while validating PR1, not predicted
|
|
382
|
+
here. PR3 must measure it before the query is trusted.
|