codegraph-brain 0.7.2__tar.gz → 0.7.4__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.7.2 → codegraph_brain-0.7.4}/.github/workflows/autodoc.yml +7 -7
- codegraph_brain-0.7.4/.github/workflows/ci.yml +46 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/.github/workflows/guardian.yml +4 -4
- codegraph_brain-0.7.4/.github/workflows/pr-title.yml +51 -0
- codegraph_brain-0.7.4/.github/workflows/release-please.yml +147 -0
- codegraph_brain-0.7.4/.release-please-manifest.json +3 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/CHANGELOG.md +20 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/PKG-INFO +1 -1
- codegraph_brain-0.7.4/docs/assets/.gitignore +1 -0
- codegraph_brain-0.7.4/docs/assets/cgis-app-avatar.png +0 -0
- codegraph_brain-0.7.4/docs/assets/cgis-app-avatar.svg +1 -0
- codegraph_brain-0.7.4/docs/assets/generate_avatar.py +123 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/how-to/MCP_REFERENCE.md +6 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/pyproject.toml +1 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/api/mcp_server.py +73 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/engine.py +1 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/indices.py +41 -22
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_cohesion.py +3 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_chunker.py +3 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_mcp_server.py +151 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_mermaid.py +4 -2
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_ontology_init.py +3 -1
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_resolver_indices.py +57 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/uv.lock +2 -2
- codegraph_brain-0.7.2/.github/workflows/ci.yml +0 -38
- codegraph_brain-0.7.2/.github/workflows/release-please.yml +0 -76
- codegraph_brain-0.7.2/.release-please-manifest.json +0 -3
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/.claude-plugin/marketplace.json +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/.gitignore +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/.pre-commit-config.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/.python-version +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/CLAUDE.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/CONTRIBUTING.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/LICENSE +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/Makefile +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/PRIVACY.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/README.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/CURATION.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-122.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-140.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-141.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-142.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-143.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-144.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/pr-278.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/benchmarks/guardian/results.jsonl +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/data/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/AUDIT.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/CASE_STUDY.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/HOW_IT_WORKS.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/ONTOLOGY.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/PATTERNS_AND_TRIADS.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/SELF_PORTRAIT.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/diagrams/pipeline_flow.mermaid +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/architecture/health_badge.json +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/examples/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/how-to/AGENT_ONBOARDING.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/how-to/CLI_USAGE.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/lab-notes/2026-06-11-chunked-review-negative-result.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/ontology/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/ontology/core.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/ontology/domains.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/ontology/patterns.yaml +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/ontology/tolerances.lock +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-09-domain-pattern-fingerprint-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-09-pattern-alphabet-motif-basis-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-10-guardian-sprint-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-fastapi-di-edges-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-guardian-chunked-review-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-guardian-chunker-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-mcp-drift-validate-fqn-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-resolver-split-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-11-symbol-import-edges-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-12-drift-empty-domains-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-12-gate-semantics-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-12-init-ontology-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-12-release-please-ci-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-13-suggest-packages-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-06-13-tangle-anti-pattern-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-29-guardian-skeptic-scoring-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-cgis-fractal-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-cgis-fractal-plan.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-chunk-source-filter-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-chunk-source-filter-plan.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-genai-client-close-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-genai-client-close-plan.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-guardian-precision-bench-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-guardian-precision-bench-plan.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-guardian-timeout-retry-design.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-30-guardian-timeout-retry-plan.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/2026-07-31-finder-bug-class-taxonomy.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/BLUEPRINT.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/PRD.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/TDD.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-09-fingerprint-drift.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-10-guardian-structured-findings-bench.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-10-motif-basis-part-b.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-10-unified-pattern-alphabet.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-11-fastapi-di-edges.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-11-guardian-chunked-review.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-11-guardian-chunker.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-11-mcp-drift-validate-fqn.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-11-resolver-split.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-12-drift-empty-domains.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-12-gate-semantics.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-12-init-ontology.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-12-release-please-ci.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-12-symbol-import-edges.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-06-13-suggest-packages.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/docs/specs/plans/2026-07-29-guardian-skeptic-scoring.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/main.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/plugin/.claude-plugin/plugin.json +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/plugin/.mcp.json +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/plugin/README.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/plugin/skills/cgis/SKILL.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/plugin/skills/ingest/SKILL.md +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/release-please-config.json +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/gen_ideal_graph.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/generate_health.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/generate_mcp_ref.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/generate_schema_docs.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/guardian_bench.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/guardian_review.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/inject_readme_graph.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/probe_closure_gap.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/scripts/probe_tier_ladder.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/__main__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/api/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/api/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/cli.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/core/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/core/models.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/_python_ast.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/_python_classes.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/_python_functions.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/_python_imports.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/_python_types.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/base.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/python_extractor.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/extractors/typescript_extractor.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/bench.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/chunked.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/chunker.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/collector.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/core.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/diff_index.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/findings.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/github_poster.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/metrics.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/prompts.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/providers/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/providers/base.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/providers/gemini.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/providers/mistral.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/providers/ollama.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/recording.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/render.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/runner.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/guardian/skeptic.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/pipeline.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/py.typed +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/analyzer.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/anomaly.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/cohesion.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/health.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/analysis/suggest_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/context/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/context/audit.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/context/context_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/context/prompt.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/context/snippet.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/_scc.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/drift.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/drift_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/fingerprint.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/fractal.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/ontology_init.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/quotient.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/drift/triads.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/engine.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/fqn.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/render/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/render/graph_json.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/render/mermaid.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/query/render/metrics.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/symbols.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/resolver/uplift.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/storage/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/src/cgis/storage/sqlite_store.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/integration/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/__init__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/conftest.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_architecture.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_drift.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_fractal.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_init_ontology_roundtrip.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_self_parse.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_self_parse_ts.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/self_parsing/test_suggest.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/.gitkeep +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/conftest.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/guardian_stubs.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test___main__.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_analyzer.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_audit.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_cli.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_context_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_di_acceptance.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_drift.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_drift_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_fingerprint.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_fqn.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_fractal.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_gen_ideal_graph.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_generate_mcp_ref.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_graph_json.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_bench.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_chunked.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_collector.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_core.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_diff_index.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_findings.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_metrics.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_poster.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_providers.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_recording.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_render.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_runner.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_guardian_skeptic.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_health_scorer.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_import_acceptance.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_metrics.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_models.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_ontology_compliance.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_patterns_yaml.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_pipeline.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_prompt.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_python_extractor.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_quotient.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_resolver.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_resolver_symbols.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_snippet.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_sqlite_store.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_suggest_service.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_triads.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_typescript_extractor.py +0 -0
- {codegraph_brain-0.7.2 → codegraph_brain-0.7.4}/tests/unit/test_uplift.py +0 -0
|
@@ -28,15 +28,15 @@ jobs:
|
|
|
28
28
|
enable-cache: true
|
|
29
29
|
|
|
30
30
|
- name: Install CGIS
|
|
31
|
-
run: uv sync
|
|
31
|
+
run: uv sync --frozen
|
|
32
32
|
|
|
33
33
|
- name: Self-ingest core engine
|
|
34
|
-
run: uv run cgis ingest ./src --output /tmp/self_graph.db
|
|
34
|
+
run: uv run --frozen cgis ingest ./src --output /tmp/self_graph.db
|
|
35
35
|
|
|
36
36
|
- name: Generate pipeline flow diagram
|
|
37
37
|
run: |
|
|
38
38
|
mkdir -p docs/architecture/diagrams
|
|
39
|
-
uv run cgis trace "cgis.pipeline.IngestionPipeline.run" \
|
|
39
|
+
uv run --frozen cgis trace "cgis.pipeline.IngestionPipeline.run" \
|
|
40
40
|
--db /tmp/self_graph.db \
|
|
41
41
|
--depth 1 \
|
|
42
42
|
--format mermaid \
|
|
@@ -44,21 +44,21 @@ jobs:
|
|
|
44
44
|
> docs/architecture/diagrams/pipeline_flow.mermaid
|
|
45
45
|
|
|
46
46
|
- name: Compute graph health badge
|
|
47
|
-
run: uv run python scripts/generate_health.py --db /tmp/self_graph.db
|
|
47
|
+
run: uv run --frozen python scripts/generate_health.py --db /tmp/self_graph.db
|
|
48
48
|
|
|
49
49
|
- name: Inject graph into README.md
|
|
50
50
|
run: |
|
|
51
|
-
uv run python scripts/inject_readme_graph.py \
|
|
51
|
+
uv run --frozen python scripts/inject_readme_graph.py \
|
|
52
52
|
--db /tmp/self_graph.db \
|
|
53
53
|
--fqn "cgis.pipeline.IngestionPipeline.run" \
|
|
54
54
|
--depth 1 \
|
|
55
55
|
--path-prefix "src/"
|
|
56
56
|
|
|
57
57
|
- name: Generate MCP reference manual
|
|
58
|
-
run: uv run python scripts/generate_mcp_ref.py
|
|
58
|
+
run: uv run --frozen python scripts/generate_mcp_ref.py
|
|
59
59
|
|
|
60
60
|
- name: Sync schema docs from source
|
|
61
|
-
run: uv run python scripts/generate_schema_docs.py
|
|
61
|
+
run: uv run --frozen python scripts/generate_schema_docs.py
|
|
62
62
|
|
|
63
63
|
- name: Open PR with generated docs
|
|
64
64
|
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Continuous Integration
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, dev, "feat/**", "fix/**", "docs/**" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
python-ci:
|
|
11
|
+
name: Python Verification
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout Code
|
|
15
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
16
|
+
|
|
17
|
+
- name: Setup uv
|
|
18
|
+
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
|
|
22
|
+
- name: Lockfile in step with pyproject
|
|
23
|
+
# This is the only step that validates the lockfile. `--frozen` below stops
|
|
24
|
+
# uv rewriting uv.lock, but it does not check that the lock is current —
|
|
25
|
+
# that is `--locked`. Keeping the check explicit gives a clearer failure
|
|
26
|
+
# than a sync error, and it still runs first so an unfrozen uv could never
|
|
27
|
+
# repair the lock ahead of it.
|
|
28
|
+
run: uv lock --check
|
|
29
|
+
|
|
30
|
+
- name: Install Dependencies
|
|
31
|
+
run: uv sync --frozen --group dev
|
|
32
|
+
|
|
33
|
+
- name: Ruff Format Check
|
|
34
|
+
run: uv run --frozen ruff format --check .
|
|
35
|
+
|
|
36
|
+
- name: Ruff Lint
|
|
37
|
+
run: uv run --frozen ruff check .
|
|
38
|
+
|
|
39
|
+
- name: Interrogate (≥90% docstring coverage)
|
|
40
|
+
run: uv run --frozen interrogate -v --fail-under 90 src/cgis
|
|
41
|
+
|
|
42
|
+
- name: Mypy (strict)
|
|
43
|
+
run: uv run --frozen mypy src
|
|
44
|
+
|
|
45
|
+
- name: Pytest
|
|
46
|
+
run: uv run --frozen pytest --cov=cgis --cov-report=term-missing
|
|
@@ -67,10 +67,10 @@ jobs:
|
|
|
67
67
|
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
|
|
68
68
|
|
|
69
69
|
- name: Install dependencies
|
|
70
|
-
run: uv sync --extra guardian
|
|
70
|
+
run: uv sync --frozen --extra guardian
|
|
71
71
|
|
|
72
72
|
- name: Build code graph
|
|
73
|
-
run: uv run cgis ingest ./src --output graph.db
|
|
73
|
+
run: uv run --frozen cgis ingest ./src --output graph.db
|
|
74
74
|
|
|
75
75
|
- name: Restore metrics from data branch
|
|
76
76
|
run: |
|
|
@@ -91,7 +91,7 @@ jobs:
|
|
|
91
91
|
GUARDIAN_SKEPTIC: ${{ vars.GUARDIAN_SKEPTIC }}
|
|
92
92
|
GUARDIAN_SKEPTIC_MODEL: ${{ vars.GUARDIAN_SKEPTIC_MODEL }}
|
|
93
93
|
run: |
|
|
94
|
-
uv run python scripts/guardian_review.py \
|
|
94
|
+
uv run --frozen python scripts/guardian_review.py \
|
|
95
95
|
--output guardian_report.md \
|
|
96
96
|
--db graph.db \
|
|
97
97
|
--pr "$PR_NUMBER" \
|
|
@@ -219,7 +219,7 @@ jobs:
|
|
|
219
219
|
git show origin/data/guardian-metrics:guardian_metrics.jsonl \
|
|
220
220
|
> guardian_metrics.jsonl
|
|
221
221
|
|
|
222
|
-
uv run cgis guardian-rate "$PR_NUMBER" "$APPLIED" \
|
|
222
|
+
uv run --frozen cgis guardian-rate "$PR_NUMBER" "$APPLIED" \
|
|
223
223
|
--metrics guardian_metrics.jsonl
|
|
224
224
|
|
|
225
225
|
if git ls-remote --exit-code origin data/guardian-metrics > /dev/null 2>&1; then
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: PR Title
|
|
2
|
+
|
|
3
|
+
# The repository squash-merges, so the PR title becomes the commit subject that
|
|
4
|
+
# release-please parses. A title it does not recognise is dropped from the
|
|
5
|
+
# changelog silently — no warning, no failure. That has now happened twice:
|
|
6
|
+
# #297 ("drift trust batch: …", a descriptive title) and #313
|
|
7
|
+
# ("security(mcp): …", a type that does not exist), the second of which would
|
|
8
|
+
# have shipped a security fix invisibly.
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [ main ]
|
|
12
|
+
# `edited` matters: without it, fixing a rejected title would not re-run
|
|
13
|
+
# the check. Kept in a separate workflow from ci.yml so retitling does not
|
|
14
|
+
# replay the whole test suite.
|
|
15
|
+
types: [ opened, edited, reopened, synchronize ]
|
|
16
|
+
|
|
17
|
+
permissions: {}
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
conventional-title:
|
|
21
|
+
name: Conventional commit title
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check the title release-please will parse
|
|
25
|
+
env:
|
|
26
|
+
# Never interpolate an untrusted title straight into `run:` — it is
|
|
27
|
+
# attacker-controlled text. Through the environment it is just data.
|
|
28
|
+
PR_TITLE: ${{ github.event.pull_request.title }}
|
|
29
|
+
run: |
|
|
30
|
+
set -euo pipefail
|
|
31
|
+
# Types release-please understands. Anything else is dropped from the
|
|
32
|
+
# changelog without complaint, which is the failure being prevented.
|
|
33
|
+
TYPES='feat|fix|docs|chore|style|refactor|perf|test|build|ci|revert'
|
|
34
|
+
if printf '%s' "$PR_TITLE" | grep -qE "^($TYPES)(\([a-z0-9._/-]+\))?!?: .+"; then
|
|
35
|
+
printf '::notice::PR title is a conventional commit.\n'
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
printf '::error::PR title is not a conventional commit: %s\n' "$PR_TITLE"
|
|
39
|
+
cat >&2 <<'MSG'
|
|
40
|
+
|
|
41
|
+
This repository squash-merges, so the PR title becomes the commit
|
|
42
|
+
subject release-please reads. An unrecognised type is dropped from the
|
|
43
|
+
CHANGELOG silently.
|
|
44
|
+
|
|
45
|
+
Expected: <type>(<optional scope>): <description>
|
|
46
|
+
Types: feat fix docs chore style refactor perf test build ci revert
|
|
47
|
+
|
|
48
|
+
Note there is no `security` type — use `fix` with a scope:
|
|
49
|
+
fix(mcp): validate db_path before cgis_ingest creates a database
|
|
50
|
+
MSG
|
|
51
|
+
exit 1
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release-please:
|
|
10
|
+
name: Release Please
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
# Scoped to this job only: the publish job below must never inherit
|
|
14
|
+
# write access to the repository.
|
|
15
|
+
contents: write
|
|
16
|
+
pull-requests: write
|
|
17
|
+
outputs:
|
|
18
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
19
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
20
|
+
release_pr: ${{ steps.release.outputs.pr }}
|
|
21
|
+
steps:
|
|
22
|
+
- name: Mint a GitHub App token
|
|
23
|
+
id: app-token
|
|
24
|
+
# A GITHUB_TOKEN-authored PR leaves its checks parked in
|
|
25
|
+
# `action_required` forever, so release-please needs an identity of its
|
|
26
|
+
# own. App tokens beat a PAT: one hour of life, auto-rotated, scoped to
|
|
27
|
+
# this repo, and not tied to anyone's personal account.
|
|
28
|
+
# continue-on-error: an unconfigured App must degrade, not break the release.
|
|
29
|
+
continue-on-error: true
|
|
30
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
31
|
+
with:
|
|
32
|
+
# Accepted from either store: the App ID is not sensitive, so a repo
|
|
33
|
+
# variable is conventional, but it is commonly filed as a secret.
|
|
34
|
+
app-id: ${{ vars.CGIS_APP_ID || secrets.CGIS_APP_ID }}
|
|
35
|
+
private-key: ${{ secrets.CGIS_APP_PRIVATE_KEY }}
|
|
36
|
+
|
|
37
|
+
- name: Run release-please
|
|
38
|
+
id: release
|
|
39
|
+
uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
|
|
40
|
+
with:
|
|
41
|
+
# Falls back to GITHUB_TOKEN when the App is not configured — the
|
|
42
|
+
# release still opens, its checks just need a manual nudge.
|
|
43
|
+
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
44
|
+
config-file: release-please-config.json
|
|
45
|
+
manifest-file: .release-please-manifest.json
|
|
46
|
+
|
|
47
|
+
relock:
|
|
48
|
+
name: Re-lock the release PR
|
|
49
|
+
needs: release-please
|
|
50
|
+
# Only when release-please actually has an open release PR to amend.
|
|
51
|
+
if: needs.release-please.outputs.release_pr != ''
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
permissions:
|
|
54
|
+
# Narrower than the release job: this one only pushes a lockfile.
|
|
55
|
+
contents: write
|
|
56
|
+
steps:
|
|
57
|
+
- name: Mint a GitHub App token
|
|
58
|
+
id: app-token
|
|
59
|
+
# A GITHUB_TOKEN-authored PR leaves its checks parked in
|
|
60
|
+
# `action_required` forever, so release-please needs an identity of its
|
|
61
|
+
# own. App tokens beat a PAT: one hour of life, auto-rotated, scoped to
|
|
62
|
+
# this repo, and not tied to anyone's personal account.
|
|
63
|
+
# continue-on-error: an unconfigured App must degrade, not break the release.
|
|
64
|
+
continue-on-error: true
|
|
65
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
66
|
+
with:
|
|
67
|
+
# Accepted from either store: the App ID is not sensitive, so a repo
|
|
68
|
+
# variable is conventional, but it is commonly filed as a secret.
|
|
69
|
+
app-id: ${{ vars.CGIS_APP_ID || secrets.CGIS_APP_ID }}
|
|
70
|
+
private-key: ${{ secrets.CGIS_APP_PRIVATE_KEY }}
|
|
71
|
+
|
|
72
|
+
- name: Checkout the release branch
|
|
73
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
74
|
+
with:
|
|
75
|
+
ref: ${{ fromJSON(needs.release-please.outputs.release_pr).headBranchName }}
|
|
76
|
+
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
77
|
+
|
|
78
|
+
- name: Setup uv
|
|
79
|
+
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
|
|
80
|
+
with:
|
|
81
|
+
enable-cache: true
|
|
82
|
+
|
|
83
|
+
- name: Re-lock and push if the version moved
|
|
84
|
+
run: |
|
|
85
|
+
set -euo pipefail
|
|
86
|
+
# release-please bumps pyproject.toml but never re-resolves uv.lock, so
|
|
87
|
+
# the lockfile's own version entry falls a release behind and the CI
|
|
88
|
+
# `uv lock --check` gate fails on every release PR (#303).
|
|
89
|
+
uv lock
|
|
90
|
+
if git diff --quiet -- uv.lock; then
|
|
91
|
+
echo "uv.lock already in step with pyproject.toml"
|
|
92
|
+
exit 0
|
|
93
|
+
fi
|
|
94
|
+
git config user.name "github-actions[bot]"
|
|
95
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
96
|
+
git add uv.lock
|
|
97
|
+
git commit -m "chore: re-lock uv.lock for the release"
|
|
98
|
+
git push
|
|
99
|
+
|
|
100
|
+
publish:
|
|
101
|
+
name: Publish to PyPI
|
|
102
|
+
needs: release-please
|
|
103
|
+
if: needs.release-please.outputs.release_created == 'true'
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
environment:
|
|
106
|
+
name: pypi
|
|
107
|
+
url: https://pypi.org/p/codegraph-brain
|
|
108
|
+
permissions:
|
|
109
|
+
# Mints the short-lived OIDC token PyPI exchanges for an upload token.
|
|
110
|
+
# This is the whole point of trusted publishing: no API token in secrets.
|
|
111
|
+
id-token: write
|
|
112
|
+
# Lets the publish action attach PEP 740 provenance attestations.
|
|
113
|
+
attestations: write
|
|
114
|
+
contents: read
|
|
115
|
+
steps:
|
|
116
|
+
- name: Checkout Code
|
|
117
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
118
|
+
with:
|
|
119
|
+
ref: ${{ needs.release-please.outputs.tag_name }}
|
|
120
|
+
|
|
121
|
+
- name: Setup uv
|
|
122
|
+
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
|
|
123
|
+
with:
|
|
124
|
+
enable-cache: true
|
|
125
|
+
|
|
126
|
+
- name: Build sdist and wheel
|
|
127
|
+
run: uv build
|
|
128
|
+
|
|
129
|
+
- name: Verify metadata
|
|
130
|
+
# Pinned and wheel-only: this job holds publish rights, so the tooling
|
|
131
|
+
# it pulls in must not be a floating version that can run setup scripts.
|
|
132
|
+
run: uvx --no-build --from "twine==7.0.0" twine check dist/*
|
|
133
|
+
|
|
134
|
+
- name: Verify version matches the tag
|
|
135
|
+
env:
|
|
136
|
+
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
|
|
137
|
+
run: |
|
|
138
|
+
set -euo pipefail
|
|
139
|
+
built=$(ls dist/*.whl | sed -E 's/.*-([0-9][^-]*)-py3.*/\1/')
|
|
140
|
+
echo "tag=$TAG_NAME built=$built"
|
|
141
|
+
case "$TAG_NAME" in
|
|
142
|
+
*"$built") ;;
|
|
143
|
+
*) echo "::error::tag $TAG_NAME does not match built version $built"; exit 1 ;;
|
|
144
|
+
esac
|
|
145
|
+
|
|
146
|
+
- name: Publish
|
|
147
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.4](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.7.3...codegraph-brain-v0.7.4) (2026-08-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **mcp:** validate db_path before cgis_ingest creates a database ([#313](https://github.com/zaebee/codegraph-brain/issues/313)) ([2c5499b](https://github.com/zaebee/codegraph-brain/commit/2c5499b8fb7f0d40a03144417c3210900371d499)), closes [#312](https://github.com/zaebee/codegraph-brain/issues/312)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
* auto-sync architecture graph and MCP reference ([#314](https://github.com/zaebee/codegraph-brain/issues/314)) ([7d5b666](https://github.com/zaebee/codegraph-brain/commit/7d5b66669f9dfa40e2fc86dd59a4baf492a9342e))
|
|
14
|
+
|
|
15
|
+
## [0.7.3](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.7.2...codegraph-brain-v0.7.3) (2026-07-31)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **assets:** drop the argv-driven output path from the avatar generator ([#308](https://github.com/zaebee/codegraph-brain/issues/308)) ([d118074](https://github.com/zaebee/codegraph-brain/commit/d118074a6b2137f789b4978f870f5496ee1135b5))
|
|
21
|
+
* **ci:** read the App ID from a secret as well as a variable ([#306](https://github.com/zaebee/codegraph-brain/issues/306)) ([90513bc](https://github.com/zaebee/codegraph-brain/commit/90513bc3f588241848fd7404f9be5b6479a72293))
|
|
22
|
+
|
|
3
23
|
## [0.7.2](https://github.com/zaebee/codegraph-brain/compare/codegraph-brain-v0.7.1...codegraph-brain-v0.7.2) (2026-07-31)
|
|
4
24
|
|
|
5
25
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraph-brain
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Semantic code graph for AI agents — deterministic FQN resolution, impact analysis and architectural drift gates, exposed over MCP.
|
|
5
5
|
Project-URL: Homepage, https://github.com/zaebee/codegraph-brain
|
|
6
6
|
Project-URL: Repository, https://github.com/zaebee/codegraph-brain
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
_variants/
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200"><rect width="200" height="200" rx="44" fill="#0d1526"/><line x1="113.2" y1="55.7" x2="142.8" y2="86.3" stroke="#64748b" stroke-width="8" stroke-linecap="round"/><line x1="142.8" y1="113.7" x2="113.2" y2="144.3" stroke="#64748b" stroke-width="8" stroke-linecap="round"/><line x1="86.8" y1="55.7" x2="57.2" y2="86.3" stroke="#fbbf24" stroke-width="9" stroke-linecap="round"/><line x1="57.2" y1="113.7" x2="86.8" y2="144.3" stroke="#fbbf24" stroke-width="9" stroke-linecap="round"/><circle cx="100" cy="42" r="18" fill="#22d3ee"/><circle cx="44" cy="100" r="18" fill="#fbbf24"/><circle cx="156" cy="100" r="18" fill="#a78bfa"/><circle cx="100" cy="158" r="18" fill="#22d3ee"/></svg>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Generate the cgis GitHub App avatar.
|
|
2
|
+
|
|
3
|
+
Ships `v3-lit-path` as `cgis-app-avatar.png`; the other two are kept so the
|
|
4
|
+
alternatives are on the record rather than lost in a chat log.
|
|
5
|
+
|
|
6
|
+
The motif comes from the domain rather than decoration: cgis's drift alphabet is
|
|
7
|
+
built on directed triads (`_TRICODES` / `TRIAD_ORDER`), so the glyphs are actual
|
|
8
|
+
triad shapes — 021D (diverging) and the layered_dag ideal.
|
|
9
|
+
|
|
10
|
+
No arrowheads. SVG markers scale by stroke-width by default (a 4.5-unit head at
|
|
11
|
+
stroke 9 renders as a 40-unit blob), and even sized correctly an arrowhead is
|
|
12
|
+
mush at the 40px a bot avatar occupies in a PR thread. Hierarchy is carried by
|
|
13
|
+
node size and colour instead.
|
|
14
|
+
|
|
15
|
+
Rendered at 400px for upload and 40px to check legibility at comment size.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import pathlib
|
|
19
|
+
|
|
20
|
+
import cairosvg
|
|
21
|
+
|
|
22
|
+
BG = "#0d1526"
|
|
23
|
+
EDGE = "#64748b"
|
|
24
|
+
CYAN = "#22d3ee"
|
|
25
|
+
VIOLET = "#a78bfa"
|
|
26
|
+
AMBER = "#fbbf24"
|
|
27
|
+
|
|
28
|
+
HEAD = (
|
|
29
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">'
|
|
30
|
+
f'<rect width="200" height="200" rx="44" fill="{BG}"/>'
|
|
31
|
+
)
|
|
32
|
+
TAIL = "</svg>"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def edge(
|
|
36
|
+
p1: tuple[float, float], p2: tuple[float, float], *, colour: str = EDGE, w: float = 8
|
|
37
|
+
) -> str:
|
|
38
|
+
"""A graph edge, trimmed at both ends so it meets the node rims cleanly."""
|
|
39
|
+
(x1, y1), (x2, y2) = p1, p2
|
|
40
|
+
dx, dy = x2 - x1, y2 - y1
|
|
41
|
+
length = (dx * dx + dy * dy) ** 0.5
|
|
42
|
+
ux, uy = dx / length, dy / length
|
|
43
|
+
pad = 19
|
|
44
|
+
return (
|
|
45
|
+
f'<line x1="{x1 + ux * pad:.1f}" y1="{y1 + uy * pad:.1f}" '
|
|
46
|
+
f'x2="{x2 - ux * pad:.1f}" y2="{y2 - uy * pad:.1f}" '
|
|
47
|
+
f'stroke="{colour}" stroke-width="{w}" stroke-linecap="round"/>'
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def node(p: tuple[float, float], colour: str, r: float = 18) -> str:
|
|
52
|
+
"""A graph node."""
|
|
53
|
+
return f'<circle cx="{p[0]}" cy="{p[1]}" r="{r}" fill="{colour}"/>'
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
TOP, LEFT, RIGHT, BOTTOM = (100, 42), (44, 100), (156, 100), (100, 158)
|
|
57
|
+
|
|
58
|
+
# 1. layered_dag — diverge at the top, converge at the bottom.
|
|
59
|
+
v1 = (
|
|
60
|
+
HEAD
|
|
61
|
+
+ edge(TOP, LEFT)
|
|
62
|
+
+ edge(TOP, RIGHT)
|
|
63
|
+
+ edge(LEFT, BOTTOM)
|
|
64
|
+
+ edge(RIGHT, BOTTOM)
|
|
65
|
+
+ node(TOP, CYAN)
|
|
66
|
+
+ node(LEFT, VIOLET)
|
|
67
|
+
+ node(RIGHT, VIOLET)
|
|
68
|
+
+ node(BOTTOM, CYAN)
|
|
69
|
+
+ TAIL
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# 2. 021D on its own — fewest strokes, best legibility at 40px.
|
|
73
|
+
T2, BL2, BR2 = (100, 54), (48, 144), (152, 144)
|
|
74
|
+
v2 = (
|
|
75
|
+
HEAD
|
|
76
|
+
+ edge(T2, BL2, w=9)
|
|
77
|
+
+ edge(T2, BR2, w=9)
|
|
78
|
+
+ node(T2, CYAN, 21)
|
|
79
|
+
+ node(BL2, VIOLET, 21)
|
|
80
|
+
+ node(BR2, VIOLET, 21)
|
|
81
|
+
+ TAIL
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# 3. layered_dag with one path lit — structure, plus the analysis laid over it.
|
|
85
|
+
v3 = (
|
|
86
|
+
HEAD
|
|
87
|
+
+ edge(TOP, RIGHT)
|
|
88
|
+
+ edge(RIGHT, BOTTOM)
|
|
89
|
+
+ edge(TOP, LEFT, colour=AMBER, w=9)
|
|
90
|
+
+ edge(LEFT, BOTTOM, colour=AMBER, w=9)
|
|
91
|
+
+ node(TOP, CYAN)
|
|
92
|
+
+ node(LEFT, AMBER)
|
|
93
|
+
+ node(RIGHT, VIOLET)
|
|
94
|
+
+ node(BOTTOM, CYAN)
|
|
95
|
+
+ TAIL
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
HERE = pathlib.Path(__file__).parent
|
|
99
|
+
# Variants land in a gitignored scratch dir; only the chosen one is versioned,
|
|
100
|
+
# so re-running this never litters docs/assets.
|
|
101
|
+
VARIANTS = HERE / "_variants"
|
|
102
|
+
VARIANTS.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
|
|
104
|
+
CHOSEN = "v3-lit-path"
|
|
105
|
+
|
|
106
|
+
for name, svg in (("v1-layered-dag", v1), ("v2-fanout", v2), ("v3-lit-path", v3)):
|
|
107
|
+
(VARIANTS / f"{name}.svg").write_text(svg)
|
|
108
|
+
for px in (400, 40):
|
|
109
|
+
cairosvg.svg2png(
|
|
110
|
+
bytestring=svg.encode(),
|
|
111
|
+
write_to=str(VARIANTS / f"{name}-{px}.png"),
|
|
112
|
+
output_width=px,
|
|
113
|
+
output_height=px,
|
|
114
|
+
)
|
|
115
|
+
if name == CHOSEN:
|
|
116
|
+
(HERE / "cgis-app-avatar.svg").write_text(svg)
|
|
117
|
+
cairosvg.svg2png(
|
|
118
|
+
bytestring=svg.encode(),
|
|
119
|
+
write_to=str(HERE / "cgis-app-avatar.png"),
|
|
120
|
+
output_width=400,
|
|
121
|
+
output_height=400,
|
|
122
|
+
)
|
|
123
|
+
print(f"rendered {name}" + (" <- shipped as cgis-app-avatar.*" if name == CHOSEN else ""))
|
|
@@ -176,9 +176,14 @@ Show the structural layout (CONTAINS/DECLARES) of a module or class.
|
|
|
176
176
|
Scan a local directory, extract all symbols, resolve links, and build the graph DB.
|
|
177
177
|
|
|
178
178
|
Use this to initialise or refresh the code knowledge graph for a project.
|
|
179
|
-
|
|
179
|
+
Node FQNs are normalised relative to the workspace root so the graph is
|
|
180
180
|
portable across machines.
|
|
181
181
|
|
|
182
|
+
``db_path`` must name a database — it has to end in ``.db``, ``.sqlite`` or
|
|
183
|
+
``.sqlite3``, live in a directory that already exists, and not point at an
|
|
184
|
+
existing file that is not a SQLite database. cgis will not create parent
|
|
185
|
+
directories.
|
|
186
|
+
|
|
182
187
|
By default the ingest is **incremental**: only changed/new files are
|
|
183
188
|
re-scanned, and the summary reports both what changed this run and the
|
|
184
189
|
whole-graph total. Set ``full_rebuild=True`` to re-scan every file and
|
|
@@ -7,7 +7,7 @@ packages = ["src/cgis"]
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "codegraph-brain"
|
|
10
|
-
version = "0.7.
|
|
10
|
+
version = "0.7.4"
|
|
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"
|
|
@@ -85,20 +85,92 @@ def _render_subgraph(
|
|
|
85
85
|
return f"❌ Unknown format '{output_format}'. Use 'mermaid' or 'json'."
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
#: Names cgis will create a database under. Everything else is refused, so an
|
|
89
|
+
#: agent cannot be talked into materialising `~/.ssh/authorized_keys` (#312).
|
|
90
|
+
_DB_SUFFIXES = frozenset({".db", ".sqlite", ".sqlite3"})
|
|
91
|
+
|
|
92
|
+
#: First 16 bytes of any SQLite file.
|
|
93
|
+
_SQLITE_MAGIC = b"SQLite format 3\x00"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _reject_db_path(db_path: str) -> str | None:
|
|
97
|
+
"""Return a refusal message for an unusable ``db_path``, or None if it is fine.
|
|
98
|
+
|
|
99
|
+
``cgis_ingest`` is the only MCP tool that creates its database — the other
|
|
100
|
+
twelve refuse a path that does not already exist, which is guard enough for
|
|
101
|
+
them. It needs a different one: it reads untrusted repository content and is
|
|
102
|
+
then told by the same agent where to write, so ``db_path`` is attacker-
|
|
103
|
+
reachable in a way the read-only tools' paths are not.
|
|
104
|
+
|
|
105
|
+
Refuses an unexpected suffix, a missing parent directory (creating a tree is
|
|
106
|
+
never wanted), a directory target, and an existing file that is not a
|
|
107
|
+
database. The last is belt-and-braces — SQLite already declines to open a
|
|
108
|
+
non-database — but it fails with a message that says why.
|
|
109
|
+
|
|
110
|
+
Everything is judged on the **resolved** path. A dangling symlink is the
|
|
111
|
+
bypass this guard exists to stop: ``attack.db`` pointing at a target that
|
|
112
|
+
does not exist yet makes ``is_file()`` return False, every check passes, and
|
|
113
|
+
SQLite creates the target. Resolving first means the suffix rule applies to
|
|
114
|
+
where the write actually lands. (A symlink to an *existing* non-database was
|
|
115
|
+
already refused by the magic-byte check.)
|
|
116
|
+
|
|
117
|
+
The filesystem probes are wrapped: this runs *before* ``cgis_ingest``'s own
|
|
118
|
+
try/except, and ``Path.resolve()``, ``Path.is_dir()`` and friends propagate
|
|
119
|
+
``OSError`` (a ``PermissionError`` on the parent, or a symlink loop), which
|
|
120
|
+
would escape the tool as a crash instead of a message the agent can act on.
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
path = Path(db_path).resolve()
|
|
124
|
+
except OSError as exc:
|
|
125
|
+
return f"❌ Refusing db_path '{db_path}': path is inaccessible ({exc})."
|
|
126
|
+
# Case-insensitive: `.DB` carries the same intent, and on a case-insensitive
|
|
127
|
+
# filesystem it is literally the same file.
|
|
128
|
+
if path.suffix.lower() not in _DB_SUFFIXES:
|
|
129
|
+
allowed = ", ".join(sorted(_DB_SUFFIXES))
|
|
130
|
+
return f"❌ Refusing db_path '{db_path}': name must end in one of {allowed}."
|
|
131
|
+
try:
|
|
132
|
+
if path.is_dir():
|
|
133
|
+
return f"❌ Refusing db_path '{db_path}': it is a directory."
|
|
134
|
+
if not path.parent.is_dir():
|
|
135
|
+
return (
|
|
136
|
+
f"❌ Refusing db_path '{db_path}': parent directory does not exist. "
|
|
137
|
+
"cgis will not create one."
|
|
138
|
+
)
|
|
139
|
+
if path.is_file() and path.stat().st_size > 0:
|
|
140
|
+
with path.open("rb") as fh:
|
|
141
|
+
if fh.read(len(_SQLITE_MAGIC)) != _SQLITE_MAGIC:
|
|
142
|
+
return (
|
|
143
|
+
f"❌ Refusing db_path '{db_path}': existing file is not a SQLite database."
|
|
144
|
+
)
|
|
145
|
+
except OSError as exc:
|
|
146
|
+
return f"❌ Refusing db_path '{db_path}': path is inaccessible ({exc})."
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
|
|
88
150
|
@mcp.tool()
|
|
89
151
|
def cgis_ingest(project_path: str, db_path: str = _DEFAULT_DB, full_rebuild: bool = False) -> str:
|
|
90
152
|
"""Scan a local directory, extract all symbols, resolve links, and build the graph DB.
|
|
91
153
|
|
|
92
154
|
Use this to initialise or refresh the code knowledge graph for a project.
|
|
93
|
-
|
|
155
|
+
Node FQNs are normalised relative to the workspace root so the graph is
|
|
94
156
|
portable across machines.
|
|
95
157
|
|
|
158
|
+
``db_path`` must name a database — it has to end in ``.db``, ``.sqlite`` or
|
|
159
|
+
``.sqlite3``, live in a directory that already exists, and not point at an
|
|
160
|
+
existing file that is not a SQLite database. cgis will not create parent
|
|
161
|
+
directories.
|
|
162
|
+
|
|
96
163
|
By default the ingest is **incremental**: only changed/new files are
|
|
97
164
|
re-scanned, and the summary reports both what changed this run and the
|
|
98
165
|
whole-graph total. Set ``full_rebuild=True`` to re-scan every file and
|
|
99
166
|
overwrite the database from scratch — use this to drop nodes for files that
|
|
100
167
|
were deleted or renamed, which an incremental run leaves behind.
|
|
101
168
|
"""
|
|
169
|
+
refusal = _reject_db_path(db_path)
|
|
170
|
+
if refusal is not None:
|
|
171
|
+
logger.warning("MCP ingest refused db_path", db=db_path)
|
|
172
|
+
return refusal
|
|
173
|
+
|
|
102
174
|
pipeline = IngestionPipeline(_EXTRACTORS)
|
|
103
175
|
try:
|
|
104
176
|
with SQLiteStore(db_path) as store:
|
|
@@ -126,7 +126,7 @@ class ResolverEngine:
|
|
|
126
126
|
|
|
127
127
|
def _ensure_virtual_node(self, target: str, virtual_nodes: dict[str, Node]) -> None:
|
|
128
128
|
"""Create a virtual boundary node for target if it is not already in the graph."""
|
|
129
|
-
if
|
|
129
|
+
if not self._index.has_node(target) and target not in virtual_nodes:
|
|
130
130
|
virtual_nodes[target] = self._make_virtual_node(
|
|
131
131
|
target, self._index.classify_fqn(target)
|
|
132
132
|
)
|