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.
Files changed (622) hide show
  1. animamunch-1.108.82/.clabot +28 -0
  2. animamunch-1.108.82/.dockerignore +14 -0
  3. animamunch-1.108.82/.github/actions/health-radar/README.md +109 -0
  4. animamunch-1.108.82/.github/actions/health-radar/action.yml +145 -0
  5. animamunch-1.108.82/.github/actions/health-radar/render_comment.py +170 -0
  6. animamunch-1.108.82/.github/dependabot.yml +15 -0
  7. animamunch-1.108.82/.github/workflows/health-radar-comment.yml +80 -0
  8. animamunch-1.108.82/.github/workflows/health-radar.yml +53 -0
  9. animamunch-1.108.82/.github/workflows/publish.yml +49 -0
  10. animamunch-1.108.82/.github/workflows/sign-release.yml +103 -0
  11. animamunch-1.108.82/.github/workflows/test.yml +75 -0
  12. animamunch-1.108.82/.gitignore +84 -0
  13. animamunch-1.108.82/AGENTS.md +81 -0
  14. animamunch-1.108.82/AGENT_HINTS.md +94 -0
  15. animamunch-1.108.82/AGENT_HOOKS.md +1239 -0
  16. animamunch-1.108.82/AGENT_INSTALL_UNIVERSAL.md +264 -0
  17. animamunch-1.108.82/ARCHITECTURE.md +801 -0
  18. animamunch-1.108.82/CHANGELOG.md +6796 -0
  19. animamunch-1.108.82/CODE_OF_CONDUCT.md +92 -0
  20. animamunch-1.108.82/CONFIGURATION.md +486 -0
  21. animamunch-1.108.82/CONTEXT_PROVIDERS.md +380 -0
  22. animamunch-1.108.82/CONTRIBUTING.md +47 -0
  23. animamunch-1.108.82/Caddyfile +26 -0
  24. animamunch-1.108.82/Dockerfile +37 -0
  25. animamunch-1.108.82/GROQ.md +256 -0
  26. animamunch-1.108.82/HEADLESS.md +149 -0
  27. animamunch-1.108.82/INSTALL_FROM_SOURCE.md +404 -0
  28. animamunch-1.108.82/LANGUAGE_SUPPORT.md +216 -0
  29. animamunch-1.108.82/LICENSE +52 -0
  30. animamunch-1.108.82/PKG-INFO +1141 -0
  31. animamunch-1.108.82/QUICKSTART.md +399 -0
  32. animamunch-1.108.82/README.md +1003 -0
  33. animamunch-1.108.82/RELEASE_RESTORE.md +83 -0
  34. animamunch-1.108.82/SECURITY.md +283 -0
  35. animamunch-1.108.82/SPEC.md +1241 -0
  36. animamunch-1.108.82/SPEC_MUNCH.md +252 -0
  37. animamunch-1.108.82/TOKEN_SAVINGS.md +159 -0
  38. animamunch-1.108.82/TROUBLESHOOTING.md +277 -0
  39. animamunch-1.108.82/TWEAKCC.md +251 -0
  40. animamunch-1.108.82/USER_GUIDE.md +1005 -0
  41. animamunch-1.108.82/badge-kit.md +202 -0
  42. animamunch-1.108.82/benchmarks/METHODOLOGY.md +169 -0
  43. animamunch-1.108.82/benchmarks/RAG_COMPARISON_NOTES.md +135 -0
  44. animamunch-1.108.82/benchmarks/README.md +95 -0
  45. animamunch-1.108.82/benchmarks/ab-test-dead-code-2026-03-18.md +91 -0
  46. animamunch-1.108.82/benchmarks/ab-test-naming-audit-2026-03-18.md +83 -0
  47. animamunch-1.108.82/benchmarks/harness/ab_v1_70_0.py +251 -0
  48. animamunch-1.108.82/benchmarks/harness/capture_schema_baseline.py +80 -0
  49. animamunch-1.108.82/benchmarks/harness/capture_token_baseline.py +72 -0
  50. animamunch-1.108.82/benchmarks/harness/run_benchmark.py +398 -0
  51. animamunch-1.108.82/benchmarks/harness/run_rag_baseline.py +925 -0
  52. animamunch-1.108.82/benchmarks/profile_backpressure.py +512 -0
  53. animamunch-1.108.82/benchmarks/profile_config_regression.py +258 -0
  54. animamunch-1.108.82/benchmarks/profile_language_filter.py +317 -0
  55. animamunch-1.108.82/benchmarks/rag_baseline_results.json +2723 -0
  56. animamunch-1.108.82/benchmarks/rag_baseline_results.md +312 -0
  57. animamunch-1.108.82/benchmarks/replay/__init__.py +6 -0
  58. animamunch-1.108.82/benchmarks/replay/fixtures/self_v1_75_0.json +68 -0
  59. animamunch-1.108.82/benchmarks/replay/metrics.py +77 -0
  60. animamunch-1.108.82/benchmarks/replay/results/self_v1_75_0-v1.75.0.json +96 -0
  61. animamunch-1.108.82/benchmarks/replay/run_replay.py +163 -0
  62. animamunch-1.108.82/benchmarks/requirements-rag-bench.txt +9 -0
  63. animamunch-1.108.82/benchmarks/results.md +140 -0
  64. animamunch-1.108.82/benchmarks/results_v1.70.0.md +84 -0
  65. animamunch-1.108.82/benchmarks/schema_baseline.json +8 -0
  66. animamunch-1.108.82/benchmarks/tasks.json +57 -0
  67. animamunch-1.108.82/benchmarks/token_baselines/README.md +50 -0
  68. animamunch-1.108.82/benchmarks/whitepaper.md +588 -0
  69. animamunch-1.108.82/cli/README.md +64 -0
  70. animamunch-1.108.82/cli/cli.py +64 -0
  71. animamunch-1.108.82/clients/ts/README.md +44 -0
  72. animamunch-1.108.82/clients/ts/decoder.ts +301 -0
  73. animamunch-1.108.82/docker-compose.yml +44 -0
  74. animamunch-1.108.82/examples/groq_validate.py +229 -0
  75. animamunch-1.108.82/examples/otel-collector/README.md +54 -0
  76. animamunch-1.108.82/examples/otel-collector/jcm-exporter.yaml +69 -0
  77. animamunch-1.108.82/jcodemunch_whitepaper.pdf +0 -0
  78. animamunch-1.108.82/munch-bench/corpus/django.yaml +81 -0
  79. animamunch-1.108.82/munch-bench/corpus/express.yaml +81 -0
  80. animamunch-1.108.82/munch-bench/corpus/fastapi.yaml +81 -0
  81. animamunch-1.108.82/munch-bench/corpus/flask.yaml +89 -0
  82. animamunch-1.108.82/munch-bench/corpus/gin.yaml +81 -0
  83. animamunch-1.108.82/munch-bench/corpus/jcodemunch.yaml +81 -0
  84. animamunch-1.108.82/munch-bench/corpus/langchain.yaml +81 -0
  85. animamunch-1.108.82/munch-bench/corpus/nextjs.yaml +81 -0
  86. animamunch-1.108.82/munch-bench/corpus/pytorch.yaml +81 -0
  87. animamunch-1.108.82/munch-bench/corpus/react.yaml +81 -0
  88. animamunch-1.108.82/munch-bench/corpus/requests.yaml +81 -0
  89. animamunch-1.108.82/munch-bench/corpus/rust_axum.yaml +81 -0
  90. animamunch-1.108.82/munch-bench/corpus/spring_boot.yaml +81 -0
  91. animamunch-1.108.82/munch-bench/corpus/vue.yaml +81 -0
  92. animamunch-1.108.82/munch-bench/leaderboard.html +195 -0
  93. animamunch-1.108.82/munch-bench/munch_bench/__init__.py +3 -0
  94. animamunch-1.108.82/munch-bench/munch_bench/cli.py +151 -0
  95. animamunch-1.108.82/munch-bench/munch_bench/corpus.py +77 -0
  96. animamunch-1.108.82/munch-bench/munch_bench/encoding_bench.py +216 -0
  97. animamunch-1.108.82/munch-bench/munch_bench/evaluate.py +298 -0
  98. animamunch-1.108.82/munch-bench/munch_bench/inference.py +203 -0
  99. animamunch-1.108.82/munch-bench/munch_bench/leaderboard.py +218 -0
  100. animamunch-1.108.82/munch-bench/munch_bench/retrieval.py +83 -0
  101. animamunch-1.108.82/munch-bench/munch_bench/runner.py +145 -0
  102. animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_express.json +777 -0
  103. animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_fastapi.json +502 -0
  104. animamunch-1.108.82/munch-bench/results/anthropic_claude-haiku-4-5_flask.json +768 -0
  105. animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_express.json +777 -0
  106. animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_fastapi.json +502 -0
  107. animamunch-1.108.82/munch-bench/results/anthropic_claude-sonnet-4-6_flask.json +768 -0
  108. animamunch-1.108.82/munch-bench/results/groq_llama-3.3-70b-versatile_2026-04-13.json +634 -0
  109. animamunch-1.108.82/munch-bench/tests/__init__.py +0 -0
  110. animamunch-1.108.82/munch-bench/tests/test_corpus.py +59 -0
  111. animamunch-1.108.82/munch-bench/tests/test_evaluate.py +80 -0
  112. animamunch-1.108.82/munch-bench/tests/test_leaderboard.py +40 -0
  113. animamunch-1.108.82/packaging/debian/build_deb.sh +179 -0
  114. animamunch-1.108.82/pyproject.toml +122 -0
  115. animamunch-1.108.82/scripts/unstable_modules_diag.py +81 -0
  116. animamunch-1.108.82/server.json +21 -0
  117. animamunch-1.108.82/speedreview/README.md +140 -0
  118. animamunch-1.108.82/speedreview/action.yml +82 -0
  119. animamunch-1.108.82/speedreview/review.py +426 -0
  120. animamunch-1.108.82/src/jcodemunch_mcp/__init__.py +8 -0
  121. animamunch-1.108.82/src/jcodemunch_mcp/__main__.py +5 -0
  122. animamunch-1.108.82/src/jcodemunch_mcp/agent_selector.py +495 -0
  123. animamunch-1.108.82/src/jcodemunch_mcp/cli/__init__.py +0 -0
  124. animamunch-1.108.82/src/jcodemunch_mcp/cli/delivery.py +119 -0
  125. animamunch-1.108.82/src/jcodemunch_mcp/cli/digest.py +111 -0
  126. animamunch-1.108.82/src/jcodemunch_mcp/cli/file_risk.py +87 -0
  127. animamunch-1.108.82/src/jcodemunch_mcp/cli/health.py +86 -0
  128. animamunch-1.108.82/src/jcodemunch_mcp/cli/hooks.py +960 -0
  129. animamunch-1.108.82/src/jcodemunch_mcp/cli/init.py +1946 -0
  130. animamunch-1.108.82/src/jcodemunch_mcp/cli/install_pack.py +266 -0
  131. animamunch-1.108.82/src/jcodemunch_mcp/cli/observatory.py +88 -0
  132. animamunch-1.108.82/src/jcodemunch_mcp/cli/receipt.py +467 -0
  133. animamunch-1.108.82/src/jcodemunch_mcp/cli/reflect.py +130 -0
  134. animamunch-1.108.82/src/jcodemunch_mcp/cli/skills.py +284 -0
  135. animamunch-1.108.82/src/jcodemunch_mcp/cli/upgrade.py +55 -0
  136. animamunch-1.108.82/src/jcodemunch_mcp/cli/whatsnew.py +188 -0
  137. animamunch-1.108.82/src/jcodemunch_mcp/config.py +2424 -0
  138. animamunch-1.108.82/src/jcodemunch_mcp/counter.py +353 -0
  139. animamunch-1.108.82/src/jcodemunch_mcp/credentials.py +227 -0
  140. animamunch-1.108.82/src/jcodemunch_mcp/embeddings/__init__.py +0 -0
  141. animamunch-1.108.82/src/jcodemunch_mcp/embeddings/local_encoder.py +368 -0
  142. animamunch-1.108.82/src/jcodemunch_mcp/encoding/__init__.py +113 -0
  143. animamunch-1.108.82/src/jcodemunch_mcp/encoding/decoder.py +36 -0
  144. animamunch-1.108.82/src/jcodemunch_mcp/encoding/format.py +296 -0
  145. animamunch-1.108.82/src/jcodemunch_mcp/encoding/gate.py +41 -0
  146. animamunch-1.108.82/src/jcodemunch_mcp/encoding/generic.py +366 -0
  147. animamunch-1.108.82/src/jcodemunch_mcp/encoding/json_passthrough.py +15 -0
  148. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schema_driven.py +256 -0
  149. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/__init__.py +14 -0
  150. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/find_importers.py +27 -0
  151. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/find_references.py +89 -0
  152. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_blast_radius.py +43 -0
  153. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_call_hierarchy.py +48 -0
  154. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_dependency_cycles.py +39 -0
  155. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_dependency_graph.py +42 -0
  156. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_file_outline.py +158 -0
  157. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_impact_preview.py +34 -0
  158. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_ranked_context.py +37 -0
  159. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_repo_outline.py +44 -0
  160. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_signal_chains.py +52 -0
  161. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/get_tectonic_map.py +52 -0
  162. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/registry.py +49 -0
  163. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_ast.py +29 -0
  164. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_symbols.py +29 -0
  165. animamunch-1.108.82/src/jcodemunch_mcp/encoding/schemas/search_text.py +129 -0
  166. animamunch-1.108.82/src/jcodemunch_mcp/enrichment/__init__.py +0 -0
  167. animamunch-1.108.82/src/jcodemunch_mcp/enrichment/lsp_bridge.py +1042 -0
  168. animamunch-1.108.82/src/jcodemunch_mcp/groq/__init__.py +1 -0
  169. animamunch-1.108.82/src/jcodemunch_mcp/groq/cli.py +219 -0
  170. animamunch-1.108.82/src/jcodemunch_mcp/groq/config.py +52 -0
  171. animamunch-1.108.82/src/jcodemunch_mcp/groq/explainer.py +460 -0
  172. animamunch-1.108.82/src/jcodemunch_mcp/groq/inference.py +79 -0
  173. animamunch-1.108.82/src/jcodemunch_mcp/groq/retriever.py +141 -0
  174. animamunch-1.108.82/src/jcodemunch_mcp/groq/voice.py +296 -0
  175. animamunch-1.108.82/src/jcodemunch_mcp/hook_event.py +213 -0
  176. animamunch-1.108.82/src/jcodemunch_mcp/org/__init__.py +11 -0
  177. animamunch-1.108.82/src/jcodemunch_mcp/org/http_routes.py +94 -0
  178. animamunch-1.108.82/src/jcodemunch_mcp/org/license.py +241 -0
  179. animamunch-1.108.82/src/jcodemunch_mcp/org/report.py +73 -0
  180. animamunch-1.108.82/src/jcodemunch_mcp/org/store.py +101 -0
  181. animamunch-1.108.82/src/jcodemunch_mcp/parser/__init__.py +23 -0
  182. animamunch-1.108.82/src/jcodemunch_mcp/parser/astro_shared.py +44 -0
  183. animamunch-1.108.82/src/jcodemunch_mcp/parser/complexity.py +111 -0
  184. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/__init__.py +27 -0
  185. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/_route_utils.py +313 -0
  186. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/base.py +253 -0
  187. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/dbt.py +269 -0
  188. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/decorator_routes.py +397 -0
  189. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/django.py +266 -0
  190. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/express.py +219 -0
  191. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/framework_profiles.py +447 -0
  192. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/git_blame.py +170 -0
  193. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/go_routers.py +159 -0
  194. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/laravel.py +826 -0
  195. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/nextjs.py +217 -0
  196. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/nuxt.py +254 -0
  197. animamunch-1.108.82/src/jcodemunch_mcp/parser/context/rails.py +293 -0
  198. animamunch-1.108.82/src/jcodemunch_mcp/parser/extractor.py +9697 -0
  199. animamunch-1.108.82/src/jcodemunch_mcp/parser/fqn.py +97 -0
  200. animamunch-1.108.82/src/jcodemunch_mcp/parser/hierarchy.py +46 -0
  201. animamunch-1.108.82/src/jcodemunch_mcp/parser/imports.py +1280 -0
  202. animamunch-1.108.82/src/jcodemunch_mcp/parser/languages.py +2200 -0
  203. animamunch-1.108.82/src/jcodemunch_mcp/parser/parse_cache.py +165 -0
  204. animamunch-1.108.82/src/jcodemunch_mcp/parser/sql_preprocessor.py +186 -0
  205. animamunch-1.108.82/src/jcodemunch_mcp/parser/symbols.py +80 -0
  206. animamunch-1.108.82/src/jcodemunch_mcp/parser/template_shared.py +182 -0
  207. animamunch-1.108.82/src/jcodemunch_mcp/path_map.py +84 -0
  208. animamunch-1.108.82/src/jcodemunch_mcp/progress.py +149 -0
  209. animamunch-1.108.82/src/jcodemunch_mcp/redact.py +252 -0
  210. animamunch-1.108.82/src/jcodemunch_mcp/reindex_state.py +328 -0
  211. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/__init__.py +1 -0
  212. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/confidence.py +175 -0
  213. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/embed_drift.py +268 -0
  214. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/freshness.py +268 -0
  215. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/regret.py +245 -0
  216. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/signal_fusion.py +307 -0
  217. animamunch-1.108.82/src/jcodemunch_mcp/retrieval/tuning.py +321 -0
  218. animamunch-1.108.82/src/jcodemunch_mcp/runtime/__init__.py +60 -0
  219. animamunch-1.108.82/src/jcodemunch_mcp/runtime/confidence.py +328 -0
  220. animamunch-1.108.82/src/jcodemunch_mcp/runtime/http_routes.py +408 -0
  221. animamunch-1.108.82/src/jcodemunch_mcp/runtime/ingest.py +365 -0
  222. animamunch-1.108.82/src/jcodemunch_mcp/runtime/otel.py +268 -0
  223. animamunch-1.108.82/src/jcodemunch_mcp/runtime/redact.py +157 -0
  224. animamunch-1.108.82/src/jcodemunch_mcp/runtime/resolve.py +133 -0
  225. animamunch-1.108.82/src/jcodemunch_mcp/runtime/sql_ingest.py +526 -0
  226. animamunch-1.108.82/src/jcodemunch_mcp/runtime/sql_log.py +429 -0
  227. animamunch-1.108.82/src/jcodemunch_mcp/runtime/stack_ingest.py +339 -0
  228. animamunch-1.108.82/src/jcodemunch_mcp/runtime/stack_log.py +481 -0
  229. animamunch-1.108.82/src/jcodemunch_mcp/secret_classifier.py +310 -0
  230. animamunch-1.108.82/src/jcodemunch_mcp/security.py +457 -0
  231. animamunch-1.108.82/src/jcodemunch_mcp/server.py +9633 -0
  232. animamunch-1.108.82/src/jcodemunch_mcp/service_installer.py +293 -0
  233. animamunch-1.108.82/src/jcodemunch_mcp/storage/__init__.py +15 -0
  234. animamunch-1.108.82/src/jcodemunch_mcp/storage/embedding_store.py +251 -0
  235. animamunch-1.108.82/src/jcodemunch_mcp/storage/git_root.py +321 -0
  236. animamunch-1.108.82/src/jcodemunch_mcp/storage/index_store.py +1073 -0
  237. animamunch-1.108.82/src/jcodemunch_mcp/storage/process_locks.py +374 -0
  238. animamunch-1.108.82/src/jcodemunch_mcp/storage/sqlite_store.py +2661 -0
  239. animamunch-1.108.82/src/jcodemunch_mcp/storage/token_tracker.py +914 -0
  240. animamunch-1.108.82/src/jcodemunch_mcp/summarizer/__init__.py +25 -0
  241. animamunch-1.108.82/src/jcodemunch_mcp/summarizer/batch_summarize.py +906 -0
  242. animamunch-1.108.82/src/jcodemunch_mcp/summarizer/file_summarize.py +89 -0
  243. animamunch-1.108.82/src/jcodemunch_mcp/tier_resolver.py +118 -0
  244. animamunch-1.108.82/src/jcodemunch_mcp/tools/__init__.py +4 -0
  245. animamunch-1.108.82/src/jcodemunch_mcp/tools/_call_graph.py +708 -0
  246. animamunch-1.108.82/src/jcodemunch_mcp/tools/_indexing_pipeline.py +410 -0
  247. animamunch-1.108.82/src/jcodemunch_mcp/tools/_utils.py +141 -0
  248. animamunch-1.108.82/src/jcodemunch_mcp/tools/analyze_perf.py +261 -0
  249. animamunch-1.108.82/src/jcodemunch_mcp/tools/assemble_task_context.py +1027 -0
  250. animamunch-1.108.82/src/jcodemunch_mcp/tools/audit_agent_config.py +464 -0
  251. animamunch-1.108.82/src/jcodemunch_mcp/tools/check_embedding_drift.py +38 -0
  252. animamunch-1.108.82/src/jcodemunch_mcp/tools/check_references.py +225 -0
  253. animamunch-1.108.82/src/jcodemunch_mcp/tools/check_rename_safe.py +114 -0
  254. animamunch-1.108.82/src/jcodemunch_mcp/tools/check_safe.py +637 -0
  255. animamunch-1.108.82/src/jcodemunch_mcp/tools/decision_context.py +213 -0
  256. animamunch-1.108.82/src/jcodemunch_mcp/tools/digest.py +394 -0
  257. animamunch-1.108.82/src/jcodemunch_mcp/tools/embed_repo.py +337 -0
  258. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_hot_paths.py +148 -0
  259. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_implementations.py +540 -0
  260. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_importers.py +356 -0
  261. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_references.py +343 -0
  262. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_similar_symbols.py +546 -0
  263. animamunch-1.108.82/src/jcodemunch_mcp/tools/find_unused_paths.py +308 -0
  264. animamunch-1.108.82/src/jcodemunch_mcp/tools/flow_edges.py +401 -0
  265. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_blast_radius.py +544 -0
  266. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_call_hierarchy.py +214 -0
  267. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_changed_symbols.py +294 -0
  268. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_churn_rate.py +176 -0
  269. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_class_hierarchy.py +160 -0
  270. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_context_bundle.py +443 -0
  271. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_coupling_metrics.py +106 -0
  272. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_cross_repo_map.py +135 -0
  273. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dead_code_v2.py +623 -0
  274. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_delivery_metrics.py +315 -0
  275. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dependency_cycles.py +130 -0
  276. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_dependency_graph.py +237 -0
  277. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_extraction_candidates.py +146 -0
  278. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_content.py +93 -0
  279. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_outline.py +211 -0
  280. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_risk.py +249 -0
  281. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_file_tree.py +159 -0
  282. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_group_contracts.py +463 -0
  283. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_hotspots.py +180 -0
  284. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_impact_preview.py +207 -0
  285. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_layer_violations.py +169 -0
  286. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_pr_risk_profile.py +630 -0
  287. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_project_intel.py +1146 -0
  288. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_ranked_context.py +569 -0
  289. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_redaction_log.py +145 -0
  290. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_related_symbols.py +148 -0
  291. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_health.py +276 -0
  292. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_map.py +220 -0
  293. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_repo_outline.py +193 -0
  294. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_runtime_coverage.py +190 -0
  295. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_session_context.py +273 -0
  296. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_signal_chains.py +554 -0
  297. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol.py +436 -0
  298. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_complexity.py +98 -0
  299. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_diff.py +122 -0
  300. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_importance.py +137 -0
  301. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_symbol_provenance.py +505 -0
  302. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_tectonic_map.py +566 -0
  303. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_untested_symbols.py +232 -0
  304. animamunch-1.108.82/src/jcodemunch_mcp/tools/get_watch_status.py +112 -0
  305. animamunch-1.108.82/src/jcodemunch_mcp/tools/health_radar.py +339 -0
  306. animamunch-1.108.82/src/jcodemunch_mcp/tools/import_runtime_signal.py +135 -0
  307. animamunch-1.108.82/src/jcodemunch_mcp/tools/index_file.py +248 -0
  308. animamunch-1.108.82/src/jcodemunch_mcp/tools/index_folder.py +2331 -0
  309. animamunch-1.108.82/src/jcodemunch_mcp/tools/index_repo.py +611 -0
  310. animamunch-1.108.82/src/jcodemunch_mcp/tools/invalidate_cache.py +79 -0
  311. animamunch-1.108.82/src/jcodemunch_mcp/tools/list_repos.py +69 -0
  312. animamunch-1.108.82/src/jcodemunch_mcp/tools/list_workspaces.py +524 -0
  313. animamunch-1.108.82/src/jcodemunch_mcp/tools/mermaid_viewer.py +169 -0
  314. animamunch-1.108.82/src/jcodemunch_mcp/tools/observatory.py +306 -0
  315. animamunch-1.108.82/src/jcodemunch_mcp/tools/observatory_render.py +440 -0
  316. animamunch-1.108.82/src/jcodemunch_mcp/tools/package_registry.py +478 -0
  317. animamunch-1.108.82/src/jcodemunch_mcp/tools/pagerank.py +101 -0
  318. animamunch-1.108.82/src/jcodemunch_mcp/tools/plan_refactoring.py +2262 -0
  319. animamunch-1.108.82/src/jcodemunch_mcp/tools/plan_turn.py +297 -0
  320. animamunch-1.108.82/src/jcodemunch_mcp/tools/register_edit.py +99 -0
  321. animamunch-1.108.82/src/jcodemunch_mcp/tools/render_diagram.py +1113 -0
  322. animamunch-1.108.82/src/jcodemunch_mcp/tools/resolve_repo.py +436 -0
  323. animamunch-1.108.82/src/jcodemunch_mcp/tools/search_ast.py +1218 -0
  324. animamunch-1.108.82/src/jcodemunch_mcp/tools/search_columns.py +174 -0
  325. animamunch-1.108.82/src/jcodemunch_mcp/tools/search_symbols.py +1586 -0
  326. animamunch-1.108.82/src/jcodemunch_mcp/tools/search_text.py +204 -0
  327. animamunch-1.108.82/src/jcodemunch_mcp/tools/session_journal.py +212 -0
  328. animamunch-1.108.82/src/jcodemunch_mcp/tools/session_state.py +330 -0
  329. animamunch-1.108.82/src/jcodemunch_mcp/tools/suggest_corrections.py +326 -0
  330. animamunch-1.108.82/src/jcodemunch_mcp/tools/suggest_queries.py +124 -0
  331. animamunch-1.108.82/src/jcodemunch_mcp/tools/summarize_repo.py +140 -0
  332. animamunch-1.108.82/src/jcodemunch_mcp/tools/tune_weights.py +72 -0
  333. animamunch-1.108.82/src/jcodemunch_mcp/tools/turn_budget.py +137 -0
  334. animamunch-1.108.82/src/jcodemunch_mcp/tools/winnow_symbols.py +349 -0
  335. animamunch-1.108.82/src/jcodemunch_mcp/version_check.py +94 -0
  336. animamunch-1.108.82/src/jcodemunch_mcp/watch_all.py +157 -0
  337. animamunch-1.108.82/src/jcodemunch_mcp/watcher.py +1298 -0
  338. animamunch-1.108.82/tests/__init__.py +25 -0
  339. animamunch-1.108.82/tests/conftest.py +161 -0
  340. animamunch-1.108.82/tests/conftest_helpers.py +62 -0
  341. animamunch-1.108.82/tests/encoding/__init__.py +0 -0
  342. animamunch-1.108.82/tests/encoding/test_dispatcher.py +168 -0
  343. animamunch-1.108.82/tests/encoding/test_format.py +65 -0
  344. animamunch-1.108.82/tests/encoding/test_generic_hardened.py +209 -0
  345. animamunch-1.108.82/tests/encoding/test_tier1_roundtrip.py +695 -0
  346. animamunch-1.108.82/tests/fixtures/al/sample.al +189 -0
  347. animamunch-1.108.82/tests/fixtures/arduino/sample.ino +49 -0
  348. animamunch-1.108.82/tests/fixtures/astro/BaseLayout.astro +47 -0
  349. animamunch-1.108.82/tests/fixtures/astro/ClientIsland.astro +49 -0
  350. animamunch-1.108.82/tests/fixtures/astro/ContentPage.astro +10 -0
  351. animamunch-1.108.82/tests/fixtures/astro/DynamicRoute.astro +40 -0
  352. animamunch-1.108.82/tests/fixtures/astro/WidgetComponent.astro +43 -0
  353. animamunch-1.108.82/tests/fixtures/astro/WithProps.astro +17 -0
  354. animamunch-1.108.82/tests/fixtures/astro/sample.astro +11 -0
  355. animamunch-1.108.82/tests/fixtures/astro/sample_bom_crlf.astro +12 -0
  356. animamunch-1.108.82/tests/fixtures/astro/sample_malformed_frontmatter.astro +10 -0
  357. animamunch-1.108.82/tests/fixtures/astro/sample_multi_script.astro +29 -0
  358. animamunch-1.108.82/tests/fixtures/blade/sample.blade.php +31 -0
  359. animamunch-1.108.82/tests/fixtures/c/sample.c +34 -0
  360. animamunch-1.108.82/tests/fixtures/cpp/sample.cpp +44 -0
  361. animamunch-1.108.82/tests/fixtures/csharp/sample.cs +49 -0
  362. animamunch-1.108.82/tests/fixtures/dart/sample.dart +38 -0
  363. animamunch-1.108.82/tests/fixtures/elixir/sample.ex +56 -0
  364. animamunch-1.108.82/tests/fixtures/go/sample.go +20 -0
  365. animamunch-1.108.82/tests/fixtures/java/Sample.java +19 -0
  366. animamunch-1.108.82/tests/fixtures/javascript/sample.js +23 -0
  367. animamunch-1.108.82/tests/fixtures/perl/sample.pl +47 -0
  368. animamunch-1.108.82/tests/fixtures/php/sample.php +53 -0
  369. animamunch-1.108.82/tests/fixtures/python/sample.py +15 -0
  370. animamunch-1.108.82/tests/fixtures/razor/Counter.razor +36 -0
  371. animamunch-1.108.82/tests/fixtures/razor/dotnet_aspnetcore_layout.cshtml +57 -0
  372. animamunch-1.108.82/tests/fixtures/razor/sample.cshtml +18 -0
  373. animamunch-1.108.82/tests/fixtures/ruby/sample.rb +46 -0
  374. animamunch-1.108.82/tests/fixtures/rust/sample.rs +19 -0
  375. animamunch-1.108.82/tests/fixtures/templates/sample.py.jinja +20 -0
  376. animamunch-1.108.82/tests/fixtures/templates/sample.ts.j2 +21 -0
  377. animamunch-1.108.82/tests/fixtures/templates/widget.ts.twig +14 -0
  378. animamunch-1.108.82/tests/fixtures/typescript/sample.ts +24 -0
  379. animamunch-1.108.82/tests/fixtures/verilog/sample.sv +53 -0
  380. animamunch-1.108.82/tests/fixtures/vhdl/sample.vhd +39 -0
  381. animamunch-1.108.82/tests/fixtures/xml/sample.xml +15 -0
  382. animamunch-1.108.82/tests/fixtures/xml/sample.xul +17 -0
  383. animamunch-1.108.82/tests/test_adaptive_languages.py +208 -0
  384. animamunch-1.108.82/tests/test_agent_selector.py +427 -0
  385. animamunch-1.108.82/tests/test_al.py +465 -0
  386. animamunch-1.108.82/tests/test_anthropic_optional.py +60 -0
  387. animamunch-1.108.82/tests/test_architecture_tools.py +354 -0
  388. animamunch-1.108.82/tests/test_arrow_functions.py +178 -0
  389. animamunch-1.108.82/tests/test_asm_language.py +433 -0
  390. animamunch-1.108.82/tests/test_assemble_task_context.py +214 -0
  391. animamunch-1.108.82/tests/test_astro.py +104 -0
  392. animamunch-1.108.82/tests/test_audit_agent_config.py +356 -0
  393. animamunch-1.108.82/tests/test_blade.py +110 -0
  394. animamunch-1.108.82/tests/test_blast_radius.py +293 -0
  395. animamunch-1.108.82/tests/test_bm25_correctness.py +322 -0
  396. animamunch-1.108.82/tests/test_branch_indexing.py +535 -0
  397. animamunch-1.108.82/tests/test_build.py +49 -0
  398. animamunch-1.108.82/tests/test_cache_mode.py +107 -0
  399. animamunch-1.108.82/tests/test_call_extraction.py +269 -0
  400. animamunch-1.108.82/tests/test_call_graph_ast.py +221 -0
  401. animamunch-1.108.82/tests/test_call_hierarchy.py +676 -0
  402. animamunch-1.108.82/tests/test_call_references_model.py +632 -0
  403. animamunch-1.108.82/tests/test_check_delete_safe.py +208 -0
  404. animamunch-1.108.82/tests/test_check_edit_safe.py +108 -0
  405. animamunch-1.108.82/tests/test_check_references.py +161 -0
  406. animamunch-1.108.82/tests/test_check_rename_safe.py +77 -0
  407. animamunch-1.108.82/tests/test_churn_rate.py +137 -0
  408. animamunch-1.108.82/tests/test_class_hierarchy.py +212 -0
  409. animamunch-1.108.82/tests/test_claude_md_policy.py +146 -0
  410. animamunch-1.108.82/tests/test_cleanup.py +119 -0
  411. animamunch-1.108.82/tests/test_cli.py +170 -0
  412. animamunch-1.108.82/tests/test_complexity.py +97 -0
  413. animamunch-1.108.82/tests/test_confidence.py +148 -0
  414. animamunch-1.108.82/tests/test_config.py +2423 -0
  415. animamunch-1.108.82/tests/test_config_set.py +111 -0
  416. animamunch-1.108.82/tests/test_config_watcher_keys.py +36 -0
  417. animamunch-1.108.82/tests/test_context_providers.py +373 -0
  418. animamunch-1.108.82/tests/test_copilot_hook.py +82 -0
  419. animamunch-1.108.82/tests/test_counter.py +185 -0
  420. animamunch-1.108.82/tests/test_credentials.py +144 -0
  421. animamunch-1.108.82/tests/test_cross_repo.py +705 -0
  422. animamunch-1.108.82/tests/test_css.py +388 -0
  423. animamunch-1.108.82/tests/test_dart_imports.py +81 -0
  424. animamunch-1.108.82/tests/test_dbt_provider.py +481 -0
  425. animamunch-1.108.82/tests/test_dead_code_v2.py +87 -0
  426. animamunch-1.108.82/tests/test_decorator_awareness.py +252 -0
  427. animamunch-1.108.82/tests/test_decorator_routes.py +317 -0
  428. animamunch-1.108.82/tests/test_deferred_summarization.py +62 -0
  429. animamunch-1.108.82/tests/test_delete_index_cli.py +68 -0
  430. animamunch-1.108.82/tests/test_delivery_metrics.py +185 -0
  431. animamunch-1.108.82/tests/test_dependency_graph_imports_alias.py +88 -0
  432. animamunch-1.108.82/tests/test_digest.py +220 -0
  433. animamunch-1.108.82/tests/test_dispatch_resolution.py +434 -0
  434. animamunch-1.108.82/tests/test_dispatch_schema_parity.py +163 -0
  435. animamunch-1.108.82/tests/test_django_provider.py +128 -0
  436. animamunch-1.108.82/tests/test_docs_config_parity.py +130 -0
  437. animamunch-1.108.82/tests/test_embed_drift.py +188 -0
  438. animamunch-1.108.82/tests/test_express_provider.py +135 -0
  439. animamunch-1.108.82/tests/test_extra_extensions.py +116 -0
  440. animamunch-1.108.82/tests/test_extraction_candidates.py +120 -0
  441. animamunch-1.108.82/tests/test_file_summaries.py +200 -0
  442. animamunch-1.108.82/tests/test_find_dead_code.py +215 -0
  443. animamunch-1.108.82/tests/test_find_implementations.py +160 -0
  444. animamunch-1.108.82/tests/test_find_importers.py +1680 -0
  445. animamunch-1.108.82/tests/test_find_references_line_numbers.py +75 -0
  446. animamunch-1.108.82/tests/test_find_similar_symbols.py +210 -0
  447. animamunch-1.108.82/tests/test_fqn.py +184 -0
  448. animamunch-1.108.82/tests/test_framework_profiles.py +123 -0
  449. animamunch-1.108.82/tests/test_freshness.py +257 -0
  450. animamunch-1.108.82/tests/test_fuzzy_search.py +220 -0
  451. animamunch-1.108.82/tests/test_gcm.py +178 -0
  452. animamunch-1.108.82/tests/test_get_changed_symbols.py +298 -0
  453. animamunch-1.108.82/tests/test_get_context_bundle.py +114 -0
  454. animamunch-1.108.82/tests/test_get_file_outline_integration.py +133 -0
  455. animamunch-1.108.82/tests/test_get_file_risk.py +96 -0
  456. animamunch-1.108.82/tests/test_get_file_tree.py +198 -0
  457. animamunch-1.108.82/tests/test_get_group_contracts.py +219 -0
  458. animamunch-1.108.82/tests/test_get_repo_map.py +142 -0
  459. animamunch-1.108.82/tests/test_get_untested_symbols.py +271 -0
  460. animamunch-1.108.82/tests/test_git_root_identity.py +542 -0
  461. animamunch-1.108.82/tests/test_git_sha_verification.py +156 -0
  462. animamunch-1.108.82/tests/test_go_routers_provider.py +165 -0
  463. animamunch-1.108.82/tests/test_groq_explainer.py +170 -0
  464. animamunch-1.108.82/tests/test_groq_voice.py +126 -0
  465. animamunch-1.108.82/tests/test_handshake_watchdog.py +72 -0
  466. animamunch-1.108.82/tests/test_hardening.py +987 -0
  467. animamunch-1.108.82/tests/test_health_radar.py +240 -0
  468. animamunch-1.108.82/tests/test_health_radar_action.py +148 -0
  469. animamunch-1.108.82/tests/test_hooks.py +775 -0
  470. animamunch-1.108.82/tests/test_hotspots.py +148 -0
  471. animamunch-1.108.82/tests/test_identity_mode.py +297 -0
  472. animamunch-1.108.82/tests/test_incremental.py +290 -0
  473. animamunch-1.108.82/tests/test_index_file.py +189 -0
  474. animamunch-1.108.82/tests/test_init.py +516 -0
  475. animamunch-1.108.82/tests/test_init_hooks_paths.py +191 -0
  476. animamunch-1.108.82/tests/test_init_minimal.py +124 -0
  477. animamunch-1.108.82/tests/test_install_copilot_hooks.py +60 -0
  478. animamunch-1.108.82/tests/test_install_pack.py +214 -0
  479. animamunch-1.108.82/tests/test_install_uninstall.py +360 -0
  480. animamunch-1.108.82/tests/test_json.py +125 -0
  481. animamunch-1.108.82/tests/test_languages.py +2457 -0
  482. animamunch-1.108.82/tests/test_laravel_provider.py +917 -0
  483. animamunch-1.108.82/tests/test_list_repos.py +33 -0
  484. animamunch-1.108.82/tests/test_local_encoder.py +359 -0
  485. animamunch-1.108.82/tests/test_local_integration.py +579 -0
  486. animamunch-1.108.82/tests/test_lsp_bridge.py +494 -0
  487. animamunch-1.108.82/tests/test_luau_language.py +139 -0
  488. animamunch-1.108.82/tests/test_meta_disclosure.py +197 -0
  489. animamunch-1.108.82/tests/test_migration.py +72 -0
  490. animamunch-1.108.82/tests/test_mtime_optimization.py +282 -0
  491. animamunch-1.108.82/tests/test_negative_evidence.py +224 -0
  492. animamunch-1.108.82/tests/test_new_languages.py +514 -0
  493. animamunch-1.108.82/tests/test_new_languages_v143.py +358 -0
  494. animamunch-1.108.82/tests/test_nextjs_provider.py +223 -0
  495. animamunch-1.108.82/tests/test_nuxt_provider.py +218 -0
  496. animamunch-1.108.82/tests/test_observatory.py +301 -0
  497. animamunch-1.108.82/tests/test_org_http.py +89 -0
  498. animamunch-1.108.82/tests/test_org_license.py +133 -0
  499. animamunch-1.108.82/tests/test_org_rollup.py +50 -0
  500. animamunch-1.108.82/tests/test_pagerank.py +296 -0
  501. animamunch-1.108.82/tests/test_parse_cache.py +141 -0
  502. animamunch-1.108.82/tests/test_parse_warnings.py +201 -0
  503. animamunch-1.108.82/tests/test_parser.py +478 -0
  504. animamunch-1.108.82/tests/test_path_map.py +256 -0
  505. animamunch-1.108.82/tests/test_perf_telemetry.py +131 -0
  506. animamunch-1.108.82/tests/test_plan_refactoring.py +1907 -0
  507. animamunch-1.108.82/tests/test_plan_turn.py +248 -0
  508. animamunch-1.108.82/tests/test_post_tool_use_hook.py +232 -0
  509. animamunch-1.108.82/tests/test_process_locks.py +277 -0
  510. animamunch-1.108.82/tests/test_progress.py +251 -0
  511. animamunch-1.108.82/tests/test_project_intel.py +810 -0
  512. animamunch-1.108.82/tests/test_prompts.py +45 -0
  513. animamunch-1.108.82/tests/test_property_based.py +229 -0
  514. animamunch-1.108.82/tests/test_provider_metadata_and_perf.py +386 -0
  515. animamunch-1.108.82/tests/test_psr4.py +213 -0
  516. animamunch-1.108.82/tests/test_pulse.py +49 -0
  517. animamunch-1.108.82/tests/test_rails_provider.py +101 -0
  518. animamunch-1.108.82/tests/test_ranking_ledger.py +220 -0
  519. animamunch-1.108.82/tests/test_rate_limit.py +147 -0
  520. animamunch-1.108.82/tests/test_razor.py +257 -0
  521. animamunch-1.108.82/tests/test_receipt.py +254 -0
  522. animamunch-1.108.82/tests/test_redact.py +136 -0
  523. animamunch-1.108.82/tests/test_register_edit.py +128 -0
  524. animamunch-1.108.82/tests/test_reindex_state.py +277 -0
  525. animamunch-1.108.82/tests/test_related_symbols.py +173 -0
  526. animamunch-1.108.82/tests/test_render_diagram.py +553 -0
  527. animamunch-1.108.82/tests/test_render_diagram_integration.py +160 -0
  528. animamunch-1.108.82/tests/test_render_diagram_viewer.py +377 -0
  529. animamunch-1.108.82/tests/test_replay_metrics.py +145 -0
  530. animamunch-1.108.82/tests/test_repo_health.py +211 -0
  531. animamunch-1.108.82/tests/test_resolve_repo.py +549 -0
  532. animamunch-1.108.82/tests/test_result_cache.py +220 -0
  533. animamunch-1.108.82/tests/test_retrieval_tools.py +423 -0
  534. animamunch-1.108.82/tests/test_route_utils.py +247 -0
  535. animamunch-1.108.82/tests/test_runtime_phase0.py +333 -0
  536. animamunch-1.108.82/tests/test_runtime_phase1.py +461 -0
  537. animamunch-1.108.82/tests/test_runtime_phase2.py +416 -0
  538. animamunch-1.108.82/tests/test_runtime_phase3.py +244 -0
  539. animamunch-1.108.82/tests/test_runtime_phase4.py +474 -0
  540. animamunch-1.108.82/tests/test_runtime_phase5.py +412 -0
  541. animamunch-1.108.82/tests/test_runtime_phase6.py +418 -0
  542. animamunch-1.108.82/tests/test_runtime_phase7.py +300 -0
  543. animamunch-1.108.82/tests/test_scala_parser.py +120 -0
  544. animamunch-1.108.82/tests/test_schema_budget.py +169 -0
  545. animamunch-1.108.82/tests/test_search_columns.py +143 -0
  546. animamunch-1.108.82/tests/test_search_perf.py +213 -0
  547. animamunch-1.108.82/tests/test_search_result_cache.py +213 -0
  548. animamunch-1.108.82/tests/test_search_symbols_defaults.py +235 -0
  549. animamunch-1.108.82/tests/test_secret_classifier.py +162 -0
  550. animamunch-1.108.82/tests/test_security.py +940 -0
  551. animamunch-1.108.82/tests/test_semantic_search.py +634 -0
  552. animamunch-1.108.82/tests/test_server.py +1485 -0
  553. animamunch-1.108.82/tests/test_session_journal.py +234 -0
  554. animamunch-1.108.82/tests/test_session_snapshot.py +283 -0
  555. animamunch-1.108.82/tests/test_session_state.py +277 -0
  556. animamunch-1.108.82/tests/test_share_savings.py +161 -0
  557. animamunch-1.108.82/tests/test_signal_fusion.py +255 -0
  558. animamunch-1.108.82/tests/test_skills.py +197 -0
  559. animamunch-1.108.82/tests/test_sql_language.py +331 -0
  560. animamunch-1.108.82/tests/test_sqlite_store.py +895 -0
  561. animamunch-1.108.82/tests/test_storage.py +658 -0
  562. animamunch-1.108.82/tests/test_streamable_http_integration.py +162 -0
  563. animamunch-1.108.82/tests/test_streamable_http_sessions.py +198 -0
  564. animamunch-1.108.82/tests/test_suggest_corrections.py +196 -0
  565. animamunch-1.108.82/tests/test_suggest_queries.py +117 -0
  566. animamunch-1.108.82/tests/test_summarize_from_docstrings.py +97 -0
  567. animamunch-1.108.82/tests/test_summarizer.py +1726 -0
  568. animamunch-1.108.82/tests/test_swift_parser.py +102 -0
  569. animamunch-1.108.82/tests/test_symbol_complexity.py +109 -0
  570. animamunch-1.108.82/tests/test_symbol_diff.py +210 -0
  571. animamunch-1.108.82/tests/test_tectonic_map.py +222 -0
  572. animamunch-1.108.82/tests/test_telemetry_db_skip.py +141 -0
  573. animamunch-1.108.82/tests/test_templates.py +262 -0
  574. animamunch-1.108.82/tests/test_tier_resolver.py +183 -0
  575. animamunch-1.108.82/tests/test_tier_runtime.py +606 -0
  576. animamunch-1.108.82/tests/test_token_budget_context.py +376 -0
  577. animamunch-1.108.82/tests/test_tool_registration.py +94 -0
  578. animamunch-1.108.82/tests/test_tools.py +1266 -0
  579. animamunch-1.108.82/tests/test_truncated_flag.py +86 -0
  580. animamunch-1.108.82/tests/test_turn_budget.py +93 -0
  581. animamunch-1.108.82/tests/test_v1_108_0.py +302 -0
  582. animamunch-1.108.82/tests/test_v1_108_2.py +173 -0
  583. animamunch-1.108.82/tests/test_v1_108_55.py +216 -0
  584. animamunch-1.108.82/tests/test_v1_108_56.py +323 -0
  585. animamunch-1.108.82/tests/test_v1_108_57.py +148 -0
  586. animamunch-1.108.82/tests/test_v1_108_58.py +210 -0
  587. animamunch-1.108.82/tests/test_v1_108_59.py +161 -0
  588. animamunch-1.108.82/tests/test_v1_108_63.py +132 -0
  589. animamunch-1.108.82/tests/test_v1_108_64.py +73 -0
  590. animamunch-1.108.82/tests/test_v1_108_70.py +272 -0
  591. animamunch-1.108.82/tests/test_v1_108_71.py +89 -0
  592. animamunch-1.108.82/tests/test_v1_108_72.py +87 -0
  593. animamunch-1.108.82/tests/test_v1_108_73.py +128 -0
  594. animamunch-1.108.82/tests/test_v1_108_74.py +68 -0
  595. animamunch-1.108.82/tests/test_v1_108_78.py +218 -0
  596. animamunch-1.108.82/tests/test_v1_108_80.py +144 -0
  597. animamunch-1.108.82/tests/test_v1_108_81.py +59 -0
  598. animamunch-1.108.82/tests/test_v1_80_10_dead_code_intra_file_calls.py +74 -0
  599. animamunch-1.108.82/tests/test_v1_80_7_dead_code_js_reexports.py +206 -0
  600. animamunch-1.108.82/tests/test_v1_80_9_lodash_class.py +200 -0
  601. animamunch-1.108.82/tests/test_version_check.py +82 -0
  602. animamunch-1.108.82/tests/test_watch_all.py +110 -0
  603. animamunch-1.108.82/tests/test_watch_claude.py +717 -0
  604. animamunch-1.108.82/tests/test_watch_once.py +86 -0
  605. animamunch-1.108.82/tests/test_watcher_dynamic.py +409 -0
  606. animamunch-1.108.82/tests/test_watcher_lock.py +907 -0
  607. animamunch-1.108.82/tests/test_watcher_memory_cache.py +600 -0
  608. animamunch-1.108.82/tests/test_watcher_serve.py +1096 -0
  609. animamunch-1.108.82/tests/test_weight_tuning.py +241 -0
  610. animamunch-1.108.82/tests/test_whatsnew.py +130 -0
  611. animamunch-1.108.82/tests/test_winnow_symbols.py +208 -0
  612. animamunch-1.108.82/tests/test_yaml_language.py +140 -0
  613. animamunch-1.108.82/uv.lock +3635 -0
  614. animamunch-1.108.82/vscode-extension/.gitignore +3 -0
  615. animamunch-1.108.82/vscode-extension/.vscodeignore +6 -0
  616. animamunch-1.108.82/vscode-extension/README.md +63 -0
  617. animamunch-1.108.82/vscode-extension/package-lock.json +55 -0
  618. animamunch-1.108.82/vscode-extension/package.json +80 -0
  619. animamunch-1.108.82/vscode-extension/src/extension.ts +118 -0
  620. animamunch-1.108.82/vscode-extension/src/riskGutter.ts +297 -0
  621. animamunch-1.108.82/vscode-extension/tsconfig.json +14 -0
  622. 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,14 @@
1
+ .git
2
+ .github
3
+ __pycache__
4
+ *.pyc
5
+ *.egg-info
6
+ dist
7
+ build
8
+ tests
9
+ benchmarks
10
+ *.pdf
11
+ .venv
12
+ .mypy_cache
13
+ .pytest_cache
14
+ node_modules
@@ -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