codegraph-brain 0.23.1__tar.gz → 0.23.2__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.23.2/.github/workflows/mcp-registry.yml +81 -0
- codegraph_brain-0.23.2/.release-please-manifest.json +3 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/CHANGELOG.md +7 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/PKG-INFO +1 -1
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/pyproject.toml +1 -1
- codegraph_brain-0.23.2/scripts/mcp_registry_gate.sh +101 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/server.json +2 -2
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/cli.py +53 -30
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/render/graph_json.py +22 -8
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_cli.py +108 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_graph_json.py +15 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/uv.lock +1 -1
- codegraph_brain-0.23.1/.release-please-manifest.json +0 -3
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.claude-plugin/marketplace.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.gitattributes +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/test-count-baseline +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/workflows/autodoc.yml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/workflows/ci.yml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/workflows/guardian.yml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/workflows/pr-title.yml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.github/workflows/release-please.yml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.gitignore +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.pre-commit-config.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/.python-version +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/CLAUDE.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/CONTRIBUTING.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/LICENSE +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/Makefile +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/PRIVACY.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/CURATION.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/calibration.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/246-cross-vendor/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/246-cross-vendor/free-nemotron-quota-cutoff.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/401-evidence/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/401-evidence/pr-399-control-rows.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/401-evidence/pr-399-recording.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/401-evidence/pr-399-treatment-rows.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/407-no-checker-appeal/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-directive-rows.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/experiments/407-no-checker-appeal/pr-399-control-prohibition-rows.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-122.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-140.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-141.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-142.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-143.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-144.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-278.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/pr-313.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/guardian/results.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/cal_dot_com.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/discourse.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/grafana.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/keycloak.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian/sentry.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-judged.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-p3-judged-run1.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-p3-judged-run1.jsonl.corrupted-backup +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-p3-run1.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-p3-run2.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-p3-run3.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-plan.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-repeat-judged.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-repeat-reviews.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/benchmarks/martian-reviews.jsonl +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/data/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/AUDIT.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/CASE_STUDY.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/GUARDIAN_LOCAL_BENCH.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/GUARDIAN_REMOTE_OLLAMA.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/HOW_IT_WORKS.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/ONTOLOGY.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/PATTERNS_AND_TRIADS.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/SELF_PORTRAIT.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/diagrams/pipeline_flow.mermaid +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/architecture/health_badge.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/assets/.gitignore +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/assets/cgis-app-avatar.png +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/assets/cgis-app-avatar.svg +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/assets/generate_avatar.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/examples/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/how-to/AGENT_ONBOARDING.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/how-to/CLI_USAGE.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/how-to/MCP_REFERENCE.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/lab-notes/2026-06-11-chunked-review-negative-result.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/ontology/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/ontology/core.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/ontology/domains.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/ontology/patterns.yaml +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/ontology/tolerances.lock +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/plans/2026-09-09-graph-freshness.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-09-domain-pattern-fingerprint-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-09-pattern-alphabet-motif-basis-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-10-guardian-sprint-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-fastapi-di-edges-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-guardian-chunked-review-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-guardian-chunker-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-mcp-drift-validate-fqn-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-resolver-split-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-11-symbol-import-edges-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-12-drift-empty-domains-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-12-gate-semantics-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-12-init-ontology-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-12-release-please-ci-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-13-suggest-packages-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-06-13-tangle-anti-pattern-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-29-guardian-skeptic-scoring-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-cgis-fractal-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-cgis-fractal-plan.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-chunk-source-filter-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-chunk-source-filter-plan.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-genai-client-close-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-genai-client-close-plan.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-guardian-precision-bench-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-guardian-precision-bench-plan.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-guardian-timeout-retry-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-30-guardian-timeout-retry-plan.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-07-31-finder-bug-class-taxonomy.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-08-01-aura-autoevolution-poc.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-08-11-guardian-code-review-bench.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-08-14-review-fingerprint-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-09-05-annotation-graph-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/2026-09-09-graph-freshness-design.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/BLUEPRINT.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/PRD.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/TDD.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-09-fingerprint-drift.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-10-guardian-structured-findings-bench.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-10-motif-basis-part-b.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-10-unified-pattern-alphabet.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-11-fastapi-di-edges.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-11-guardian-chunked-review.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-11-guardian-chunker.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-11-mcp-drift-validate-fqn.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-11-resolver-split.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-12-drift-empty-domains.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-12-gate-semantics.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-12-init-ontology.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-12-release-please-ci.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-12-symbol-import-edges.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-06-13-suggest-packages.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-07-29-guardian-skeptic-scoring.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-08-14-review-fingerprint.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-09-05-annotation-graph-pr1.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/docs/specs/plans/2026-09-05-annotation-graph-pr2.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/glama.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/main.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/plugin/.claude-plugin/plugin.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/plugin/.mcp.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/plugin/README.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/plugin/skills/cgis/SKILL.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/plugin/skills/ingest/SKILL.md +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/release-please-config.json +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/backfill_calibration_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/backfill_review_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/check_pytest_raises.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/check_test_count.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/colab_bench.sh +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/gen_ideal_graph.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/generate_health.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/generate_mcp_ref.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/generate_schema_docs.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/guardian_bench.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/guardian_calibrate.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/guardian_martian.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/guardian_replay_skeptic.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/guardian_review.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/inject_architecture_graph.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/ollama_visitor.sh +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/probe_closure_gap.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/probe_tier_ladder.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/recordings_from_corpus.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/scripts/skeptic_arms.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/__main__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/api/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/api/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/api/mcp_server.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/coverage.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/freshness.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/generated.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/js_globals.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/models.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/core/paths.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_annotations.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_ast.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_classes.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_functions.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_imports.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_python_types.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/_typescript_bindings.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/base.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/python_extractor.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/registry.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/extractors/typescript_extractor.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/axes.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/bench.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/calibrate.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/chunked.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/chunker.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/collector.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/core.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/diff_index.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/evidence.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/findings.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/github_poster.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/martian.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/metrics.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/prompts.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/base.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/gemini.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/mistral.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/ollama.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/providers/openrouter.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/recording.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/render.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/review_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/runner.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/guardian/skeptic.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/pipeline.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/py.typed +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/analyzer.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/anomaly.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/cohesion.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/health.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/analysis/suggest_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/audit.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/context_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/orphans.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/prompt.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/context/snippet.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/_scc.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/drift.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/drift_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/fractal.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/ontology_init.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/quotient.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/drift/triads.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/engine.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/fqn.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/render/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/render/mermaid.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/query/render/metrics.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/engine.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/indices.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/js_builtins.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/symbols.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/resolver/uplift.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/storage/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/src/cgis/storage/sqlite_store.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/integration/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/__init__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/conftest.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_annotation_calibration.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_architecture.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_drift.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_fractal.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_init_ontology_roundtrip.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_receiver_resolution.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_self_parse.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_self_parse_ts.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/self_parsing/test_suggest.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/.gitkeep +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/conftest.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/guardian_stubs.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/review_path_inventory.txt +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test___main__.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_analyzer.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_annotation_edges.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_audit.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_backfill_calibration_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_backfill_review_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_check_pytest_raises.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_check_test_count.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_cohesion.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_context_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_di_acceptance.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_drift.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_drift_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_extractor_registry.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_fingerprint.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_fqn.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_fractal.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_freshness.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_gen_ideal_graph.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_generate_mcp_ref.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_generated.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_axes.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_bench.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_bench_script.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_calibrate.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_calibrate_script.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_chunked.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_chunker.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_collector.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_core.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_diff_index.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_evidence.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_findings.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_martian.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_martian_script.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_martian_union.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_metrics.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_mistral_sampling.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_ollama_sampling.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_ollama_truncation.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_openrouter.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_poster.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_providers.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_providers_name.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_recording.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_render.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_replay_skeptic.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_review_script.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_runner.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_salvage.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_guardian_skeptic.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_health_scorer.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_import_acceptance.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_inject_architecture_graph.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_mcp_server.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_mcp_tool_schemas.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_mermaid.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_metrics.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_models.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_name_load_positions.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_ontology_compliance.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_ontology_init.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_orphans.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_paths.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_patterns_yaml.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_pipeline.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_pipeline_incremental_symbols.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_prompt.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_python_annotations.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_python_extractor.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_query_coverage.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_quotient.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_recordings_from_corpus.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_resolver.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_resolver_indices.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_resolver_js_builtins.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_resolver_language_scope.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_resolver_symbols.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_review_fingerprint_closure.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_review_fingerprint_contract.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_review_fingerprint_digest.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_review_fingerprint_record.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_self_types.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_skeptic_arms.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_snippet.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_sqlite_store.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_suggest_service.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_temperature_source.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_triads.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_typescript_extractor.py +0 -0
- {codegraph_brain-0.23.1 → codegraph_brain-0.23.2}/tests/unit/test_uplift.py +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Publish to MCP Registry
|
|
2
|
+
|
|
3
|
+
# A separate workflow file, not a job in release-please.yml: PyPI trusted
|
|
4
|
+
# publishing is bound to that file, so nothing here can mint a PyPI upload token
|
|
5
|
+
# whatever the publisher's environment restriction is (#471).
|
|
6
|
+
#
|
|
7
|
+
# Runs after every Release Please run and publishes only a tagged version the
|
|
8
|
+
# registry does not list yet (scripts/mcp_registry_gate.sh), so ordinary pushes
|
|
9
|
+
# to main are no-ops.
|
|
10
|
+
#
|
|
11
|
+
# A failed Release Please run (PyPI publish or relock) skips this workflow: the
|
|
12
|
+
# red run is the signal. Recover with "Re-run failed jobs" there, or dispatch
|
|
13
|
+
# this workflow on main.
|
|
14
|
+
on:
|
|
15
|
+
workflow_run:
|
|
16
|
+
workflows: ["Release Please"]
|
|
17
|
+
types: [completed]
|
|
18
|
+
branches: [main]
|
|
19
|
+
workflow_dispatch:
|
|
20
|
+
|
|
21
|
+
permissions: {}
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: mcp-registry
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
publish:
|
|
29
|
+
name: Publish server.json
|
|
30
|
+
# Dispatch only from main, so an older branch can't publish its own server.json.
|
|
31
|
+
# The repository check is defence in depth: Release Please never runs for forks.
|
|
32
|
+
if: >-
|
|
33
|
+
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') ||
|
|
34
|
+
(github.event.workflow_run.conclusion == 'success' &&
|
|
35
|
+
github.event.workflow_run.head_repository.full_name == github.repository)
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
permissions:
|
|
38
|
+
contents: read
|
|
39
|
+
# OIDC for `mcp-publisher login github-oidc`: no stored registry secret.
|
|
40
|
+
id-token: write
|
|
41
|
+
env:
|
|
42
|
+
# Pinned and checksum-verified: this job holds a registry identity, so it must
|
|
43
|
+
# not run whatever `releases/latest` happens to be. Bump both together; a
|
|
44
|
+
# binary too old for the registry fails login with "invalid audience".
|
|
45
|
+
MCP_PUBLISHER_VERSION: "1.8.1"
|
|
46
|
+
MCP_PUBLISHER_SHA256: a06c9096dcb9727c13555b6be26c7effa707b01f06a4c561ba7a3635443cf2cc
|
|
47
|
+
steps:
|
|
48
|
+
- name: Checkout the released commit
|
|
49
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
50
|
+
with:
|
|
51
|
+
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
|
|
52
|
+
persist-credentials: false
|
|
53
|
+
|
|
54
|
+
- name: Decide whether to publish
|
|
55
|
+
id: gate
|
|
56
|
+
run: bash scripts/mcp_registry_gate.sh check >> "$GITHUB_OUTPUT"
|
|
57
|
+
|
|
58
|
+
- name: Wait for the version on PyPI
|
|
59
|
+
if: steps.gate.outputs.publish == 'true'
|
|
60
|
+
run: bash scripts/mcp_registry_gate.sh wait-pypi
|
|
61
|
+
|
|
62
|
+
- name: Install mcp-publisher
|
|
63
|
+
if: steps.gate.outputs.publish == 'true'
|
|
64
|
+
run: |
|
|
65
|
+
set -euo pipefail
|
|
66
|
+
url="https://github.com/modelcontextprotocol/registry/releases/download/v${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz"
|
|
67
|
+
curl --proto '=https' --tlsv1.2 -fsSL "$url" -o mcp-publisher.tar.gz
|
|
68
|
+
echo "${MCP_PUBLISHER_SHA256} mcp-publisher.tar.gz" | sha256sum --check --strict
|
|
69
|
+
tar -xzf mcp-publisher.tar.gz mcp-publisher
|
|
70
|
+
|
|
71
|
+
- name: Validate server.json
|
|
72
|
+
if: steps.gate.outputs.publish == 'true'
|
|
73
|
+
run: ./mcp-publisher validate
|
|
74
|
+
|
|
75
|
+
- name: Log in with GitHub OIDC
|
|
76
|
+
if: steps.gate.outputs.publish == 'true'
|
|
77
|
+
run: ./mcp-publisher login github-oidc
|
|
78
|
+
|
|
79
|
+
- name: Publish
|
|
80
|
+
if: steps.gate.outputs.publish == 'true'
|
|
81
|
+
run: ./mcp-publisher publish
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.23.2](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.23.1...codegraph-brain-v0.23.2) (2026-09-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **cli:** impact/trace list each neighbour once, JSON each edge once ([#475](https://github.com/zaebee/codegraph-brain/issues/475)) ([9c93b4b](https://github.com/zaebee/codegraph-brain/commit/9c93b4ba5748f99fe2aeb43d698c9d9628e6295a))
|
|
9
|
+
|
|
3
10
|
## [0.23.1](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.23.0...codegraph-brain-v0.23.1) (2026-09-17)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: codegraph-brain
|
|
3
|
-
Version: 0.23.
|
|
3
|
+
Version: 0.23.2
|
|
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
|
|
@@ -7,7 +7,7 @@ packages = ["src/cgis"]
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "codegraph-brain"
|
|
10
|
-
version = "0.23.
|
|
10
|
+
version = "0.23.2"
|
|
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"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Decide whether server.json's version should be published to the MCP Registry,
|
|
3
|
+
# and wait until PyPI can back it (#471).
|
|
4
|
+
#
|
|
5
|
+
# scripts/mcp_registry_gate.sh check → prints publish=true|false (for $GITHUB_OUTPUT)
|
|
6
|
+
# scripts/mcp_registry_gate.sh wait-pypi → blocks until PyPI serves the version
|
|
7
|
+
#
|
|
8
|
+
# `check` is what makes the workflow safe to run after *every* Release Please run:
|
|
9
|
+
# only a tagged release that the registry does not list yet is published, so a
|
|
10
|
+
# docs push to main is a no-op and a re-run never double-publishes.
|
|
11
|
+
#
|
|
12
|
+
# Every lookup fails closed. `publish=false` is printed only on a definite answer
|
|
13
|
+
# (no such tag, version already listed); a network error or an unexpected
|
|
14
|
+
# response exits non-zero, because a silently skipped release is exactly what
|
|
15
|
+
# this automation exists to prevent.
|
|
16
|
+
#
|
|
17
|
+
# `wait-pypi` exists because the registry verifies ownership by fetching
|
|
18
|
+
# pypi.org/pypi/<pkg>/<version>/json and looking for the mcp-name marker, and a
|
|
19
|
+
# fresh upload is not always visible there straight away (0.23.0 and 0.23.1 both
|
|
20
|
+
# failed a `pip install` for a few minutes after the publish job went green).
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
REGISTRY="${MCP_REGISTRY_URL:-https://registry.modelcontextprotocol.io}"
|
|
24
|
+
PYPI="${PYPI_URL:-https://pypi.org}"
|
|
25
|
+
TAG_PREFIX="${TAG_PREFIX:-codegraph-brain-v}"
|
|
26
|
+
WAIT_SECONDS="${WAIT_SECONDS:-600}"
|
|
27
|
+
POLL_SECONDS="${POLL_SECONDS:-15}"
|
|
28
|
+
|
|
29
|
+
fail() {
|
|
30
|
+
echo "::error::$*" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
read_field() {
|
|
35
|
+
local filter="$1" label="$2" value
|
|
36
|
+
value=$(jq -r "${filter} // empty" server.json) || fail "server.json is not valid JSON."
|
|
37
|
+
[[ -n "$value" ]] || fail "server.json has no ${label} (${filter})."
|
|
38
|
+
printf '%s' "$value"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
name=$(read_field .name "server name")
|
|
42
|
+
version=$(read_field .version "version")
|
|
43
|
+
package=$(read_field 'first(.packages[]? | select(.registryType == "pypi") | .identifier)' "PyPI package")
|
|
44
|
+
|
|
45
|
+
check() {
|
|
46
|
+
local tag="refs/tags/${TAG_PREFIX}${version}" rc=0
|
|
47
|
+
git ls-remote --exit-code --tags origin "$tag" >/dev/null || rc=$?
|
|
48
|
+
case "$rc" in
|
|
49
|
+
0) ;;
|
|
50
|
+
2)
|
|
51
|
+
echo "No tag ${TAG_PREFIX}${version}: not a release, nothing to publish." >&2
|
|
52
|
+
echo "publish=false"
|
|
53
|
+
return
|
|
54
|
+
;;
|
|
55
|
+
*) fail "git ls-remote for ${tag} failed (exit ${rc}); cannot tell whether this is a release." ;;
|
|
56
|
+
esac
|
|
57
|
+
|
|
58
|
+
# The status alone is not enough: a moved API also answers 404, and a proxy can
|
|
59
|
+
# answer 200 with nothing. Each answer must also carry the body that means it.
|
|
60
|
+
local encoded body status
|
|
61
|
+
encoded=$(jq -rn --arg n "$name" '$n | @uri')
|
|
62
|
+
body=$(mktemp)
|
|
63
|
+
status=$(curl -sS -o "$body" -w '%{http_code}' \
|
|
64
|
+
"${REGISTRY}/v0/servers/${encoded}/versions/${version}") ||
|
|
65
|
+
fail "Registry lookup for ${name} ${version} failed."
|
|
66
|
+
if [[ "$status" == 200 ]] &&
|
|
67
|
+
jq -e --arg n "$name" --arg v "$version" \
|
|
68
|
+
'.server.name == $n and .server.version == $v' "$body" >/dev/null 2>&1; then
|
|
69
|
+
echo "${name} ${version} is already in the registry." >&2
|
|
70
|
+
echo "publish=false"
|
|
71
|
+
elif [[ "$status" == 404 ]] &&
|
|
72
|
+
jq -e '.detail == "Server not found"' "$body" >/dev/null 2>&1; then
|
|
73
|
+
echo "${name} ${version} is released and not in the registry yet." >&2
|
|
74
|
+
echo "publish=true"
|
|
75
|
+
else
|
|
76
|
+
fail "Unexpected registry answer for ${name} ${version}: HTTP ${status}, $(head -c 200 "$body")"
|
|
77
|
+
fi
|
|
78
|
+
rm -f "$body"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
wait_pypi() {
|
|
82
|
+
local marker="mcp-name: ${name}" deadline=$((SECONDS + WAIT_SECONDS))
|
|
83
|
+
until curl -fsS "${PYPI}/pypi/${package}/${version}/json" 2>/dev/null |
|
|
84
|
+
jq -e --arg m "$marker" '(.info.description // "") | contains($m)' >/dev/null 2>&1; do
|
|
85
|
+
if [[ "$SECONDS" -ge "$deadline" ]]; then
|
|
86
|
+
fail "${package} ${version} with '${marker}' not on PyPI after ${WAIT_SECONDS}s." \
|
|
87
|
+
"Publish manually once it is: mcp-publisher login github && mcp-publisher publish"
|
|
88
|
+
fi
|
|
89
|
+
sleep "$POLL_SECONDS"
|
|
90
|
+
done
|
|
91
|
+
echo "${package} ${version} is on PyPI with the mcp-name marker." >&2
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
case "${1:-}" in
|
|
95
|
+
check) check ;;
|
|
96
|
+
wait-pypi) wait_pypi ;;
|
|
97
|
+
*)
|
|
98
|
+
echo "usage: $0 check|wait-pypi" >&2
|
|
99
|
+
exit 2
|
|
100
|
+
;;
|
|
101
|
+
esac
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"source": "github",
|
|
9
9
|
"id": "1260843154"
|
|
10
10
|
},
|
|
11
|
-
"version": "0.23.
|
|
11
|
+
"version": "0.23.2",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "pypi",
|
|
15
15
|
"registryBaseUrl": "https://pypi.org",
|
|
16
16
|
"identifier": "codegraph-brain",
|
|
17
|
-
"version": "0.23.
|
|
17
|
+
"version": "0.23.2",
|
|
18
18
|
"runtimeHint": "uvx",
|
|
19
19
|
"transport": {
|
|
20
20
|
"type": "stdio"
|
|
@@ -20,6 +20,7 @@ style tags you wrote yourself and pure numbers need no escaping.
|
|
|
20
20
|
|
|
21
21
|
import dataclasses
|
|
22
22
|
import json as _json
|
|
23
|
+
from collections.abc import Callable
|
|
23
24
|
from enum import StrEnum
|
|
24
25
|
from pathlib import Path
|
|
25
26
|
|
|
@@ -318,6 +319,40 @@ def _resolve_cli_fqn(store: SQLiteStore, target: str, kind: str) -> str:
|
|
|
318
319
|
return resolution.resolved
|
|
319
320
|
|
|
320
321
|
|
|
322
|
+
def _tree_neighbours(
|
|
323
|
+
store: SQLiteStore,
|
|
324
|
+
edges: list[Edge],
|
|
325
|
+
neighbour_of: Callable[[Edge], str],
|
|
326
|
+
*,
|
|
327
|
+
allowed_edge_types: frozenset[EdgeType] | None,
|
|
328
|
+
show_external: bool,
|
|
329
|
+
min_confidence: float | None,
|
|
330
|
+
) -> list[tuple[str, Node | None]]:
|
|
331
|
+
"""The neighbours one tree level shows: filtered, in edge order, each id once.
|
|
332
|
+
|
|
333
|
+
One entry per neighbour, not per edge: two call sites are separate edges to the
|
|
334
|
+
same node, and a tree row shows neither line nor edge type to tell them apart
|
|
335
|
+
(#463). A neighbour absent from the store (an unresolved target) comes back with
|
|
336
|
+
``None``, and is dropped with the non-INTERNAL ones when ``show_external`` is off.
|
|
337
|
+
"""
|
|
338
|
+
if allowed_edge_types is not None:
|
|
339
|
+
edges = [e for e in edges if e.type in allowed_edge_types]
|
|
340
|
+
if min_confidence is not None:
|
|
341
|
+
edges = [e for e in edges if e.confidence >= min_confidence]
|
|
342
|
+
ids = list(dict.fromkeys(neighbour_of(e) for e in edges))
|
|
343
|
+
nodes = {n.id: n for n in store.get_nodes(ids)}
|
|
344
|
+
return [
|
|
345
|
+
(node_id, nodes.get(node_id))
|
|
346
|
+
for node_id in ids
|
|
347
|
+
if show_external or _is_internal(nodes.get(node_id))
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def _is_internal(node: Node | None) -> bool:
|
|
352
|
+
"""True for a stored node from the ingested repository."""
|
|
353
|
+
return node is not None and node.namespace == NodeNamespace.INTERNAL
|
|
354
|
+
|
|
355
|
+
|
|
321
356
|
def build_trace_tree(
|
|
322
357
|
store: SQLiteStore,
|
|
323
358
|
current_id: str,
|
|
@@ -333,21 +368,15 @@ def build_trace_tree(
|
|
|
333
368
|
if current_depth >= max_depth:
|
|
334
369
|
return
|
|
335
370
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if not show_external and (
|
|
347
|
-
target_node is None or target_node.namespace != NodeNamespace.INTERNAL
|
|
348
|
-
):
|
|
349
|
-
continue
|
|
350
|
-
|
|
371
|
+
callees = _tree_neighbours(
|
|
372
|
+
store,
|
|
373
|
+
store.get_outgoing_edges(current_id),
|
|
374
|
+
lambda edge: edge.target,
|
|
375
|
+
allowed_edge_types=allowed_edge_types,
|
|
376
|
+
show_external=show_external,
|
|
377
|
+
min_confidence=min_confidence,
|
|
378
|
+
)
|
|
379
|
+
for target_id, target_node in callees:
|
|
351
380
|
if target_node:
|
|
352
381
|
label = (
|
|
353
382
|
f"[bold green]{target_node.type.value}[/bold green] "
|
|
@@ -470,21 +499,15 @@ def build_impact_tree(
|
|
|
470
499
|
if current_depth >= max_depth:
|
|
471
500
|
return
|
|
472
501
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if not show_external and (
|
|
484
|
-
source_node is None or source_node.namespace != NodeNamespace.INTERNAL
|
|
485
|
-
):
|
|
486
|
-
continue
|
|
487
|
-
|
|
502
|
+
callers = _tree_neighbours(
|
|
503
|
+
store,
|
|
504
|
+
store.get_incoming_edges(current_id),
|
|
505
|
+
lambda edge: edge.source,
|
|
506
|
+
allowed_edge_types=allowed_edge_types,
|
|
507
|
+
show_external=show_external,
|
|
508
|
+
min_confidence=min_confidence,
|
|
509
|
+
)
|
|
510
|
+
for source_id, source_node in callers:
|
|
488
511
|
if source_node:
|
|
489
512
|
label = (
|
|
490
513
|
f"[bold magenta]{source_node.type.value}[/bold magenta] "
|
|
@@ -28,6 +28,10 @@ def graph_to_json(
|
|
|
28
28
|
``coverage`` is the traversal's local resolution coverage (#201). A
|
|
29
29
|
structure query follows no calls and passes none, so the key is omitted
|
|
30
30
|
rather than reported as a zero it did not measure.
|
|
31
|
+
|
|
32
|
+
Edges are one per distinct ``(src, type, dst)``, as in the Mermaid view: two
|
|
33
|
+
call sites to the same function are separate graph edges, but without a line
|
|
34
|
+
number the payload would state the same fact twice (#463).
|
|
31
35
|
"""
|
|
32
36
|
payload: dict[str, Any] = {
|
|
33
37
|
"root": root,
|
|
@@ -40,16 +44,26 @@ def graph_to_json(
|
|
|
40
44
|
}
|
|
41
45
|
for node in nodes
|
|
42
46
|
],
|
|
43
|
-
"edges":
|
|
44
|
-
|
|
47
|
+
"edges": _distinct_edges(edges),
|
|
48
|
+
}
|
|
49
|
+
if coverage is not None:
|
|
50
|
+
payload["coverage"] = coverage.model_dump()
|
|
51
|
+
return payload
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _distinct_edges(edges: list[Edge]) -> list[dict[str, Any]]:
|
|
55
|
+
"""Collapse edges sharing ``(src, type, dst)``, first-seen order, highest confidence kept."""
|
|
56
|
+
distinct: dict[tuple[str, str, str], dict[str, Any]] = {}
|
|
57
|
+
for edge in edges:
|
|
58
|
+
key = (edge.source, edge.type.value, edge.target)
|
|
59
|
+
seen = distinct.get(key)
|
|
60
|
+
if seen is None:
|
|
61
|
+
distinct[key] = {
|
|
45
62
|
"src": edge.source,
|
|
46
63
|
"dst": edge.target,
|
|
47
64
|
"type": edge.type.value,
|
|
48
65
|
"confidence": edge.confidence,
|
|
49
66
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if coverage is not None:
|
|
54
|
-
payload["coverage"] = coverage.model_dump()
|
|
55
|
-
return payload
|
|
67
|
+
elif edge.confidence > seen["confidence"]:
|
|
68
|
+
seen["confidence"] = edge.confidence
|
|
69
|
+
return list(distinct.values())
|
|
@@ -162,6 +162,101 @@ def test_trace_renders_callees_in_tree(tmp_path: Path) -> None:
|
|
|
162
162
|
assert "callee" in result.output
|
|
163
163
|
|
|
164
164
|
|
|
165
|
+
_REPEATED_CALLS = """\
|
|
166
|
+
def leaf(): pass
|
|
167
|
+
|
|
168
|
+
def target():
|
|
169
|
+
leaf()
|
|
170
|
+
leaf()
|
|
171
|
+
|
|
172
|
+
def caller():
|
|
173
|
+
target()
|
|
174
|
+
target()
|
|
175
|
+
|
|
176
|
+
def top():
|
|
177
|
+
caller()
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _repeated_calls_db(tmp_path: Path) -> str:
|
|
182
|
+
"""caller calls target from two lines, target calls leaf from two lines (#463)."""
|
|
183
|
+
(tmp_path / "funcs.py").write_text(_REPEATED_CALLS, encoding="utf-8")
|
|
184
|
+
db_file = tmp_path / "graph.db"
|
|
185
|
+
result = runner.invoke(app, ["ingest", str(tmp_path), "--output", str(db_file)])
|
|
186
|
+
assert result.exit_code == 0
|
|
187
|
+
return str(db_file)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def test_impact_tree_lists_each_caller_once(tmp_path: Path) -> None:
|
|
191
|
+
"""Two call sites are one caller: one row, and its own callers expanded once (#463)."""
|
|
192
|
+
db = _repeated_calls_db(tmp_path)
|
|
193
|
+
result = runner.invoke(
|
|
194
|
+
app, ["impact", "funcs.target", "--db", db, "--depth", "2"], env={"COLUMNS": "200"}
|
|
195
|
+
)
|
|
196
|
+
assert result.exit_code == 0
|
|
197
|
+
assert result.output.count("FUNCTION funcs.caller ") == 1
|
|
198
|
+
assert result.output.count("FUNCTION funcs.top ") == 1
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_trace_tree_lists_each_callee_once(tmp_path: Path) -> None:
|
|
202
|
+
"""Two call sites are one callee: one row, and its own callees expanded once (#463)."""
|
|
203
|
+
db = _repeated_calls_db(tmp_path)
|
|
204
|
+
result = runner.invoke(
|
|
205
|
+
app, ["trace", "funcs.caller", "--db", db, "--depth", "2"], env={"COLUMNS": "200"}
|
|
206
|
+
)
|
|
207
|
+
assert result.exit_code == 0
|
|
208
|
+
assert result.output.count("FUNCTION funcs.target ") == 1
|
|
209
|
+
assert result.output.count("FUNCTION funcs.leaf ") == 1
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
_DIAMOND = """\
|
|
213
|
+
def leaf(): pass
|
|
214
|
+
|
|
215
|
+
def a():
|
|
216
|
+
leaf()
|
|
217
|
+
|
|
218
|
+
def b():
|
|
219
|
+
leaf()
|
|
220
|
+
|
|
221
|
+
def top():
|
|
222
|
+
a()
|
|
223
|
+
b()
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_trees_keep_a_node_reached_through_two_parents(tmp_path: Path) -> None:
|
|
228
|
+
"""Dedup is per parent: leaf under both a and b, top above both (#463 review).
|
|
229
|
+
|
|
230
|
+
A dedup set shared across the recursion would print leaf once and silently drop
|
|
231
|
+
the second path — on cgis's own graph that loses 73 of 133 trace rows.
|
|
232
|
+
"""
|
|
233
|
+
(tmp_path / "funcs.py").write_text(_DIAMOND, encoding="utf-8")
|
|
234
|
+
db = str(tmp_path / "graph.db")
|
|
235
|
+
assert runner.invoke(app, ["ingest", str(tmp_path), "--output", db]).exit_code == 0
|
|
236
|
+
env = {"COLUMNS": "200"}
|
|
237
|
+
|
|
238
|
+
trace = runner.invoke(app, ["trace", "funcs.top", "--db", db, "--depth", "2"], env=env)
|
|
239
|
+
assert trace.exit_code == 0
|
|
240
|
+
assert trace.output.count("FUNCTION funcs.leaf ") == 2
|
|
241
|
+
|
|
242
|
+
impact = runner.invoke(app, ["impact", "funcs.leaf", "--db", db, "--depth", "2"], env=env)
|
|
243
|
+
assert impact.exit_code == 0
|
|
244
|
+
assert impact.output.count("FUNCTION funcs.top ") == 2
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@pytest.mark.parametrize(
|
|
248
|
+
("command", "root"), [("impact", "funcs.target"), ("trace", "funcs.caller")]
|
|
249
|
+
)
|
|
250
|
+
def test_json_traversal_emits_each_edge_once(tmp_path: Path, command: str, root: str) -> None:
|
|
251
|
+
"""Repeated call sites collapse to one (src, type, dst) edge, as in mermaid (#463)."""
|
|
252
|
+
db = _repeated_calls_db(tmp_path)
|
|
253
|
+
result = runner.invoke(app, [command, root, "--db", db, "--depth", "2", "--format", "json"])
|
|
254
|
+
assert result.exit_code == 0
|
|
255
|
+
edges = [(e["src"], e["type"], e["dst"]) for e in json.loads(result.stdout)["edges"]]
|
|
256
|
+
assert len(edges) == len(set(edges))
|
|
257
|
+
assert ("funcs.caller", "CALLS", "funcs.target") in edges
|
|
258
|
+
|
|
259
|
+
|
|
165
260
|
def test_trace_shows_unresolved_external_call(tmp_path: Path) -> None:
|
|
166
261
|
"""Calls to built-ins not in the graph are labelled as Unresolved."""
|
|
167
262
|
(tmp_path / "mod.py").write_text("def greet(): print('hi')\n", encoding="utf-8")
|
|
@@ -185,6 +280,19 @@ def test_trace_shows_unresolved_external_call(tmp_path: Path) -> None:
|
|
|
185
280
|
assert "print" in result.output
|
|
186
281
|
|
|
187
282
|
|
|
283
|
+
def test_trace_hides_external_calls_by_default(tmp_path: Path) -> None:
|
|
284
|
+
"""Without --show-external the stdlib callee is filtered out of the tree."""
|
|
285
|
+
(tmp_path / "mod.py").write_text("def greet(): print('hi')\n", encoding="utf-8")
|
|
286
|
+
db_file = tmp_path / "graph.db"
|
|
287
|
+
runner.invoke(app, ["ingest", str(tmp_path), "--output", str(db_file)])
|
|
288
|
+
|
|
289
|
+
result = runner.invoke(app, ["trace", "mod.greet", "--db", str(db_file)])
|
|
290
|
+
|
|
291
|
+
assert result.exit_code == 0
|
|
292
|
+
assert "Tracing execution flow" in result.output
|
|
293
|
+
assert "print" not in result.output
|
|
294
|
+
|
|
295
|
+
|
|
188
296
|
def test_trace_min_confidence_hides_low_conf_calls(tmp_path: Path) -> None:
|
|
189
297
|
"""--min-confidence hides low-confidence (unresolved/raw_call) edges from the tree (#112)."""
|
|
190
298
|
(tmp_path / "mod.py").write_text("def greet(): print('hi')\n", encoding="utf-8")
|
|
@@ -89,3 +89,18 @@ def test_graph_to_json_omits_coverage_when_none() -> None:
|
|
|
89
89
|
payload = graph_to_json("pkg.a", [_make_node("pkg.a")], [])
|
|
90
90
|
|
|
91
91
|
assert "coverage" not in payload
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_graph_to_json_collapses_edges_with_the_same_endpoints_and_type() -> None:
|
|
95
|
+
"""Two call sites are indistinguishable in the payload — emit one edge, highest confidence."""
|
|
96
|
+
nodes = [_make_node("pkg.a"), _make_node("pkg.b")]
|
|
97
|
+
first = _make_edge("pkg.a", "pkg.b", confidence=0.4)
|
|
98
|
+
second = first.model_copy(update={"id": "pkg.a->pkg.b@2", "confidence": 0.9})
|
|
99
|
+
other_type = _make_edge("pkg.a", "pkg.b", EdgeType.REFERENCES).model_copy(
|
|
100
|
+
update={"id": "pkg.a->pkg.b@ref"}
|
|
101
|
+
)
|
|
102
|
+
payload = graph_to_json("pkg.a", nodes, [first, second, other_type])
|
|
103
|
+
assert payload["edges"] == [
|
|
104
|
+
{"src": "pkg.a", "dst": "pkg.b", "type": "CALLS", "confidence": 0.9},
|
|
105
|
+
{"src": "pkg.a", "dst": "pkg.b", "type": "REFERENCES", "confidence": 1.0},
|
|
106
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|