animamunch 1.108.82__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.
- animamunch-1.108.82/.clabot +28 -0
- animamunch-1.108.82/.dockerignore +14 -0
- animamunch-1.108.82/.github/actions/health-radar/README.md +109 -0
- animamunch-1.108.82/.github/actions/health-radar/action.yml +145 -0
- animamunch-1.108.82/.github/actions/health-radar/render_comment.py +170 -0
- animamunch-1.108.82/.github/dependabot.yml +15 -0
- animamunch-1.108.82/.github/workflows/health-radar-comment.yml +80 -0
- animamunch-1.108.82/.github/workflows/health-radar.yml +53 -0
- animamunch-1.108.82/.github/workflows/publish.yml +49 -0
- animamunch-1.108.82/.github/workflows/sign-release.yml +103 -0
- animamunch-1.108.82/.github/workflows/test.yml +75 -0
- animamunch-1.108.82/.gitignore +84 -0
- animamunch-1.108.82/AGENTS.md +81 -0
- animamunch-1.108.82/AGENT_HINTS.md +94 -0
- animamunch-1.108.82/AGENT_HOOKS.md +1239 -0
- animamunch-1.108.82/AGENT_INSTALL_UNIVERSAL.md +264 -0
- animamunch-1.108.82/ARCHITECTURE.md +801 -0
- animamunch-1.108.82/CHANGELOG.md +6796 -0
- animamunch-1.108.82/CODE_OF_CONDUCT.md +92 -0
- animamunch-1.108.82/CONFIGURATION.md +486 -0
- animamunch-1.108.82/CONTEXT_PROVIDERS.md +380 -0
- animamunch-1.108.82/CONTRIBUTING.md +47 -0
- animamunch-1.108.82/Caddyfile +26 -0
- animamunch-1.108.82/Dockerfile +37 -0
- animamunch-1.108.82/GROQ.md +256 -0
- animamunch-1.108.82/HEADLESS.md +149 -0
- animamunch-1.108.82/INSTALL_FROM_SOURCE.md +404 -0
- animamunch-1.108.82/LANGUAGE_SUPPORT.md +216 -0
- animamunch-1.108.82/LICENSE +52 -0
- animamunch-1.108.82/PKG-INFO +1141 -0
- animamunch-1.108.82/QUICKSTART.md +399 -0
- animamunch-1.108.82/README.md +1003 -0
- animamunch-1.108.82/RELEASE_RESTORE.md +83 -0
- animamunch-1.108.82/SECURITY.md +283 -0
- animamunch-1.108.82/SPEC.md +1241 -0
- animamunch-1.108.82/SPEC_MUNCH.md +252 -0
- animamunch-1.108.82/TOKEN_SAVINGS.md +159 -0
- animamunch-1.108.82/TROUBLESHOOTING.md +277 -0
- animamunch-1.108.82/TWEAKCC.md +251 -0
- animamunch-1.108.82/USER_GUIDE.md +1005 -0
- animamunch-1.108.82/badge-kit.md +202 -0
- animamunch-1.108.82/benchmarks/METHODOLOGY.md +169 -0
- animamunch-1.108.82/benchmarks/RAG_COMPARISON_NOTES.md +135 -0
- animamunch-1.108.82/benchmarks/README.md +95 -0
- animamunch-1.108.82/benchmarks/ab-test-dead-code-2026-03-18.md +91 -0
- animamunch-1.108.82/benchmarks/ab-test-naming-audit-2026-03-18.md +83 -0
- animamunch-1.108.82/benchmarks/harness/ab_v1_70_0.py +251 -0
- animamunch-1.108.82/benchmarks/harness/capture_schema_baseline.py +80 -0
- animamunch-1.108.82/benchmarks/harness/capture_token_baseline.py +72 -0
- animamunch-1.108.82/benchmarks/harness/run_benchmark.py +398 -0
- animamunch-1.108.82/benchmarks/harness/run_rag_baseline.py +925 -0
- animamunch-1.108.82/benchmarks/profile_backpressure.py +512 -0
- animamunch-1.108.82/benchmarks/profile_config_regression.py +258 -0
- animamunch-1.108.82/benchmarks/profile_language_filter.py +317 -0
- animamunch-1.108.82/benchmarks/rag_baseline_results.json +2723 -0
- animamunch-1.108.82/benchmarks/rag_baseline_results.md +312 -0
- animamunch-1.108.82/benchmarks/replay/__init__.py +6 -0
- animamunch-1.108.82/benchmarks/replay/fixtures/self_v1_75_0.json +68 -0
- animamunch-1.108.82/benchmarks/replay/metrics.py +77 -0
- animamunch-1.108.82/benchmarks/replay/results/self_v1_75_0-v1.75.0.json +96 -0
- animamunch-1.108.82/benchmarks/replay/run_replay.py +163 -0
- animamunch-1.108.82/benchmarks/requirements-rag-bench.txt +9 -0
- animamunch-1.108.82/benchmarks/results.md +140 -0
- animamunch-1.108.82/benchmarks/results_v1.70.0.md +84 -0
- animamunch-1.108.82/benchmarks/schema_baseline.json +8 -0
- animamunch-1.108.82/benchmarks/tasks.json +57 -0
- animamunch-1.108.82/benchmarks/token_baselines/README.md +50 -0
- animamunch-1.108.82/benchmarks/whitepaper.md +588 -0
- animamunch-1.108.82/cli/README.md +64 -0
- animamunch-1.108.82/cli/cli.py +64 -0
- animamunch-1.108.82/clients/ts/README.md +44 -0
- animamunch-1.108.82/clients/ts/decoder.ts +301 -0
- animamunch-1.108.82/docker-compose.yml +44 -0
- animamunch-1.108.82/examples/groq_validate.py +229 -0
- animamunch-1.108.82/examples/otel-collector/README.md +54 -0
- animamunch-1.108.82/examples/otel-collector/jcm-exporter.yaml +69 -0
- animamunch-1.108.82/jcodemunch_whitepaper.pdf +0 -0
- animamunch-1.108.82/munch-bench/corpus/django.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/express.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/fastapi.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/flask.yaml +89 -0
- animamunch-1.108.82/munch-bench/corpus/gin.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/jcodemunch.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/langchain.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/nextjs.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/pytorch.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/react.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/requests.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/rust_axum.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/spring_boot.yaml +81 -0
- animamunch-1.108.82/munch-bench/corpus/vue.yaml +81 -0
- animamunch-1.108.82/munch-bench/leaderboard.html +195 -0
- animamunch-1.108.82/munch-bench/munch_bench/__init__.py +3 -0
- animamunch-1.108.82/munch-bench/munch_bench/cli.py +151 -0
- animamunch-1.108.82/munch-bench/munch_bench/corpus.py +77 -0
- animamunch-1.108.82/munch-bench/munch_bench/encoding_bench.py +216 -0
- animamunch-1.108.82/munch-bench/munch_bench/evaluate.py +298 -0
- animamunch-1.108.82/munch-bench/munch_bench/inference.py +203 -0
- animamunch-1.108.82/munch-bench/munch_bench/leaderboard.py +218 -0
- animamunch-1.108.82/munch-bench/munch_bench/retrieval.py +83 -0
- animamunch-1.108.82/munch-bench/munch_bench/runner.py +145 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_express.json +777 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_fastapi.json +502 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_flask.json +768 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_express.json +777 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_fastapi.json +502 -0
- animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_flask.json +768 -0
- animamunch-1.108.82/munch-bench/results/groq_llama-3.3-70b-versatile_2026-04-13.json +634 -0
- animamunch-1.108.82/munch-bench/tests/__init__.py +0 -0
- animamunch-1.108.82/munch-bench/tests/test_corpus.py +59 -0
- animamunch-1.108.82/munch-bench/tests/test_evaluate.py +80 -0
- animamunch-1.108.82/munch-bench/tests/test_leaderboard.py +40 -0
- animamunch-1.108.82/packaging/debian/build_deb.sh +179 -0
- animamunch-1.108.82/pyproject.toml +122 -0
- animamunch-1.108.82/scripts/unstable_modules_diag.py +81 -0
- animamunch-1.108.82/server.json +21 -0
- animamunch-1.108.82/speedreview/README.md +140 -0
- animamunch-1.108.82/speedreview/action.yml +82 -0
- animamunch-1.108.82/speedreview/review.py +426 -0
- animamunch-1.108.82/src/jcodemunch_mcp/__init__.py +8 -0
- animamunch-1.108.82/src/jcodemunch_mcp/__main__.py +5 -0
- animamunch-1.108.82/src/jcodemunch_mcp/agent_selector.py +495 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/__init__.py +0 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/delivery.py +119 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/digest.py +111 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/file_risk.py +87 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/health.py +86 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/hooks.py +960 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/init.py +1946 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/install_pack.py +266 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/observatory.py +88 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/receipt.py +467 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/reflect.py +130 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/skills.py +284 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/upgrade.py +55 -0
- animamunch-1.108.82/src/jcodemunch_mcp/cli/whatsnew.py +188 -0
- animamunch-1.108.82/src/jcodemunch_mcp/config.py +2424 -0
- animamunch-1.108.82/src/jcodemunch_mcp/counter.py +353 -0
- animamunch-1.108.82/src/jcodemunch_mcp/credentials.py +227 -0
- animamunch-1.108.82/src/jcodemunch_mcp/embeddings/__init__.py +0 -0
- animamunch-1.108.82/src/jcodemunch_mcp/embeddings/local_encoder.py +368 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/__init__.py +113 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/decoder.py +36 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/format.py +296 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/gate.py +41 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/generic.py +366 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/json_passthrough.py +15 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schema_driven.py +256 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/__init__.py +14 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/find_importers.py +27 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/find_references.py +89 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_blast_radius.py +43 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_call_hierarchy.py +48 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_dependency_cycles.py +39 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_dependency_graph.py +42 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_file_outline.py +158 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_impact_preview.py +34 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_ranked_context.py +37 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_repo_outline.py +44 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_signal_chains.py +52 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_tectonic_map.py +52 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/registry.py +49 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_ast.py +29 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_symbols.py +29 -0
- animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_text.py +129 -0
- animamunch-1.108.82/src/jcodemunch_mcp/enrichment/__init__.py +0 -0
- animamunch-1.108.82/src/jcodemunch_mcp/enrichment/lsp_bridge.py +1042 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/__init__.py +1 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/cli.py +219 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/config.py +52 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/explainer.py +460 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/inference.py +79 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/retriever.py +141 -0
- animamunch-1.108.82/src/jcodemunch_mcp/groq/voice.py +296 -0
- animamunch-1.108.82/src/jcodemunch_mcp/hook_event.py +213 -0
- animamunch-1.108.82/src/jcodemunch_mcp/org/__init__.py +11 -0
- animamunch-1.108.82/src/jcodemunch_mcp/org/http_routes.py +94 -0
- animamunch-1.108.82/src/jcodemunch_mcp/org/license.py +241 -0
- animamunch-1.108.82/src/jcodemunch_mcp/org/report.py +73 -0
- animamunch-1.108.82/src/jcodemunch_mcp/org/store.py +101 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/__init__.py +23 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/astro_shared.py +44 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/complexity.py +111 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/__init__.py +27 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/_route_utils.py +313 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/base.py +253 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/dbt.py +269 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/decorator_routes.py +397 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/django.py +266 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/express.py +219 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/framework_profiles.py +447 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/git_blame.py +170 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/go_routers.py +159 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/laravel.py +826 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/nextjs.py +217 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/nuxt.py +254 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/context/rails.py +293 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/extractor.py +9697 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/fqn.py +97 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/hierarchy.py +46 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/imports.py +1280 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/languages.py +2200 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/parse_cache.py +165 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/sql_preprocessor.py +186 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/symbols.py +80 -0
- animamunch-1.108.82/src/jcodemunch_mcp/parser/template_shared.py +182 -0
- animamunch-1.108.82/src/jcodemunch_mcp/path_map.py +84 -0
- animamunch-1.108.82/src/jcodemunch_mcp/progress.py +149 -0
- animamunch-1.108.82/src/jcodemunch_mcp/redact.py +252 -0
- animamunch-1.108.82/src/jcodemunch_mcp/reindex_state.py +328 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/__init__.py +1 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/confidence.py +175 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/embed_drift.py +268 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/freshness.py +268 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/regret.py +245 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/signal_fusion.py +307 -0
- animamunch-1.108.82/src/jcodemunch_mcp/retrieval/tuning.py +321 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/__init__.py +60 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/confidence.py +328 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/http_routes.py +408 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/ingest.py +365 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/otel.py +268 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/redact.py +157 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/resolve.py +133 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/sql_ingest.py +526 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/sql_log.py +429 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/stack_ingest.py +339 -0
- animamunch-1.108.82/src/jcodemunch_mcp/runtime/stack_log.py +481 -0
- animamunch-1.108.82/src/jcodemunch_mcp/secret_classifier.py +310 -0
- animamunch-1.108.82/src/jcodemunch_mcp/security.py +457 -0
- animamunch-1.108.82/src/jcodemunch_mcp/server.py +9633 -0
- animamunch-1.108.82/src/jcodemunch_mcp/service_installer.py +293 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/__init__.py +15 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/embedding_store.py +251 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/git_root.py +321 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/index_store.py +1073 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/process_locks.py +374 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/sqlite_store.py +2661 -0
- animamunch-1.108.82/src/jcodemunch_mcp/storage/token_tracker.py +914 -0
- animamunch-1.108.82/src/jcodemunch_mcp/summarizer/__init__.py +25 -0
- animamunch-1.108.82/src/jcodemunch_mcp/summarizer/batch_summarize.py +906 -0
- animamunch-1.108.82/src/jcodemunch_mcp/summarizer/file_summarize.py +89 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tier_resolver.py +118 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/__init__.py +4 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/_call_graph.py +708 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/_indexing_pipeline.py +410 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/_utils.py +141 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/analyze_perf.py +261 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/assemble_task_context.py +1027 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/audit_agent_config.py +464 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/check_embedding_drift.py +38 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/check_references.py +225 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/check_rename_safe.py +114 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/check_safe.py +637 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/decision_context.py +213 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/digest.py +394 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/embed_repo.py +337 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_hot_paths.py +148 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_implementations.py +540 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_importers.py +356 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_references.py +343 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_similar_symbols.py +546 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/find_unused_paths.py +308 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/flow_edges.py +401 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_blast_radius.py +544 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_call_hierarchy.py +214 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_changed_symbols.py +294 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_churn_rate.py +176 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_class_hierarchy.py +160 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_context_bundle.py +443 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_coupling_metrics.py +106 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_cross_repo_map.py +135 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dead_code_v2.py +623 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_delivery_metrics.py +315 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dependency_cycles.py +130 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dependency_graph.py +237 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_extraction_candidates.py +146 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_content.py +93 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_outline.py +211 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_risk.py +249 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_tree.py +159 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_group_contracts.py +463 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_hotspots.py +180 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_impact_preview.py +207 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_layer_violations.py +169 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_pr_risk_profile.py +630 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_project_intel.py +1146 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_ranked_context.py +569 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_redaction_log.py +145 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_related_symbols.py +148 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_health.py +276 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_map.py +220 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_outline.py +193 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_runtime_coverage.py +190 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_session_context.py +273 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_signal_chains.py +554 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol.py +436 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_complexity.py +98 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_diff.py +122 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_importance.py +137 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_provenance.py +505 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_tectonic_map.py +566 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_untested_symbols.py +232 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/get_watch_status.py +112 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/health_radar.py +339 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/import_runtime_signal.py +135 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/index_file.py +248 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/index_folder.py +2331 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/index_repo.py +611 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/invalidate_cache.py +79 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/list_repos.py +69 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/list_workspaces.py +524 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/mermaid_viewer.py +169 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/observatory.py +306 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/observatory_render.py +440 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/package_registry.py +478 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/pagerank.py +101 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/plan_refactoring.py +2262 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/plan_turn.py +297 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/register_edit.py +99 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/render_diagram.py +1113 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/resolve_repo.py +436 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/search_ast.py +1218 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/search_columns.py +174 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/search_symbols.py +1586 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/search_text.py +204 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/session_journal.py +212 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/session_state.py +330 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/suggest_corrections.py +326 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/suggest_queries.py +124 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/summarize_repo.py +140 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/tune_weights.py +72 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/turn_budget.py +137 -0
- animamunch-1.108.82/src/jcodemunch_mcp/tools/winnow_symbols.py +349 -0
- animamunch-1.108.82/src/jcodemunch_mcp/version_check.py +94 -0
- animamunch-1.108.82/src/jcodemunch_mcp/watch_all.py +157 -0
- animamunch-1.108.82/src/jcodemunch_mcp/watcher.py +1298 -0
- animamunch-1.108.82/tests/__init__.py +25 -0
- animamunch-1.108.82/tests/conftest.py +161 -0
- animamunch-1.108.82/tests/conftest_helpers.py +62 -0
- animamunch-1.108.82/tests/encoding/__init__.py +0 -0
- animamunch-1.108.82/tests/encoding/test_dispatcher.py +168 -0
- animamunch-1.108.82/tests/encoding/test_format.py +65 -0
- animamunch-1.108.82/tests/encoding/test_generic_hardened.py +209 -0
- animamunch-1.108.82/tests/encoding/test_tier1_roundtrip.py +695 -0
- animamunch-1.108.82/tests/fixtures/al/sample.al +189 -0
- animamunch-1.108.82/tests/fixtures/arduino/sample.ino +49 -0
- animamunch-1.108.82/tests/fixtures/astro/BaseLayout.astro +47 -0
- animamunch-1.108.82/tests/fixtures/astro/ClientIsland.astro +49 -0
- animamunch-1.108.82/tests/fixtures/astro/ContentPage.astro +10 -0
- animamunch-1.108.82/tests/fixtures/astro/DynamicRoute.astro +40 -0
- animamunch-1.108.82/tests/fixtures/astro/WidgetComponent.astro +43 -0
- animamunch-1.108.82/tests/fixtures/astro/WithProps.astro +17 -0
- animamunch-1.108.82/tests/fixtures/astro/sample.astro +11 -0
- animamunch-1.108.82/tests/fixtures/astro/sample_bom_crlf.astro +12 -0
- animamunch-1.108.82/tests/fixtures/astro/sample_malformed_frontmatter.astro +10 -0
- animamunch-1.108.82/tests/fixtures/astro/sample_multi_script.astro +29 -0
- animamunch-1.108.82/tests/fixtures/blade/sample.blade.php +31 -0
- animamunch-1.108.82/tests/fixtures/c/sample.c +34 -0
- animamunch-1.108.82/tests/fixtures/cpp/sample.cpp +44 -0
- animamunch-1.108.82/tests/fixtures/csharp/sample.cs +49 -0
- animamunch-1.108.82/tests/fixtures/dart/sample.dart +38 -0
- animamunch-1.108.82/tests/fixtures/elixir/sample.ex +56 -0
- animamunch-1.108.82/tests/fixtures/go/sample.go +20 -0
- animamunch-1.108.82/tests/fixtures/java/Sample.java +19 -0
- animamunch-1.108.82/tests/fixtures/javascript/sample.js +23 -0
- animamunch-1.108.82/tests/fixtures/perl/sample.pl +47 -0
- animamunch-1.108.82/tests/fixtures/php/sample.php +53 -0
- animamunch-1.108.82/tests/fixtures/python/sample.py +15 -0
- animamunch-1.108.82/tests/fixtures/razor/Counter.razor +36 -0
- animamunch-1.108.82/tests/fixtures/razor/dotnet_aspnetcore_layout.cshtml +57 -0
- animamunch-1.108.82/tests/fixtures/razor/sample.cshtml +18 -0
- animamunch-1.108.82/tests/fixtures/ruby/sample.rb +46 -0
- animamunch-1.108.82/tests/fixtures/rust/sample.rs +19 -0
- animamunch-1.108.82/tests/fixtures/templates/sample.py.jinja +20 -0
- animamunch-1.108.82/tests/fixtures/templates/sample.ts.j2 +21 -0
- animamunch-1.108.82/tests/fixtures/templates/widget.ts.twig +14 -0
- animamunch-1.108.82/tests/fixtures/typescript/sample.ts +24 -0
- animamunch-1.108.82/tests/fixtures/verilog/sample.sv +53 -0
- animamunch-1.108.82/tests/fixtures/vhdl/sample.vhd +39 -0
- animamunch-1.108.82/tests/fixtures/xml/sample.xml +15 -0
- animamunch-1.108.82/tests/fixtures/xml/sample.xul +17 -0
- animamunch-1.108.82/tests/test_adaptive_languages.py +208 -0
- animamunch-1.108.82/tests/test_agent_selector.py +427 -0
- animamunch-1.108.82/tests/test_al.py +465 -0
- animamunch-1.108.82/tests/test_anthropic_optional.py +60 -0
- animamunch-1.108.82/tests/test_architecture_tools.py +354 -0
- animamunch-1.108.82/tests/test_arrow_functions.py +178 -0
- animamunch-1.108.82/tests/test_asm_language.py +433 -0
- animamunch-1.108.82/tests/test_assemble_task_context.py +214 -0
- animamunch-1.108.82/tests/test_astro.py +104 -0
- animamunch-1.108.82/tests/test_audit_agent_config.py +356 -0
- animamunch-1.108.82/tests/test_blade.py +110 -0
- animamunch-1.108.82/tests/test_blast_radius.py +293 -0
- animamunch-1.108.82/tests/test_bm25_correctness.py +322 -0
- animamunch-1.108.82/tests/test_branch_indexing.py +535 -0
- animamunch-1.108.82/tests/test_build.py +49 -0
- animamunch-1.108.82/tests/test_cache_mode.py +107 -0
- animamunch-1.108.82/tests/test_call_extraction.py +269 -0
- animamunch-1.108.82/tests/test_call_graph_ast.py +221 -0
- animamunch-1.108.82/tests/test_call_hierarchy.py +676 -0
- animamunch-1.108.82/tests/test_call_references_model.py +632 -0
- animamunch-1.108.82/tests/test_check_delete_safe.py +208 -0
- animamunch-1.108.82/tests/test_check_edit_safe.py +108 -0
- animamunch-1.108.82/tests/test_check_references.py +161 -0
- animamunch-1.108.82/tests/test_check_rename_safe.py +77 -0
- animamunch-1.108.82/tests/test_churn_rate.py +137 -0
- animamunch-1.108.82/tests/test_class_hierarchy.py +212 -0
- animamunch-1.108.82/tests/test_claude_md_policy.py +146 -0
- animamunch-1.108.82/tests/test_cleanup.py +119 -0
- animamunch-1.108.82/tests/test_cli.py +170 -0
- animamunch-1.108.82/tests/test_complexity.py +97 -0
- animamunch-1.108.82/tests/test_confidence.py +148 -0
- animamunch-1.108.82/tests/test_config.py +2423 -0
- animamunch-1.108.82/tests/test_config_set.py +111 -0
- animamunch-1.108.82/tests/test_config_watcher_keys.py +36 -0
- animamunch-1.108.82/tests/test_context_providers.py +373 -0
- animamunch-1.108.82/tests/test_copilot_hook.py +82 -0
- animamunch-1.108.82/tests/test_counter.py +185 -0
- animamunch-1.108.82/tests/test_credentials.py +144 -0
- animamunch-1.108.82/tests/test_cross_repo.py +705 -0
- animamunch-1.108.82/tests/test_css.py +388 -0
- animamunch-1.108.82/tests/test_dart_imports.py +81 -0
- animamunch-1.108.82/tests/test_dbt_provider.py +481 -0
- animamunch-1.108.82/tests/test_dead_code_v2.py +87 -0
- animamunch-1.108.82/tests/test_decorator_awareness.py +252 -0
- animamunch-1.108.82/tests/test_decorator_routes.py +317 -0
- animamunch-1.108.82/tests/test_deferred_summarization.py +62 -0
- animamunch-1.108.82/tests/test_delete_index_cli.py +68 -0
- animamunch-1.108.82/tests/test_delivery_metrics.py +185 -0
- animamunch-1.108.82/tests/test_dependency_graph_imports_alias.py +88 -0
- animamunch-1.108.82/tests/test_digest.py +220 -0
- animamunch-1.108.82/tests/test_dispatch_resolution.py +434 -0
- animamunch-1.108.82/tests/test_dispatch_schema_parity.py +163 -0
- animamunch-1.108.82/tests/test_django_provider.py +128 -0
- animamunch-1.108.82/tests/test_docs_config_parity.py +130 -0
- animamunch-1.108.82/tests/test_embed_drift.py +188 -0
- animamunch-1.108.82/tests/test_express_provider.py +135 -0
- animamunch-1.108.82/tests/test_extra_extensions.py +116 -0
- animamunch-1.108.82/tests/test_extraction_candidates.py +120 -0
- animamunch-1.108.82/tests/test_file_summaries.py +200 -0
- animamunch-1.108.82/tests/test_find_dead_code.py +215 -0
- animamunch-1.108.82/tests/test_find_implementations.py +160 -0
- animamunch-1.108.82/tests/test_find_importers.py +1680 -0
- animamunch-1.108.82/tests/test_find_references_line_numbers.py +75 -0
- animamunch-1.108.82/tests/test_find_similar_symbols.py +210 -0
- animamunch-1.108.82/tests/test_fqn.py +184 -0
- animamunch-1.108.82/tests/test_framework_profiles.py +123 -0
- animamunch-1.108.82/tests/test_freshness.py +257 -0
- animamunch-1.108.82/tests/test_fuzzy_search.py +220 -0
- animamunch-1.108.82/tests/test_gcm.py +178 -0
- animamunch-1.108.82/tests/test_get_changed_symbols.py +298 -0
- animamunch-1.108.82/tests/test_get_context_bundle.py +114 -0
- animamunch-1.108.82/tests/test_get_file_outline_integration.py +133 -0
- animamunch-1.108.82/tests/test_get_file_risk.py +96 -0
- animamunch-1.108.82/tests/test_get_file_tree.py +198 -0
- animamunch-1.108.82/tests/test_get_group_contracts.py +219 -0
- animamunch-1.108.82/tests/test_get_repo_map.py +142 -0
- animamunch-1.108.82/tests/test_get_untested_symbols.py +271 -0
- animamunch-1.108.82/tests/test_git_root_identity.py +542 -0
- animamunch-1.108.82/tests/test_git_sha_verification.py +156 -0
- animamunch-1.108.82/tests/test_go_routers_provider.py +165 -0
- animamunch-1.108.82/tests/test_groq_explainer.py +170 -0
- animamunch-1.108.82/tests/test_groq_voice.py +126 -0
- animamunch-1.108.82/tests/test_handshake_watchdog.py +72 -0
- animamunch-1.108.82/tests/test_hardening.py +987 -0
- animamunch-1.108.82/tests/test_health_radar.py +240 -0
- animamunch-1.108.82/tests/test_health_radar_action.py +148 -0
- animamunch-1.108.82/tests/test_hooks.py +775 -0
- animamunch-1.108.82/tests/test_hotspots.py +148 -0
- animamunch-1.108.82/tests/test_identity_mode.py +297 -0
- animamunch-1.108.82/tests/test_incremental.py +290 -0
- animamunch-1.108.82/tests/test_index_file.py +189 -0
- animamunch-1.108.82/tests/test_init.py +516 -0
- animamunch-1.108.82/tests/test_init_hooks_paths.py +191 -0
- animamunch-1.108.82/tests/test_init_minimal.py +124 -0
- animamunch-1.108.82/tests/test_install_copilot_hooks.py +60 -0
- animamunch-1.108.82/tests/test_install_pack.py +214 -0
- animamunch-1.108.82/tests/test_install_uninstall.py +360 -0
- animamunch-1.108.82/tests/test_json.py +125 -0
- animamunch-1.108.82/tests/test_languages.py +2457 -0
- animamunch-1.108.82/tests/test_laravel_provider.py +917 -0
- animamunch-1.108.82/tests/test_list_repos.py +33 -0
- animamunch-1.108.82/tests/test_local_encoder.py +359 -0
- animamunch-1.108.82/tests/test_local_integration.py +579 -0
- animamunch-1.108.82/tests/test_lsp_bridge.py +494 -0
- animamunch-1.108.82/tests/test_luau_language.py +139 -0
- animamunch-1.108.82/tests/test_meta_disclosure.py +197 -0
- animamunch-1.108.82/tests/test_migration.py +72 -0
- animamunch-1.108.82/tests/test_mtime_optimization.py +282 -0
- animamunch-1.108.82/tests/test_negative_evidence.py +224 -0
- animamunch-1.108.82/tests/test_new_languages.py +514 -0
- animamunch-1.108.82/tests/test_new_languages_v143.py +358 -0
- animamunch-1.108.82/tests/test_nextjs_provider.py +223 -0
- animamunch-1.108.82/tests/test_nuxt_provider.py +218 -0
- animamunch-1.108.82/tests/test_observatory.py +301 -0
- animamunch-1.108.82/tests/test_org_http.py +89 -0
- animamunch-1.108.82/tests/test_org_license.py +133 -0
- animamunch-1.108.82/tests/test_org_rollup.py +50 -0
- animamunch-1.108.82/tests/test_pagerank.py +296 -0
- animamunch-1.108.82/tests/test_parse_cache.py +141 -0
- animamunch-1.108.82/tests/test_parse_warnings.py +201 -0
- animamunch-1.108.82/tests/test_parser.py +478 -0
- animamunch-1.108.82/tests/test_path_map.py +256 -0
- animamunch-1.108.82/tests/test_perf_telemetry.py +131 -0
- animamunch-1.108.82/tests/test_plan_refactoring.py +1907 -0
- animamunch-1.108.82/tests/test_plan_turn.py +248 -0
- animamunch-1.108.82/tests/test_post_tool_use_hook.py +232 -0
- animamunch-1.108.82/tests/test_process_locks.py +277 -0
- animamunch-1.108.82/tests/test_progress.py +251 -0
- animamunch-1.108.82/tests/test_project_intel.py +810 -0
- animamunch-1.108.82/tests/test_prompts.py +45 -0
- animamunch-1.108.82/tests/test_property_based.py +229 -0
- animamunch-1.108.82/tests/test_provider_metadata_and_perf.py +386 -0
- animamunch-1.108.82/tests/test_psr4.py +213 -0
- animamunch-1.108.82/tests/test_pulse.py +49 -0
- animamunch-1.108.82/tests/test_rails_provider.py +101 -0
- animamunch-1.108.82/tests/test_ranking_ledger.py +220 -0
- animamunch-1.108.82/tests/test_rate_limit.py +147 -0
- animamunch-1.108.82/tests/test_razor.py +257 -0
- animamunch-1.108.82/tests/test_receipt.py +254 -0
- animamunch-1.108.82/tests/test_redact.py +136 -0
- animamunch-1.108.82/tests/test_register_edit.py +128 -0
- animamunch-1.108.82/tests/test_reindex_state.py +277 -0
- animamunch-1.108.82/tests/test_related_symbols.py +173 -0
- animamunch-1.108.82/tests/test_render_diagram.py +553 -0
- animamunch-1.108.82/tests/test_render_diagram_integration.py +160 -0
- animamunch-1.108.82/tests/test_render_diagram_viewer.py +377 -0
- animamunch-1.108.82/tests/test_replay_metrics.py +145 -0
- animamunch-1.108.82/tests/test_repo_health.py +211 -0
- animamunch-1.108.82/tests/test_resolve_repo.py +549 -0
- animamunch-1.108.82/tests/test_result_cache.py +220 -0
- animamunch-1.108.82/tests/test_retrieval_tools.py +423 -0
- animamunch-1.108.82/tests/test_route_utils.py +247 -0
- animamunch-1.108.82/tests/test_runtime_phase0.py +333 -0
- animamunch-1.108.82/tests/test_runtime_phase1.py +461 -0
- animamunch-1.108.82/tests/test_runtime_phase2.py +416 -0
- animamunch-1.108.82/tests/test_runtime_phase3.py +244 -0
- animamunch-1.108.82/tests/test_runtime_phase4.py +474 -0
- animamunch-1.108.82/tests/test_runtime_phase5.py +412 -0
- animamunch-1.108.82/tests/test_runtime_phase6.py +418 -0
- animamunch-1.108.82/tests/test_runtime_phase7.py +300 -0
- animamunch-1.108.82/tests/test_scala_parser.py +120 -0
- animamunch-1.108.82/tests/test_schema_budget.py +169 -0
- animamunch-1.108.82/tests/test_search_columns.py +143 -0
- animamunch-1.108.82/tests/test_search_perf.py +213 -0
- animamunch-1.108.82/tests/test_search_result_cache.py +213 -0
- animamunch-1.108.82/tests/test_search_symbols_defaults.py +235 -0
- animamunch-1.108.82/tests/test_secret_classifier.py +162 -0
- animamunch-1.108.82/tests/test_security.py +940 -0
- animamunch-1.108.82/tests/test_semantic_search.py +634 -0
- animamunch-1.108.82/tests/test_server.py +1485 -0
- animamunch-1.108.82/tests/test_session_journal.py +234 -0
- animamunch-1.108.82/tests/test_session_snapshot.py +283 -0
- animamunch-1.108.82/tests/test_session_state.py +277 -0
- animamunch-1.108.82/tests/test_share_savings.py +161 -0
- animamunch-1.108.82/tests/test_signal_fusion.py +255 -0
- animamunch-1.108.82/tests/test_skills.py +197 -0
- animamunch-1.108.82/tests/test_sql_language.py +331 -0
- animamunch-1.108.82/tests/test_sqlite_store.py +895 -0
- animamunch-1.108.82/tests/test_storage.py +658 -0
- animamunch-1.108.82/tests/test_streamable_http_integration.py +162 -0
- animamunch-1.108.82/tests/test_streamable_http_sessions.py +198 -0
- animamunch-1.108.82/tests/test_suggest_corrections.py +196 -0
- animamunch-1.108.82/tests/test_suggest_queries.py +117 -0
- animamunch-1.108.82/tests/test_summarize_from_docstrings.py +97 -0
- animamunch-1.108.82/tests/test_summarizer.py +1726 -0
- animamunch-1.108.82/tests/test_swift_parser.py +102 -0
- animamunch-1.108.82/tests/test_symbol_complexity.py +109 -0
- animamunch-1.108.82/tests/test_symbol_diff.py +210 -0
- animamunch-1.108.82/tests/test_tectonic_map.py +222 -0
- animamunch-1.108.82/tests/test_telemetry_db_skip.py +141 -0
- animamunch-1.108.82/tests/test_templates.py +262 -0
- animamunch-1.108.82/tests/test_tier_resolver.py +183 -0
- animamunch-1.108.82/tests/test_tier_runtime.py +606 -0
- animamunch-1.108.82/tests/test_token_budget_context.py +376 -0
- animamunch-1.108.82/tests/test_tool_registration.py +94 -0
- animamunch-1.108.82/tests/test_tools.py +1266 -0
- animamunch-1.108.82/tests/test_truncated_flag.py +86 -0
- animamunch-1.108.82/tests/test_turn_budget.py +93 -0
- animamunch-1.108.82/tests/test_v1_108_0.py +302 -0
- animamunch-1.108.82/tests/test_v1_108_2.py +173 -0
- animamunch-1.108.82/tests/test_v1_108_55.py +216 -0
- animamunch-1.108.82/tests/test_v1_108_56.py +323 -0
- animamunch-1.108.82/tests/test_v1_108_57.py +148 -0
- animamunch-1.108.82/tests/test_v1_108_58.py +210 -0
- animamunch-1.108.82/tests/test_v1_108_59.py +161 -0
- animamunch-1.108.82/tests/test_v1_108_63.py +132 -0
- animamunch-1.108.82/tests/test_v1_108_64.py +73 -0
- animamunch-1.108.82/tests/test_v1_108_70.py +272 -0
- animamunch-1.108.82/tests/test_v1_108_71.py +89 -0
- animamunch-1.108.82/tests/test_v1_108_72.py +87 -0
- animamunch-1.108.82/tests/test_v1_108_73.py +128 -0
- animamunch-1.108.82/tests/test_v1_108_74.py +68 -0
- animamunch-1.108.82/tests/test_v1_108_78.py +218 -0
- animamunch-1.108.82/tests/test_v1_108_80.py +144 -0
- animamunch-1.108.82/tests/test_v1_108_81.py +59 -0
- animamunch-1.108.82/tests/test_v1_80_10_dead_code_intra_file_calls.py +74 -0
- animamunch-1.108.82/tests/test_v1_80_7_dead_code_js_reexports.py +206 -0
- animamunch-1.108.82/tests/test_v1_80_9_lodash_class.py +200 -0
- animamunch-1.108.82/tests/test_version_check.py +82 -0
- animamunch-1.108.82/tests/test_watch_all.py +110 -0
- animamunch-1.108.82/tests/test_watch_claude.py +717 -0
- animamunch-1.108.82/tests/test_watch_once.py +86 -0
- animamunch-1.108.82/tests/test_watcher_dynamic.py +409 -0
- animamunch-1.108.82/tests/test_watcher_lock.py +907 -0
- animamunch-1.108.82/tests/test_watcher_memory_cache.py +600 -0
- animamunch-1.108.82/tests/test_watcher_serve.py +1096 -0
- animamunch-1.108.82/tests/test_weight_tuning.py +241 -0
- animamunch-1.108.82/tests/test_whatsnew.py +130 -0
- animamunch-1.108.82/tests/test_winnow_symbols.py +208 -0
- animamunch-1.108.82/tests/test_yaml_language.py +140 -0
- animamunch-1.108.82/uv.lock +3635 -0
- animamunch-1.108.82/vscode-extension/.gitignore +3 -0
- animamunch-1.108.82/vscode-extension/.vscodeignore +6 -0
- animamunch-1.108.82/vscode-extension/README.md +63 -0
- animamunch-1.108.82/vscode-extension/package-lock.json +55 -0
- animamunch-1.108.82/vscode-extension/package.json +80 -0
- animamunch-1.108.82/vscode-extension/src/extension.ts +118 -0
- animamunch-1.108.82/vscode-extension/src/riskGutter.ts +297 -0
- animamunch-1.108.82/vscode-extension/tsconfig.json +14 -0
- animamunch-1.108.82/whatsnew.json +23 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"allowlist": [
|
|
3
|
+
"gokhanozdemir",
|
|
4
|
+
"thellMa",
|
|
5
|
+
"DrHayt",
|
|
6
|
+
"horknfbr",
|
|
7
|
+
"astrobleem",
|
|
8
|
+
"Cobdog",
|
|
9
|
+
"vvaltson",
|
|
10
|
+
"sanyapuer",
|
|
11
|
+
"paperlinguist",
|
|
12
|
+
"swmeyer1979",
|
|
13
|
+
"gebeer",
|
|
14
|
+
"josh-stephens",
|
|
15
|
+
"Mharbulous",
|
|
16
|
+
"snafu4",
|
|
17
|
+
"MariusAdrian88",
|
|
18
|
+
"ivanmilov",
|
|
19
|
+
"zrk02",
|
|
20
|
+
"Wes2000ley",
|
|
21
|
+
"allenguarnes",
|
|
22
|
+
"phuzzled",
|
|
23
|
+
"levonbragg",
|
|
24
|
+
"briepace",
|
|
25
|
+
"halindrome",
|
|
26
|
+
"vadash"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# jCodeMunch Health Radar — GitHub Action
|
|
2
|
+
|
|
3
|
+
A composite action that computes a six-axis code-health radar on the PR
|
|
4
|
+
branch and the base branch, diffs them, and posts the result as a
|
|
5
|
+
**sticky PR comment**. Suggestion-style — never blocks merges.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
1. Indexes the PR branch with `jcodemunch-mcp index .`
|
|
10
|
+
2. Runs `jcodemunch-mcp health . --radar-only` → PR radar JSON
|
|
11
|
+
3. Checks out the base branch, re-indexes, runs the same command → base
|
|
12
|
+
radar JSON
|
|
13
|
+
4. Computes the diff via the same pure helper exposed as the
|
|
14
|
+
`diff_health_radar` MCP tool
|
|
15
|
+
5. Renders a markdown table + axis movements + regression / improvement
|
|
16
|
+
bullets
|
|
17
|
+
6. Finds an existing sticky comment by HTML marker — `PATCH`es it on
|
|
18
|
+
re-runs, `POST`s a new one on the first run.
|
|
19
|
+
|
|
20
|
+
## Why a comment, not a status check
|
|
21
|
+
|
|
22
|
+
Status checks block merges. A heuristic that blocks merges gets the
|
|
23
|
+
Action disabled by the first frustrated maintainer. The radar comment
|
|
24
|
+
is **explanatory, not gating** — reviewers see the deltas, decide for
|
|
25
|
+
themselves.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
# .github/workflows/health-radar.yml
|
|
31
|
+
name: Health Radar
|
|
32
|
+
on:
|
|
33
|
+
pull_request:
|
|
34
|
+
types: [opened, synchronize, reopened]
|
|
35
|
+
|
|
36
|
+
permissions:
|
|
37
|
+
pull-requests: write # for sticky comment
|
|
38
|
+
contents: read # for git checkout
|
|
39
|
+
|
|
40
|
+
jobs:
|
|
41
|
+
radar:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 0 # need full history for index + base checkout
|
|
47
|
+
- uses: jgravelle/jcodemunch-mcp/.github/actions/health-radar@v1.88.0
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
That's the whole setup. The action handles install, index, base/branch
|
|
51
|
+
toggling, and comment posting itself.
|
|
52
|
+
|
|
53
|
+
## Inputs
|
|
54
|
+
|
|
55
|
+
| Input | Default | Description |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `python-version` | `3.11` | Python version on the runner. |
|
|
58
|
+
| `jcodemunch-version` | `latest` | Pin a specific package version, or `latest`. |
|
|
59
|
+
| `base-ref` | _(PR's base branch)_ | Override the comparison ref. |
|
|
60
|
+
| `github-token` | `${{ github.token }}` | Token used to post/edit the comment. |
|
|
61
|
+
|
|
62
|
+
## Output shape
|
|
63
|
+
|
|
64
|
+
The sticky comment looks like:
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
<!-- jcm-health-radar -->
|
|
68
|
+
## jCodeMunch Health Radar
|
|
69
|
+
|
|
70
|
+
🟡 **Composite:** B → C (-7.5 pts)
|
|
71
|
+
🔴 **Verdict:** REGRESSION on 2 axis/axes (composite -7.5)
|
|
72
|
+
|
|
73
|
+
| Axis | Baseline | PR | Δ |
|
|
74
|
+
|---|---:|---:|---:|
|
|
75
|
+
| `complexity` | 88 | 64 | **-24.0** ↓ |
|
|
76
|
+
| `dead_code` | 82 | 79 | -3.0 ↓ |
|
|
77
|
+
| `cycles` | 100 | 100 | +0.0 · |
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
### Regressions
|
|
81
|
+
- `complexity`: raw 4.5 → 11.0
|
|
82
|
+
- `dead_code`: raw 4.5 → 5.7
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Methodology
|
|
86
|
+
|
|
87
|
+
Per-axis scoring rules and rationale: see
|
|
88
|
+
[`tools/health_radar.py`](https://github.com/jgravelle/jcodemunch-mcp/blob/main/src/jcodemunch_mcp/tools/health_radar.py).
|
|
89
|
+
|
|
90
|
+
The composite is the arithmetic mean of every scored axis;
|
|
91
|
+
`omitted_axes` lists axes whose underlying signals weren't available
|
|
92
|
+
(e.g. `test_gap` if `get_untested_symbols` couldn't run).
|
|
93
|
+
|
|
94
|
+
## Known caveats
|
|
95
|
+
|
|
96
|
+
- **Re-indexes on both branches** — adds runtime in CI, scaling roughly
|
|
97
|
+
with codebase size. For very large repos, the baseline could be
|
|
98
|
+
cached by base SHA in a follow-up release.
|
|
99
|
+
- **Heuristic, not coverage data** — `test_gap` is import-graph
|
|
100
|
+
reachability + name matching. It catches "this function isn't
|
|
101
|
+
referenced by anything in `tests/`," not runtime line coverage.
|
|
102
|
+
- **`coupling` axis penalises high import fan-out**, which can be
|
|
103
|
+
legitimate in framework-style codebases. Treat the absolute number
|
|
104
|
+
as suggestive; the *delta* is what matters at PR time.
|
|
105
|
+
|
|
106
|
+
## Disabling
|
|
107
|
+
|
|
108
|
+
Just remove the workflow file. The action stores no state outside the
|
|
109
|
+
runner; no cleanup is required.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
name: 'jCodeMunch Health Radar'
|
|
2
|
+
description: >-
|
|
3
|
+
Compute a six-axis code-health radar on the PR branch and the base branch,
|
|
4
|
+
diff them, and post the result as a sticky PR comment. Suggestion-style;
|
|
5
|
+
never blocks merges.
|
|
6
|
+
author: 'jgravelle'
|
|
7
|
+
branding:
|
|
8
|
+
icon: 'activity'
|
|
9
|
+
color: 'purple'
|
|
10
|
+
|
|
11
|
+
inputs:
|
|
12
|
+
python-version:
|
|
13
|
+
description: 'Python version for the Actions runner.'
|
|
14
|
+
default: '3.11'
|
|
15
|
+
required: false
|
|
16
|
+
jcodemunch-version:
|
|
17
|
+
description: >-
|
|
18
|
+
Pin a specific jcodemunch-mcp version (e.g. 1.88.0) or 'latest'.
|
|
19
|
+
default: 'latest'
|
|
20
|
+
required: false
|
|
21
|
+
base-ref:
|
|
22
|
+
description: >-
|
|
23
|
+
Git ref to compare against (default: the PR's base branch).
|
|
24
|
+
default: ''
|
|
25
|
+
required: false
|
|
26
|
+
github-token:
|
|
27
|
+
description: 'Token for posting/editing the PR comment.'
|
|
28
|
+
default: ${{ github.token }}
|
|
29
|
+
required: false
|
|
30
|
+
|
|
31
|
+
runs:
|
|
32
|
+
using: 'composite'
|
|
33
|
+
steps:
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: ${{ inputs.python-version }}
|
|
38
|
+
|
|
39
|
+
- name: Install jcodemunch-mcp
|
|
40
|
+
shell: bash
|
|
41
|
+
run: |
|
|
42
|
+
if [ "${{ inputs.jcodemunch-version }}" = "latest" ]; then
|
|
43
|
+
pip install -U jcodemunch-mcp
|
|
44
|
+
else
|
|
45
|
+
pip install "jcodemunch-mcp==${{ inputs.jcodemunch-version }}"
|
|
46
|
+
fi
|
|
47
|
+
jcodemunch-mcp --version || true
|
|
48
|
+
|
|
49
|
+
- name: Resolve base ref
|
|
50
|
+
id: base
|
|
51
|
+
shell: bash
|
|
52
|
+
run: |
|
|
53
|
+
BASE="${{ inputs.base-ref }}"
|
|
54
|
+
if [ -z "$BASE" ]; then
|
|
55
|
+
BASE="${{ github.base_ref }}"
|
|
56
|
+
fi
|
|
57
|
+
if [ -z "$BASE" ]; then
|
|
58
|
+
echo "no base ref available — skipping (this Action is meant for pull_request triggers)"
|
|
59
|
+
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
60
|
+
else
|
|
61
|
+
echo "base=$BASE" >> "$GITHUB_OUTPUT"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
- name: Compute radar on PR branch
|
|
65
|
+
if: steps.base.outputs.skip != 'true'
|
|
66
|
+
shell: bash
|
|
67
|
+
run: |
|
|
68
|
+
jcodemunch-mcp index .
|
|
69
|
+
jcodemunch-mcp health . --radar-only > "$RUNNER_TEMP/pr_radar.json"
|
|
70
|
+
echo "PR radar:"
|
|
71
|
+
cat "$RUNNER_TEMP/pr_radar.json"
|
|
72
|
+
|
|
73
|
+
- name: Compute radar on base branch
|
|
74
|
+
if: steps.base.outputs.skip != 'true'
|
|
75
|
+
shell: bash
|
|
76
|
+
env:
|
|
77
|
+
BASE: ${{ steps.base.outputs.base }}
|
|
78
|
+
run: |
|
|
79
|
+
# Stash uncommitted state isn't needed (clean checkout in CI), but
|
|
80
|
+
# capture HEAD so we can restore it.
|
|
81
|
+
ORIG_REF=$(git rev-parse HEAD)
|
|
82
|
+
echo "$ORIG_REF" > "$RUNNER_TEMP/orig_ref"
|
|
83
|
+
|
|
84
|
+
git fetch origin "$BASE" --depth=1 || git fetch origin "$BASE"
|
|
85
|
+
git checkout "origin/$BASE" --quiet || git checkout "$BASE" --quiet
|
|
86
|
+
|
|
87
|
+
# Re-index against the base tree.
|
|
88
|
+
jcodemunch-mcp index .
|
|
89
|
+
jcodemunch-mcp health . --radar-only > "$RUNNER_TEMP/base_radar.json"
|
|
90
|
+
echo "Base radar:"
|
|
91
|
+
cat "$RUNNER_TEMP/base_radar.json"
|
|
92
|
+
|
|
93
|
+
# Restore PR HEAD so any subsequent steps see the PR tree.
|
|
94
|
+
git checkout "$ORIG_REF" --quiet
|
|
95
|
+
|
|
96
|
+
- name: Render comment markdown
|
|
97
|
+
if: steps.base.outputs.skip != 'true'
|
|
98
|
+
id: render
|
|
99
|
+
shell: bash
|
|
100
|
+
run: |
|
|
101
|
+
VERSION=$(python -c "from importlib.metadata import version; print(version('jcodemunch-mcp'))" 2>/dev/null || echo "")
|
|
102
|
+
python "${GITHUB_ACTION_PATH}/render_comment.py" \
|
|
103
|
+
--baseline "$RUNNER_TEMP/base_radar.json" \
|
|
104
|
+
--current "$RUNNER_TEMP/pr_radar.json" \
|
|
105
|
+
--version "$VERSION" \
|
|
106
|
+
> "$RUNNER_TEMP/comment.md"
|
|
107
|
+
echo "Rendered comment:"
|
|
108
|
+
cat "$RUNNER_TEMP/comment.md"
|
|
109
|
+
|
|
110
|
+
- name: Post or update sticky comment
|
|
111
|
+
# Fork-sourced pull_request events get a read-only GITHUB_TOKEN,
|
|
112
|
+
# so the comment POST returns 403 regardless of the workflow's
|
|
113
|
+
# declared `permissions:` block. For fork PRs we instead upload
|
|
114
|
+
# the rendered comment as an artifact in the calling workflow and
|
|
115
|
+
# post it from a workflow_run-triggered companion job (which DOES
|
|
116
|
+
# run in the base repo's trusted secret context). See
|
|
117
|
+
# .github/workflows/health-radar-comment.yml.
|
|
118
|
+
if: >-
|
|
119
|
+
steps.base.outputs.skip != 'true'
|
|
120
|
+
&& github.event_name == 'pull_request'
|
|
121
|
+
&& github.event.pull_request.head.repo.fork != true
|
|
122
|
+
shell: bash
|
|
123
|
+
env:
|
|
124
|
+
GH_TOKEN: ${{ inputs.github-token }}
|
|
125
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
126
|
+
REPO: ${{ github.repository }}
|
|
127
|
+
run: |
|
|
128
|
+
# Sticky-comment pattern: find existing comment by HTML marker; PATCH it
|
|
129
|
+
# if found, otherwise POST a new one. Marker is on the first line of the
|
|
130
|
+
# rendered body so a simple startswith match is robust.
|
|
131
|
+
EXISTING=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" --paginate \
|
|
132
|
+
--jq '.[] | select(.body | startswith("<!-- jcm-health-radar -->")) | .id' \
|
|
133
|
+
| head -n1)
|
|
134
|
+
|
|
135
|
+
if [ -n "$EXISTING" ]; then
|
|
136
|
+
gh api "repos/${REPO}/issues/comments/${EXISTING}" \
|
|
137
|
+
--method PATCH \
|
|
138
|
+
-F "body=@${RUNNER_TEMP}/comment.md"
|
|
139
|
+
echo "Updated existing health-radar comment ${EXISTING}."
|
|
140
|
+
else
|
|
141
|
+
gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" \
|
|
142
|
+
--method POST \
|
|
143
|
+
-F "body=@${RUNNER_TEMP}/comment.md"
|
|
144
|
+
echo "Posted new health-radar comment."
|
|
145
|
+
fi
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Render a sticky PR comment from baseline + PR radar JSON files.
|
|
2
|
+
|
|
3
|
+
Reads two radar payloads (the `radar` sub-field of `jcodemunch-mcp
|
|
4
|
+
health` output), computes the diff via the same pure helper the MCP
|
|
5
|
+
tool exposes, and prints a markdown PR comment to stdout.
|
|
6
|
+
|
|
7
|
+
Stable HTML comment marker on the first line lets the calling shell
|
|
8
|
+
script find/edit an existing comment instead of spamming the PR.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Iterable
|
|
18
|
+
|
|
19
|
+
# This script runs in the Actions runner where jcodemunch-mcp has been
|
|
20
|
+
# pip-installed, so the import works directly.
|
|
21
|
+
from jcodemunch_mcp.tools.health_radar import diff_radar
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_MARKER = "<!-- jcm-health-radar -->"
|
|
25
|
+
_GRADE_EMOJI = {"A": "🟢", "B": "🟢", "C": "🟡", "D": "🟠", "F": "🔴"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _arrow(delta) -> str:
|
|
29
|
+
if delta is None:
|
|
30
|
+
return "—"
|
|
31
|
+
if delta >= 3.0:
|
|
32
|
+
return "↑"
|
|
33
|
+
if delta <= -3.0:
|
|
34
|
+
return "↓"
|
|
35
|
+
return "·"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _signed(v) -> str:
|
|
39
|
+
if v is None:
|
|
40
|
+
return "—"
|
|
41
|
+
if v > 0:
|
|
42
|
+
return f"+{v:.1f}"
|
|
43
|
+
return f"{v:.1f}"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _radar_table(diff: dict) -> str:
|
|
47
|
+
lines = [
|
|
48
|
+
"| Axis | Baseline | PR | Δ |",
|
|
49
|
+
"|---|---:|---:|---:|",
|
|
50
|
+
]
|
|
51
|
+
for axis, d in sorted(diff["axis_deltas"].items()):
|
|
52
|
+
b = d.get("from")
|
|
53
|
+
c = d.get("to")
|
|
54
|
+
delta = d.get("delta")
|
|
55
|
+
if b is None and c is None:
|
|
56
|
+
continue
|
|
57
|
+
b_s = "—" if b is None else f"{b:.0f}"
|
|
58
|
+
c_s = "—" if c is None else f"{c:.0f}"
|
|
59
|
+
delta_s = _signed(delta)
|
|
60
|
+
emphasis = "**" if delta is not None and abs(delta) >= 3.0 else ""
|
|
61
|
+
lines.append(
|
|
62
|
+
f"| `{axis}` | {b_s} | {c_s} | {emphasis}{delta_s}{emphasis} {_arrow(delta)} |"
|
|
63
|
+
)
|
|
64
|
+
return "\n".join(lines)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _regression_detail(diff: dict, kind: str) -> str:
|
|
68
|
+
"""Render the bulleted regression / improvement axes with raw values."""
|
|
69
|
+
items = diff.get(kind, [])
|
|
70
|
+
if not items:
|
|
71
|
+
return ""
|
|
72
|
+
lines = [f"### {'Regressions' if kind == 'regressions' else 'Improvements'}"]
|
|
73
|
+
for axis in items:
|
|
74
|
+
d = diff["axis_deltas"][axis]
|
|
75
|
+
raw_from = d.get("raw_from")
|
|
76
|
+
raw_to = d.get("raw_to")
|
|
77
|
+
if raw_from is not None and raw_to is not None:
|
|
78
|
+
lines.append(f"- `{axis}`: raw {raw_from} → {raw_to}")
|
|
79
|
+
else:
|
|
80
|
+
lines.append(f"- `{axis}`: score {d.get('from')} → {d.get('to')}")
|
|
81
|
+
return "\n".join(lines)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _verdict_emoji(diff: dict) -> str:
|
|
85
|
+
if diff.get("regressions") and not diff.get("improvements"):
|
|
86
|
+
return "🔴"
|
|
87
|
+
if diff.get("improvements") and not diff.get("regressions"):
|
|
88
|
+
return "🟢"
|
|
89
|
+
if diff.get("regressions") and diff.get("improvements"):
|
|
90
|
+
return "🟡"
|
|
91
|
+
return "⚪"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def render(baseline: dict, current: dict, *, version: str = "") -> str:
|
|
95
|
+
diff = diff_radar(baseline, current)
|
|
96
|
+
|
|
97
|
+
base_grade = baseline.get("grade", "?")
|
|
98
|
+
cur_grade = current.get("grade", "?")
|
|
99
|
+
grade_line = (
|
|
100
|
+
f"{_GRADE_EMOJI.get(cur_grade, '')} **Composite:** "
|
|
101
|
+
f"{base_grade} → {cur_grade} ({_signed(diff['composite_delta'])} pts)"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
blocks: list[str] = [
|
|
105
|
+
_MARKER,
|
|
106
|
+
"## jCodeMunch Health Radar",
|
|
107
|
+
"",
|
|
108
|
+
grade_line,
|
|
109
|
+
f"{_verdict_emoji(diff)} **Verdict:** {diff['verdict']}",
|
|
110
|
+
"",
|
|
111
|
+
_radar_table(diff),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
regressions = _regression_detail(diff, "regressions")
|
|
115
|
+
if regressions:
|
|
116
|
+
blocks.append("")
|
|
117
|
+
blocks.append(regressions)
|
|
118
|
+
|
|
119
|
+
improvements = _regression_detail(diff, "improvements")
|
|
120
|
+
if improvements:
|
|
121
|
+
blocks.append("")
|
|
122
|
+
blocks.append(improvements)
|
|
123
|
+
|
|
124
|
+
blocks.append("")
|
|
125
|
+
blocks.append(
|
|
126
|
+
"_[Methodology](https://github.com/jgravelle/jcodemunch-mcp/blob/main/src/jcodemunch_mcp/tools/health_radar.py) "
|
|
127
|
+
f"· Posted by `jcodemunch-mcp{(' v' + version) if version else ''}`. "
|
|
128
|
+
"Re-runs on every push to this PR; this comment is sticky._"
|
|
129
|
+
)
|
|
130
|
+
return "\n".join(blocks).rstrip() + "\n"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _load_radar(path: Path) -> dict:
|
|
134
|
+
"""Load a radar payload from JSON. Accepts either the `radar` sub-dict
|
|
135
|
+
or the full get_repo_health response (we'll unwrap)."""
|
|
136
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
137
|
+
if isinstance(payload, dict) and "axes" in payload:
|
|
138
|
+
return payload
|
|
139
|
+
if isinstance(payload, dict) and "radar" in payload:
|
|
140
|
+
return payload["radar"]
|
|
141
|
+
raise ValueError(
|
|
142
|
+
f"{path} doesn't look like a radar payload (no `axes` field, no `radar` sub-field)"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def main(argv: list[str] | None = None) -> int:
|
|
147
|
+
parser = argparse.ArgumentParser(
|
|
148
|
+
description="Render a sticky PR comment from baseline + PR radar JSON.",
|
|
149
|
+
)
|
|
150
|
+
parser.add_argument("--baseline", type=Path, required=True,
|
|
151
|
+
help="Path to baseline radar JSON (e.g. base branch).")
|
|
152
|
+
parser.add_argument("--current", type=Path, required=True,
|
|
153
|
+
help="Path to current radar JSON (e.g. PR branch).")
|
|
154
|
+
parser.add_argument("--version", default="",
|
|
155
|
+
help="jcodemunch-mcp version string for the footer.")
|
|
156
|
+
args = parser.parse_args(argv)
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
baseline = _load_radar(args.baseline)
|
|
160
|
+
current = _load_radar(args.current)
|
|
161
|
+
except (OSError, json.JSONDecodeError, ValueError) as e:
|
|
162
|
+
print(f"error: {e}", file=sys.stderr)
|
|
163
|
+
return 2
|
|
164
|
+
|
|
165
|
+
sys.stdout.write(render(baseline, current, version=args.version))
|
|
166
|
+
return 0
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
# Security-only, batched. We do NOT run version updates (open-pull-requests-limit: 0
|
|
3
|
+
# suppresses them); Dependabot still opens PRs for actual vulnerability alerts, and the
|
|
4
|
+
# `groups` directive collapses those into a single combined PR instead of one-per-alert.
|
|
5
|
+
updates:
|
|
6
|
+
- package-ecosystem: "uv"
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: "weekly"
|
|
10
|
+
open-pull-requests-limit: 0
|
|
11
|
+
groups:
|
|
12
|
+
security-updates:
|
|
13
|
+
applies-to: security-updates
|
|
14
|
+
patterns:
|
|
15
|
+
- "*"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Companion to health-radar.yml. Fork-sourced pull_request events get a
|
|
2
|
+
# read-only GITHUB_TOKEN, so they cannot post PR comments. The radar workflow
|
|
3
|
+
# uploads the rendered comment as an artifact for fork PRs; this workflow runs
|
|
4
|
+
# on `workflow_run` (which runs in the base repo's trusted secret context with
|
|
5
|
+
# a write-capable token) and posts the sticky comment on the fork PR's behalf.
|
|
6
|
+
#
|
|
7
|
+
# Same-repo PRs are unaffected: their comment is posted inline by the action.
|
|
8
|
+
|
|
9
|
+
name: Health Radar Comment
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
workflow_run:
|
|
13
|
+
workflows: ["Health Radar"]
|
|
14
|
+
types: [completed]
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
pull-requests: write
|
|
18
|
+
contents: read
|
|
19
|
+
actions: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
comment:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
# Only act on pull_request runs (the only event Health Radar fires on).
|
|
25
|
+
if: github.event.workflow_run.event == 'pull_request'
|
|
26
|
+
steps:
|
|
27
|
+
- name: Download comment payload
|
|
28
|
+
id: download
|
|
29
|
+
uses: actions/download-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: health-radar-payload
|
|
32
|
+
run-id: ${{ github.event.workflow_run.id }}
|
|
33
|
+
github-token: ${{ github.token }}
|
|
34
|
+
path: payload
|
|
35
|
+
continue-on-error: true
|
|
36
|
+
|
|
37
|
+
- name: Skip if no payload
|
|
38
|
+
if: steps.download.outcome != 'success'
|
|
39
|
+
shell: bash
|
|
40
|
+
run: |
|
|
41
|
+
echo "No health-radar-payload artifact from run ${{ github.event.workflow_run.id }} — same-repo PR or radar failed before render. Nothing to post."
|
|
42
|
+
|
|
43
|
+
- name: Post or update sticky comment
|
|
44
|
+
if: steps.download.outcome == 'success'
|
|
45
|
+
shell: bash
|
|
46
|
+
env:
|
|
47
|
+
GH_TOKEN: ${{ github.token }}
|
|
48
|
+
REPO: ${{ github.repository }}
|
|
49
|
+
run: |
|
|
50
|
+
if [ ! -f payload/pr_number.txt ]; then
|
|
51
|
+
echo "No pr_number.txt in payload — skipping."
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
if [ ! -f payload/comment.md ]; then
|
|
55
|
+
echo "No comment.md in payload (radar likely failed before render) — skipping."
|
|
56
|
+
exit 0
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
PR_NUMBER=$(tr -d '[:space:]' < payload/pr_number.txt)
|
|
60
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
61
|
+
echo "Empty PR number in payload — skipping."
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Sticky-comment pattern: PATCH existing if present, otherwise POST.
|
|
66
|
+
EXISTING=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" --paginate \
|
|
67
|
+
--jq '.[] | select(.body | startswith("<!-- jcm-health-radar -->")) | .id' \
|
|
68
|
+
| head -n1)
|
|
69
|
+
|
|
70
|
+
if [ -n "$EXISTING" ]; then
|
|
71
|
+
gh api "repos/${REPO}/issues/comments/${EXISTING}" \
|
|
72
|
+
--method PATCH \
|
|
73
|
+
-F "body=@payload/comment.md"
|
|
74
|
+
echo "Updated existing health-radar comment ${EXISTING} on PR #${PR_NUMBER}."
|
|
75
|
+
else
|
|
76
|
+
gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" \
|
|
77
|
+
--method POST \
|
|
78
|
+
-F "body=@payload/comment.md"
|
|
79
|
+
echo "Posted new health-radar comment on PR #${PR_NUMBER}."
|
|
80
|
+
fi
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Dogfood the in-repo health-radar action on jcodemunch-mcp's own PRs.
|
|
2
|
+
# Posts a sticky PR comment with six-axis radar deltas vs the base branch.
|
|
3
|
+
|
|
4
|
+
name: Health Radar
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
types: [opened, synchronize, reopened]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
pull-requests: write
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
radar:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
# Need enough history to checkout the base branch in the action.
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- name: Run health-radar
|
|
24
|
+
uses: ./.github/actions/health-radar
|
|
25
|
+
with:
|
|
26
|
+
# Pin to the version we're shipping the action with so PRs
|
|
27
|
+
# don't accidentally regress against a never-released local
|
|
28
|
+
# change. Override per-PR if testing the action itself.
|
|
29
|
+
jcodemunch-version: '1.88.0'
|
|
30
|
+
|
|
31
|
+
# Fork PRs cannot post comments from `pull_request` context
|
|
32
|
+
# (read-only GITHUB_TOKEN). Stage the rendered comment + PR number
|
|
33
|
+
# as a workflow artifact; the companion `health-radar-comment.yml`
|
|
34
|
+
# workflow runs on `workflow_run` (trusted secret context) and
|
|
35
|
+
# posts the sticky comment on behalf of the fork PR.
|
|
36
|
+
- name: Stage comment payload (fork PRs)
|
|
37
|
+
if: always() && github.event.pull_request.head.repo.fork == true
|
|
38
|
+
shell: bash
|
|
39
|
+
run: |
|
|
40
|
+
mkdir -p "${{ runner.temp }}/radar-payload"
|
|
41
|
+
if [ -f "${{ runner.temp }}/comment.md" ]; then
|
|
42
|
+
cp "${{ runner.temp }}/comment.md" "${{ runner.temp }}/radar-payload/comment.md"
|
|
43
|
+
fi
|
|
44
|
+
echo "${{ github.event.pull_request.number }}" > "${{ runner.temp }}/radar-payload/pr_number.txt"
|
|
45
|
+
|
|
46
|
+
- name: Upload comment payload (fork PRs)
|
|
47
|
+
if: always() && github.event.pull_request.head.repo.fork == true
|
|
48
|
+
uses: actions/upload-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: health-radar-payload
|
|
51
|
+
path: ${{ runner.temp }}/radar-payload/
|
|
52
|
+
if-no-files-found: warn
|
|
53
|
+
retention-days: 1
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # Trusted Publisher (OIDC)
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v5
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v7
|
|
20
|
+
with:
|
|
21
|
+
version: "0.6.5"
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install 3.12
|
|
25
|
+
|
|
26
|
+
- name: Build dist
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Upload build artifacts
|
|
30
|
+
uses: actions/upload-artifact@v4
|
|
31
|
+
with:
|
|
32
|
+
name: dist
|
|
33
|
+
path: dist/
|
|
34
|
+
|
|
35
|
+
publish-pypi:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment: pypi
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write
|
|
41
|
+
steps:
|
|
42
|
+
- name: Download build artifacts
|
|
43
|
+
uses: actions/download-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: dist
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
- name: Publish to PyPI
|
|
49
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|