roam-code 12.18__tar.gz → 12.19__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 (616) hide show
  1. {roam_code-12.18/src/roam_code.egg-info → roam_code-12.19}/PKG-INFO +13 -7
  2. {roam_code-12.18 → roam_code-12.19}/README.md +12 -6
  3. {roam_code-12.18 → roam_code-12.19}/pyproject.toml +1 -1
  4. {roam_code-12.18 → roam_code-12.19}/src/roam/cli.py +2 -0
  5. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_adversarial.py +35 -35
  6. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_affected.py +10 -4
  7. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_agent_export.py +39 -23
  8. roam_code-12.19/src/roam/commands/cmd_audit.py +169 -0
  9. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_complexity.py +41 -7
  10. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_config.py +13 -12
  11. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_coverage_gaps.py +23 -8
  12. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_describe.py +32 -16
  13. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_impact.py +71 -0
  14. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_metrics.py +48 -24
  15. roam_code-12.19/src/roam/commands/cmd_orphan_imports.py +435 -0
  16. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_safe_zones.py +14 -1
  17. {roam_code-12.18 → roam_code-12.19}/src/roam/competitor_site_data.py +2 -2
  18. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp-server-card.json +4 -4
  19. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/sampling.py +10 -0
  20. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_server.py +99 -0
  21. roam_code-12.19/src/roam/observability.py +58 -0
  22. {roam_code-12.18 → roam_code-12.19/src/roam_code.egg-info}/PKG-INFO +13 -7
  23. {roam_code-12.18 → roam_code-12.19}/src/roam_code.egg-info/SOURCES.txt +3 -0
  24. {roam_code-12.18 → roam_code-12.19}/tests/test_defer_loading.py +6 -0
  25. {roam_code-12.18 → roam_code-12.19}/tests/test_mcp_server.py +8 -2
  26. {roam_code-12.18 → roam_code-12.19}/tests/test_v1216_passes_41_50.py +9 -5
  27. roam_code-12.19/tests/test_v1219_passes_91_100.py +174 -0
  28. roam_code-12.18/src/roam/commands/cmd_orphan_imports.py +0 -175
  29. {roam_code-12.18 → roam_code-12.19}/LICENSE +0 -0
  30. {roam_code-12.18 → roam_code-12.19}/setup.cfg +0 -0
  31. {roam_code-12.18 → roam_code-12.19}/src/roam/__init__.py +0 -0
  32. {roam_code-12.18 → roam_code-12.19}/src/roam/__main__.py +0 -0
  33. {roam_code-12.18 → roam_code-12.19}/src/roam/analysis/__init__.py +0 -0
  34. {roam_code-12.18 → roam_code-12.19}/src/roam/analysis/effects.py +0 -0
  35. {roam_code-12.18 → roam_code-12.19}/src/roam/analysis/taint.py +0 -0
  36. {roam_code-12.18 → roam_code-12.19}/src/roam/api.py +0 -0
  37. {roam_code-12.18 → roam_code-12.19}/src/roam/ask/__init__.py +0 -0
  38. {roam_code-12.18 → roam_code-12.19}/src/roam/ask/classifier.py +0 -0
  39. {roam_code-12.18 → roam_code-12.19}/src/roam/ask/recipes.py +0 -0
  40. {roam_code-12.18 → roam_code-12.19}/src/roam/ask/runner.py +0 -0
  41. {roam_code-12.18 → roam_code-12.19}/src/roam/ask/workflow.py +0 -0
  42. {roam_code-12.18 → roam_code-12.19}/src/roam/attest/__init__.py +0 -0
  43. {roam_code-12.18 → roam_code-12.19}/src/roam/attest/cga.py +0 -0
  44. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/__init__.py +0 -0
  45. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/base.py +0 -0
  46. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_config.py +0 -0
  47. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_django.py +0 -0
  48. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_protobuf.py +0 -0
  49. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_rest_api.py +0 -0
  50. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_salesforce.py +0 -0
  51. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/bridge_template.py +0 -0
  52. {roam_code-12.18 → roam_code-12.19}/src/roam/bridges/registry.py +0 -0
  53. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/__init__.py +0 -0
  54. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/detectors.py +0 -0
  55. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/fixes.py +0 -0
  56. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/python_idioms.py +0 -0
  57. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/smells.py +0 -0
  58. {roam_code-12.18 → roam_code-12.19}/src/roam/catalog/tasks.py +0 -0
  59. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/__init__.py +0 -0
  60. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/changed_files.py +0 -0
  61. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_adrs.py +0 -0
  62. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_affected_tests.py +0 -0
  63. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_agent_context.py +0 -0
  64. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_agent_plan.py +0 -0
  65. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ai_ratio.py +0 -0
  66. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ai_readiness.py +0 -0
  67. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_alerts.py +0 -0
  68. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_annotate.py +0 -0
  69. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_api.py +0 -0
  70. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_api_changes.py +0 -0
  71. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_api_drift.py +0 -0
  72. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ask.py +0 -0
  73. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_attest.py +0 -0
  74. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_auth_gaps.py +0 -0
  75. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_bisect.py +0 -0
  76. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_breaking.py +0 -0
  77. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_budget.py +0 -0
  78. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_bus_factor.py +0 -0
  79. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_capsule.py +0 -0
  80. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_cga.py +0 -0
  81. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_changelog.py +0 -0
  82. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_check_rules.py +0 -0
  83. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ci_setup.py +0 -0
  84. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_clean.py +0 -0
  85. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_clones.py +0 -0
  86. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_closure.py +0 -0
  87. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_clusters.py +0 -0
  88. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_codeowners.py +0 -0
  89. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_congestion.py +0 -0
  90. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_context.py +0 -0
  91. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_conventions.py +0 -0
  92. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_coupling.py +0 -0
  93. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_critique.py +0 -0
  94. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_cut.py +0 -0
  95. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_dark_matter.py +0 -0
  96. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_dashboard.py +0 -0
  97. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_dead.py +0 -0
  98. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_debt.py +0 -0
  99. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_deps.py +0 -0
  100. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_dev_profile.py +0 -0
  101. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_diagnose.py +0 -0
  102. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_diff.py +0 -0
  103. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_disambiguate.py +0 -0
  104. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_doc_staleness.py +0 -0
  105. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_docs_coverage.py +0 -0
  106. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_doctor.py +0 -0
  107. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_drift.py +0 -0
  108. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_duplicates.py +0 -0
  109. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_effects.py +0 -0
  110. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_endpoints.py +0 -0
  111. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_entry_points.py +0 -0
  112. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_eval_retrieve.py +0 -0
  113. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_exit_codes.py +0 -0
  114. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_fan.py +0 -0
  115. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_file.py +0 -0
  116. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_fingerprint.py +0 -0
  117. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_fitness.py +0 -0
  118. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_flag_dead.py +0 -0
  119. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_fleet.py +0 -0
  120. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_fn_coupling.py +0 -0
  121. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_forecast.py +0 -0
  122. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_graph_export.py +0 -0
  123. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_graph_stats.py +0 -0
  124. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_grep.py +0 -0
  125. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_guard.py +0 -0
  126. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_health.py +0 -0
  127. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_help_search.py +0 -0
  128. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_hooks.py +0 -0
  129. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_hotspots.py +0 -0
  130. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_hover.py +0 -0
  131. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_index.py +0 -0
  132. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_index_bundle.py +0 -0
  133. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_index_stats.py +0 -0
  134. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ingest_trace.py +0 -0
  135. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_init.py +0 -0
  136. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_intent.py +0 -0
  137. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_invariants.py +0 -0
  138. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_layers.py +0 -0
  139. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_map.py +0 -0
  140. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_math.py +0 -0
  141. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_mcp_setup.py +0 -0
  142. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_mcp_status.py +0 -0
  143. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_migration_safety.py +0 -0
  144. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_minimap.py +0 -0
  145. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_missing_index.py +0 -0
  146. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_module.py +0 -0
  147. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_mutate.py +0 -0
  148. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_n1.py +0 -0
  149. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_oracle.py +0 -0
  150. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_orchestrate.py +0 -0
  151. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_orphan_routes.py +0 -0
  152. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_over_fetch.py +0 -0
  153. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_owner.py +0 -0
  154. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_partition.py +0 -0
  155. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_path_coverage.py +0 -0
  156. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_patterns.py +0 -0
  157. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_plan.py +0 -0
  158. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_plan_refactor.py +0 -0
  159. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_plugins.py +0 -0
  160. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_pr_diff.py +0 -0
  161. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_pr_prep.py +0 -0
  162. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_pr_risk.py +0 -0
  163. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_pre_commit.py +0 -0
  164. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_preflight.py +0 -0
  165. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_py_modern.py +0 -0
  166. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_py_types.py +0 -0
  167. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_pytest_fixtures.py +0 -0
  168. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_recipes.py +0 -0
  169. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_recommend.py +0 -0
  170. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_relate.py +0 -0
  171. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_report.py +0 -0
  172. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_reset.py +0 -0
  173. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_retrieve.py +0 -0
  174. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_risk.py +0 -0
  175. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_rules.py +0 -0
  176. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_safe_delete.py +0 -0
  177. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_sbom.py +0 -0
  178. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_schema.py +0 -0
  179. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_search.py +0 -0
  180. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_search_semantic.py +0 -0
  181. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_secrets.py +0 -0
  182. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_semantic_diff.py +0 -0
  183. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_simulate.py +0 -0
  184. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_simulate_departure.py +0 -0
  185. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_sketch.py +0 -0
  186. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_smells.py +0 -0
  187. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_spectral.py +0 -0
  188. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_split.py +0 -0
  189. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_stats.py +0 -0
  190. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_suggest_refactoring.py +0 -0
  191. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_suggest_reviewers.py +0 -0
  192. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_supply_chain.py +0 -0
  193. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_symbol.py +0 -0
  194. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_syntax_check.py +0 -0
  195. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_taint.py +0 -0
  196. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_telemetry.py +0 -0
  197. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_test_gaps.py +0 -0
  198. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_test_impact.py +0 -0
  199. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_test_pyramid.py +0 -0
  200. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_test_scaffold.py +0 -0
  201. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_testmap.py +0 -0
  202. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_timeline.py +0 -0
  203. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_tour.py +0 -0
  204. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_trace.py +0 -0
  205. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_trends.py +0 -0
  206. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_triage.py +0 -0
  207. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_understand.py +0 -0
  208. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_uses.py +0 -0
  209. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_verify.py +0 -0
  210. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_verify_imports.py +0 -0
  211. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_version.py +0 -0
  212. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_vibe_check.py +0 -0
  213. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_visualize.py +0 -0
  214. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_vuln_map.py +0 -0
  215. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_vuln_reach.py +0 -0
  216. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_vulns.py +0 -0
  217. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_watch.py +0 -0
  218. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_weather.py +0 -0
  219. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_why.py +0 -0
  220. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_why_fail.py +0 -0
  221. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_workflow.py +0 -0
  222. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_ws.py +0 -0
  223. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/cmd_xlang.py +0 -0
  224. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/codeowners_helpers.py +0 -0
  225. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/context_helpers.py +0 -0
  226. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/gate_presets.py +0 -0
  227. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/graph_helpers.py +0 -0
  228. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/metrics_history.py +0 -0
  229. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/next_steps.py +0 -0
  230. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/resolve.py +0 -0
  231. {roam_code-12.18 → roam_code-12.19}/src/roam/commands/suppression.py +0 -0
  232. {roam_code-12.18 → roam_code-12.19}/src/roam/config.py +0 -0
  233. {roam_code-12.18 → roam_code-12.19}/src/roam/coverage_reports.py +0 -0
  234. {roam_code-12.18 → roam_code-12.19}/src/roam/critique/__init__.py +0 -0
  235. {roam_code-12.18 → roam_code-12.19}/src/roam/critique/aggregator.py +0 -0
  236. {roam_code-12.18 → roam_code-12.19}/src/roam/critique/checks.py +0 -0
  237. {roam_code-12.18 → roam_code-12.19}/src/roam/db/__init__.py +0 -0
  238. {roam_code-12.18 → roam_code-12.19}/src/roam/db/connection.py +0 -0
  239. {roam_code-12.18 → roam_code-12.19}/src/roam/db/queries.py +0 -0
  240. {roam_code-12.18 → roam_code-12.19}/src/roam/db/schema.py +0 -0
  241. {roam_code-12.18 → roam_code-12.19}/src/roam/eval/__init__.py +0 -0
  242. {roam_code-12.18 → roam_code-12.19}/src/roam/eval/harness.py +0 -0
  243. {roam_code-12.18 → roam_code-12.19}/src/roam/exit_codes.py +0 -0
  244. {roam_code-12.18 → roam_code-12.19}/src/roam/fleet/__init__.py +0 -0
  245. {roam_code-12.18 → roam_code-12.19}/src/roam/fleet/adapters.py +0 -0
  246. {roam_code-12.18 → roam_code-12.19}/src/roam/fleet/manifest.py +0 -0
  247. {roam_code-12.18 → roam_code-12.19}/src/roam/git_utils.py +0 -0
  248. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/__init__.py +0 -0
  249. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/anomaly.py +0 -0
  250. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/builder.py +0 -0
  251. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/clone_detect.py +0 -0
  252. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/clusters.py +0 -0
  253. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/cycles.py +0 -0
  254. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/dark_matter.py +0 -0
  255. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/diff.py +0 -0
  256. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/fingerprint.py +0 -0
  257. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/layers.py +0 -0
  258. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/pagerank.py +0 -0
  259. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/partition.py +0 -0
  260. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/pathfinding.py +0 -0
  261. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/propagation.py +0 -0
  262. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/simulate.py +0 -0
  263. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/spectral.py +0 -0
  264. {roam_code-12.18 → roam_code-12.19}/src/roam/graph/stats.py +0 -0
  265. {roam_code-12.18 → roam_code-12.19}/src/roam/index/__init__.py +0 -0
  266. {roam_code-12.18 → roam_code-12.19}/src/roam/index/complexity.py +0 -0
  267. {roam_code-12.18 → roam_code-12.19}/src/roam/index/discovery.py +0 -0
  268. {roam_code-12.18 → roam_code-12.19}/src/roam/index/django_post.py +0 -0
  269. {roam_code-12.18 → roam_code-12.19}/src/roam/index/file_roles.py +0 -0
  270. {roam_code-12.18 → roam_code-12.19}/src/roam/index/git_stats.py +0 -0
  271. {roam_code-12.18 → roam_code-12.19}/src/roam/index/gitignore.py +0 -0
  272. {roam_code-12.18 → roam_code-12.19}/src/roam/index/incremental.py +0 -0
  273. {roam_code-12.18 → roam_code-12.19}/src/roam/index/indexer.py +0 -0
  274. {roam_code-12.18 → roam_code-12.19}/src/roam/index/parser.py +0 -0
  275. {roam_code-12.18 → roam_code-12.19}/src/roam/index/pytest_fixtures.py +0 -0
  276. {roam_code-12.18 → roam_code-12.19}/src/roam/index/registry_dispatch.py +0 -0
  277. {roam_code-12.18 → roam_code-12.19}/src/roam/index/relations.py +0 -0
  278. {roam_code-12.18 → roam_code-12.19}/src/roam/index/symbols.py +0 -0
  279. {roam_code-12.18 → roam_code-12.19}/src/roam/index/test_conventions.py +0 -0
  280. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/__init__.py +0 -0
  281. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/apex_lang.py +0 -0
  282. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/aura_lang.py +0 -0
  283. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/base.py +0 -0
  284. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/c_lang.py +0 -0
  285. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/csharp_lang.py +0 -0
  286. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/extractor_schema.py +0 -0
  287. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/extractors/kotlin.yaml +0 -0
  288. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/foxpro_lang.py +0 -0
  289. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/generic_lang.py +0 -0
  290. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/go_lang.py +0 -0
  291. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/hcl_lang.py +0 -0
  292. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/java_lang.py +0 -0
  293. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/javascript_lang.py +0 -0
  294. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/kotlin_lang.py +0 -0
  295. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/php_lang.py +0 -0
  296. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/python_lang.py +0 -0
  297. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/query_engine.py +0 -0
  298. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/registry.py +0 -0
  299. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/ruby_lang.py +0 -0
  300. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/rust_lang.py +0 -0
  301. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/scala_lang.py +0 -0
  302. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/sfxml_lang.py +0 -0
  303. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/sql_lang.py +0 -0
  304. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/swift_lang.py +0 -0
  305. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/typescript_lang.py +0 -0
  306. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/visualforce_lang.py +0 -0
  307. {roam_code-12.18 → roam_code-12.19}/src/roam/languages/yaml_lang.py +0 -0
  308. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/__init__.py +0 -0
  309. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/completions.py +0 -0
  310. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/concurrency.py +0 -0
  311. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/progress.py +0 -0
  312. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/session.py +0 -0
  313. {roam_code-12.18 → roam_code-12.19}/src/roam/mcp_extras/watcher.py +0 -0
  314. {roam_code-12.18 → roam_code-12.19}/src/roam/output/__init__.py +0 -0
  315. {roam_code-12.18 → roam_code-12.19}/src/roam/output/confidence.py +0 -0
  316. {roam_code-12.18 → roam_code-12.19}/src/roam/output/errors.py +0 -0
  317. {roam_code-12.18 → roam_code-12.19}/src/roam/output/file_role_hints.py +0 -0
  318. {roam_code-12.18 → roam_code-12.19}/src/roam/output/formatter.py +0 -0
  319. {roam_code-12.18 → roam_code-12.19}/src/roam/output/framework_filter.py +0 -0
  320. {roam_code-12.18 → roam_code-12.19}/src/roam/output/mermaid.py +0 -0
  321. {roam_code-12.18 → roam_code-12.19}/src/roam/output/project_shape.py +0 -0
  322. {roam_code-12.18 → roam_code-12.19}/src/roam/output/sarif.py +0 -0
  323. {roam_code-12.18 → roam_code-12.19}/src/roam/output/schema_registry.py +0 -0
  324. {roam_code-12.18 → roam_code-12.19}/src/roam/plugins.py +0 -0
  325. {roam_code-12.18 → roam_code-12.19}/src/roam/refactor/__init__.py +0 -0
  326. {roam_code-12.18 → roam_code-12.19}/src/roam/refactor/codegen.py +0 -0
  327. {roam_code-12.18 → roam_code-12.19}/src/roam/refactor/transforms.py +0 -0
  328. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/__init__.py +0 -0
  329. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/learned_ranker.py +0 -0
  330. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/pipeline.py +0 -0
  331. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/rerank.py +0 -0
  332. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/seeds.py +0 -0
  333. {roam_code-12.18 → roam_code-12.19}/src/roam/retrieve/semantic.py +0 -0
  334. {roam_code-12.18 → roam_code-12.19}/src/roam/rules/__init__.py +0 -0
  335. {roam_code-12.18 → roam_code-12.19}/src/roam/rules/ast_match.py +0 -0
  336. {roam_code-12.18 → roam_code-12.19}/src/roam/rules/builtin.py +0 -0
  337. {roam_code-12.18 → roam_code-12.19}/src/roam/rules/dataflow.py +0 -0
  338. {roam_code-12.18 → roam_code-12.19}/src/roam/rules/engine.py +0 -0
  339. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/__init__.py +0 -0
  340. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/daemon.py +0 -0
  341. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/graph_backend.py +0 -0
  342. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/hotspots.py +0 -0
  343. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/lock_modes.py +0 -0
  344. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/lockmgr.py +0 -0
  345. {roam_code-12.18 → roam_code-12.19}/src/roam/runtime/trace_ingest.py +0 -0
  346. {roam_code-12.18 → roam_code-12.19}/src/roam/search/__init__.py +0 -0
  347. {roam_code-12.18 → roam_code-12.19}/src/roam/search/framework_packs.py +0 -0
  348. {roam_code-12.18 → roam_code-12.19}/src/roam/search/index_embeddings.py +0 -0
  349. {roam_code-12.18 → roam_code-12.19}/src/roam/search/onnx_embeddings.py +0 -0
  350. {roam_code-12.18 → roam_code-12.19}/src/roam/search/tfidf.py +0 -0
  351. {roam_code-12.18 → roam_code-12.19}/src/roam/security/__init__.py +0 -0
  352. {roam_code-12.18 → roam_code-12.19}/src/roam/security/aibom_extension.py +0 -0
  353. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_classifier.py +0 -0
  354. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_engine.py +0 -0
  355. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/api_error_leak.yaml +0 -0
  356. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/java_fileupload_path_traversal.yaml +0 -0
  357. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/js_insecure_jwt_decode.yaml +0 -0
  358. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/js_localstorage_secrets.yaml +0 -0
  359. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/js_prototype_pollution.yaml +0 -0
  360. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/js_ssrf.yaml +0 -0
  361. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/js_xss.yaml +0 -0
  362. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_basic.yaml +0 -0
  363. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_deserialization.yaml +0 -0
  364. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_path_traversal.yaml +0 -0
  365. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_socketio_remote_source.yaml +0 -0
  366. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_sqli.yaml +0 -0
  367. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/python_urllib_open_redirect.yaml +0 -0
  368. {roam_code-12.18 → roam_code-12.19}/src/roam/security/taint_rules/vue_v_html.yaml +0 -0
  369. {roam_code-12.18 → roam_code-12.19}/src/roam/security/vuln_reach.py +0 -0
  370. {roam_code-12.18 → roam_code-12.19}/src/roam/security/vuln_store.py +0 -0
  371. {roam_code-12.18 → roam_code-12.19}/src/roam/surface_counts.py +0 -0
  372. {roam_code-12.18 → roam_code-12.19}/src/roam/telemetry.py +0 -0
  373. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/__init__.py +0 -0
  374. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/ci/Jenkinsfile +0 -0
  375. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/ci/__init__.py +0 -0
  376. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/ci/azure-pipelines.yml +0 -0
  377. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/ci/bitbucket-pipelines.yml +0 -0
  378. {roam_code-12.18 → roam_code-12.19}/src/roam/templates/ci/gitlab-ci.yml +0 -0
  379. {roam_code-12.18 → roam_code-12.19}/src/roam/workspace/__init__.py +0 -0
  380. {roam_code-12.18 → roam_code-12.19}/src/roam/workspace/aggregator.py +0 -0
  381. {roam_code-12.18 → roam_code-12.19}/src/roam/workspace/api_scanner.py +0 -0
  382. {roam_code-12.18 → roam_code-12.19}/src/roam/workspace/config.py +0 -0
  383. {roam_code-12.18 → roam_code-12.19}/src/roam/workspace/db.py +0 -0
  384. {roam_code-12.18 → roam_code-12.19}/src/roam_code.egg-info/dependency_links.txt +0 -0
  385. {roam_code-12.18 → roam_code-12.19}/src/roam_code.egg-info/entry_points.txt +0 -0
  386. {roam_code-12.18 → roam_code-12.19}/src/roam_code.egg-info/requires.txt +0 -0
  387. {roam_code-12.18 → roam_code-12.19}/src/roam_code.egg-info/top_level.txt +0 -0
  388. {roam_code-12.18 → roam_code-12.19}/tests/test_adrs.py +0 -0
  389. {roam_code-12.18 → roam_code-12.19}/tests/test_adversarial.py +0 -0
  390. {roam_code-12.18 → roam_code-12.19}/tests/test_affected.py +0 -0
  391. {roam_code-12.18 → roam_code-12.19}/tests/test_agent_export.py +0 -0
  392. {roam_code-12.18 → roam_code-12.19}/tests/test_agent_mode.py +0 -0
  393. {roam_code-12.18 → roam_code-12.19}/tests/test_agent_plan_context.py +0 -0
  394. {roam_code-12.18 → roam_code-12.19}/tests/test_ai_ratio.py +0 -0
  395. {roam_code-12.18 → roam_code-12.19}/tests/test_ai_readiness.py +0 -0
  396. {roam_code-12.18 → roam_code-12.19}/tests/test_alerts_cmd.py +0 -0
  397. {roam_code-12.18 → roam_code-12.19}/tests/test_annotations.py +0 -0
  398. {roam_code-12.18 → roam_code-12.19}/tests/test_anomaly.py +0 -0
  399. {roam_code-12.18 → roam_code-12.19}/tests/test_api_changes.py +0 -0
  400. {roam_code-12.18 → roam_code-12.19}/tests/test_api_drift.py +0 -0
  401. {roam_code-12.18 → roam_code-12.19}/tests/test_ask.py +0 -0
  402. {roam_code-12.18 → roam_code-12.19}/tests/test_attest.py +0 -0
  403. {roam_code-12.18 → roam_code-12.19}/tests/test_auth_gaps.py +0 -0
  404. {roam_code-12.18 → roam_code-12.19}/tests/test_backend_fixes_round2.py +0 -0
  405. {roam_code-12.18 → roam_code-12.19}/tests/test_backend_fixes_round3.py +0 -0
  406. {roam_code-12.18 → roam_code-12.19}/tests/test_basic.py +0 -0
  407. {roam_code-12.18 → roam_code-12.19}/tests/test_batch_mcp.py +0 -0
  408. {roam_code-12.18 → roam_code-12.19}/tests/test_bisect.py +0 -0
  409. {roam_code-12.18 → roam_code-12.19}/tests/test_bridge_django.py +0 -0
  410. {roam_code-12.18 → roam_code-12.19}/tests/test_bridges.py +0 -0
  411. {roam_code-12.18 → roam_code-12.19}/tests/test_bridges_extended.py +0 -0
  412. {roam_code-12.18 → roam_code-12.19}/tests/test_budget.py +0 -0
  413. {roam_code-12.18 → roam_code-12.19}/tests/test_budget_flag.py +0 -0
  414. {roam_code-12.18 → roam_code-12.19}/tests/test_budget_phase2.py +0 -0
  415. {roam_code-12.18 → roam_code-12.19}/tests/test_bus_factor.py +0 -0
  416. {roam_code-12.18 → roam_code-12.19}/tests/test_capsule.py +0 -0
  417. {roam_code-12.18 → roam_code-12.19}/tests/test_cga.py +0 -0
  418. {roam_code-12.18 → roam_code-12.19}/tests/test_check_rules.py +0 -0
  419. {roam_code-12.18 → roam_code-12.19}/tests/test_ci_gate_eval.py +0 -0
  420. {roam_code-12.18 → roam_code-12.19}/tests/test_ci_sarif_guard.py +0 -0
  421. {roam_code-12.18 → roam_code-12.19}/tests/test_ci_setup.py +0 -0
  422. {roam_code-12.18 → roam_code-12.19}/tests/test_clones.py +0 -0
  423. {roam_code-12.18 → roam_code-12.19}/tests/test_closure.py +0 -0
  424. {roam_code-12.18 → roam_code-12.19}/tests/test_codeowners.py +0 -0
  425. {roam_code-12.18 → roam_code-12.19}/tests/test_commands_architecture.py +0 -0
  426. {roam_code-12.18 → roam_code-12.19}/tests/test_commands_exploration.py +0 -0
  427. {roam_code-12.18 → roam_code-12.19}/tests/test_commands_health.py +0 -0
  428. {roam_code-12.18 → roam_code-12.19}/tests/test_commands_refactoring.py +0 -0
  429. {roam_code-12.18 → roam_code-12.19}/tests/test_commands_workflow.py +0 -0
  430. {roam_code-12.18 → roam_code-12.19}/tests/test_competitor_site_data.py +0 -0
  431. {roam_code-12.18 → roam_code-12.19}/tests/test_comprehensive.py +0 -0
  432. {roam_code-12.18 → roam_code-12.19}/tests/test_config.py +0 -0
  433. {roam_code-12.18 → roam_code-12.19}/tests/test_congestion.py +0 -0
  434. {roam_code-12.18 → roam_code-12.19}/tests/test_context_propagation.py +0 -0
  435. {roam_code-12.18 → roam_code-12.19}/tests/test_conventions_cmd.py +0 -0
  436. {roam_code-12.18 → roam_code-12.19}/tests/test_coverage_gaps_cmd.py +0 -0
  437. {roam_code-12.18 → roam_code-12.19}/tests/test_coverage_ingestion.py +0 -0
  438. {roam_code-12.18 → roam_code-12.19}/tests/test_critique.py +0 -0
  439. {roam_code-12.18 → roam_code-12.19}/tests/test_cut.py +0 -0
  440. {roam_code-12.18 → roam_code-12.19}/tests/test_dark_matter.py +0 -0
  441. {roam_code-12.18 → roam_code-12.19}/tests/test_dark_matter_helpers.py +0 -0
  442. {roam_code-12.18 → roam_code-12.19}/tests/test_dashboard.py +0 -0
  443. {roam_code-12.18 → roam_code-12.19}/tests/test_dataflow_dead.py +0 -0
  444. {roam_code-12.18 → roam_code-12.19}/tests/test_dead_aging.py +0 -0
  445. {roam_code-12.18 → roam_code-12.19}/tests/test_demo_gif_asset.py +0 -0
  446. {roam_code-12.18 → roam_code-12.19}/tests/test_describe.py +0 -0
  447. {roam_code-12.18 → roam_code-12.19}/tests/test_detail_flag_hints.py +0 -0
  448. {roam_code-12.18 → roam_code-12.19}/tests/test_detector_precision.py +0 -0
  449. {roam_code-12.18 → roam_code-12.19}/tests/test_deterministic_output.py +0 -0
  450. {roam_code-12.18 → roam_code-12.19}/tests/test_dev_profile.py +0 -0
  451. {roam_code-12.18 → roam_code-12.19}/tests/test_difficulty_scoring.py +0 -0
  452. {roam_code-12.18 → roam_code-12.19}/tests/test_doc_consistency.py +0 -0
  453. {roam_code-12.18 → roam_code-12.19}/tests/test_doc_staleness.py +0 -0
  454. {roam_code-12.18 → roam_code-12.19}/tests/test_docker_assets.py +0 -0
  455. {roam_code-12.18 → roam_code-12.19}/tests/test_docs_coverage.py +0 -0
  456. {roam_code-12.18 → roam_code-12.19}/tests/test_docs_site_quality.py +0 -0
  457. {roam_code-12.18 → roam_code-12.19}/tests/test_doctor.py +0 -0
  458. {roam_code-12.18 → roam_code-12.19}/tests/test_drift.py +0 -0
  459. {roam_code-12.18 → roam_code-12.19}/tests/test_drift_by_team.py +0 -0
  460. {roam_code-12.18 → roam_code-12.19}/tests/test_duplicates.py +0 -0
  461. {roam_code-12.18 → roam_code-12.19}/tests/test_effects.py +0 -0
  462. {roam_code-12.18 → roam_code-12.19}/tests/test_effects_propagation.py +0 -0
  463. {roam_code-12.18 → roam_code-12.19}/tests/test_endpoints.py +0 -0
  464. {roam_code-12.18 → roam_code-12.19}/tests/test_entry_points_cmd.py +0 -0
  465. {roam_code-12.18 → roam_code-12.19}/tests/test_eval_retrieve.py +0 -0
  466. {roam_code-12.18 → roam_code-12.19}/tests/test_except_pass_narrow.py +0 -0
  467. {roam_code-12.18 → roam_code-12.19}/tests/test_exclude_patterns.py +0 -0
  468. {roam_code-12.18 → roam_code-12.19}/tests/test_exit_codes.py +0 -0
  469. {roam_code-12.18 → roam_code-12.19}/tests/test_extractor_grammar_drift.py +0 -0
  470. {roam_code-12.18 → roam_code-12.19}/tests/test_fallback_contracts.py +0 -0
  471. {roam_code-12.18 → roam_code-12.19}/tests/test_file_roles.py +0 -0
  472. {roam_code-12.18 → roam_code-12.19}/tests/test_fingerprint.py +0 -0
  473. {roam_code-12.18 → roam_code-12.19}/tests/test_fixes.py +0 -0
  474. {roam_code-12.18 → roam_code-12.19}/tests/test_flag_dead.py +0 -0
  475. {roam_code-12.18 → roam_code-12.19}/tests/test_fleet.py +0 -0
  476. {roam_code-12.18 → roam_code-12.19}/tests/test_fn_coupling.py +0 -0
  477. {roam_code-12.18 → roam_code-12.19}/tests/test_forecast.py +0 -0
  478. {roam_code-12.18 → roam_code-12.19}/tests/test_formatters.py +0 -0
  479. {roam_code-12.18 → roam_code-12.19}/tests/test_foxpro.py +0 -0
  480. {roam_code-12.18 → roam_code-12.19}/tests/test_framework_detection.py +0 -0
  481. {roam_code-12.18 → roam_code-12.19}/tests/test_gate_presets.py +0 -0
  482. {roam_code-12.18 → roam_code-12.19}/tests/test_git_utils.py +0 -0
  483. {roam_code-12.18 → roam_code-12.19}/tests/test_guard.py +0 -0
  484. {roam_code-12.18 → roam_code-12.19}/tests/test_health_gate.py +0 -0
  485. {roam_code-12.18 → roam_code-12.19}/tests/test_hooks.py +0 -0
  486. {roam_code-12.18 → roam_code-12.19}/tests/test_hotspots.py +0 -0
  487. {roam_code-12.18 → roam_code-12.19}/tests/test_hover.py +0 -0
  488. {roam_code-12.18 → roam_code-12.19}/tests/test_index.py +0 -0
  489. {roam_code-12.18 → roam_code-12.19}/tests/test_index_bundle.py +0 -0
  490. {roam_code-12.18 → roam_code-12.19}/tests/test_init_cmd.py +0 -0
  491. {roam_code-12.18 → roam_code-12.19}/tests/test_install_check.py +0 -0
  492. {roam_code-12.18 → roam_code-12.19}/tests/test_intent.py +0 -0
  493. {roam_code-12.18 → roam_code-12.19}/tests/test_invariants.py +0 -0
  494. {roam_code-12.18 → roam_code-12.19}/tests/test_json_contracts.py +0 -0
  495. {roam_code-12.18 → roam_code-12.19}/tests/test_json_error_envelope.py +0 -0
  496. {roam_code-12.18 → roam_code-12.19}/tests/test_kotlin_swift_extractors.py +0 -0
  497. {roam_code-12.18 → roam_code-12.19}/tests/test_language_corpus.py +0 -0
  498. {roam_code-12.18 → roam_code-12.19}/tests/test_languages.py +0 -0
  499. {roam_code-12.18 → roam_code-12.19}/tests/test_library_api.py +0 -0
  500. {roam_code-12.18 → roam_code-12.19}/tests/test_math.py +0 -0
  501. {roam_code-12.18 → roam_code-12.19}/tests/test_math_tips.py +0 -0
  502. {roam_code-12.18 → roam_code-12.19}/tests/test_mcp_extras.py +0 -0
  503. {roam_code-12.18 → roam_code-12.19}/tests/test_mcp_setup.py +0 -0
  504. {roam_code-12.18 → roam_code-12.19}/tests/test_mermaid.py +0 -0
  505. {roam_code-12.18 → roam_code-12.19}/tests/test_metrics_cmd.py +0 -0
  506. {roam_code-12.18 → roam_code-12.19}/tests/test_migration_safety.py +0 -0
  507. {roam_code-12.18 → roam_code-12.19}/tests/test_minimap.py +0 -0
  508. {roam_code-12.18 → roam_code-12.19}/tests/test_missing_index.py +0 -0
  509. {roam_code-12.18 → roam_code-12.19}/tests/test_mutate.py +0 -0
  510. {roam_code-12.18 → roam_code-12.19}/tests/test_n1.py +0 -0
  511. {roam_code-12.18 → roam_code-12.19}/tests/test_next_steps.py +0 -0
  512. {roam_code-12.18 → roam_code-12.19}/tests/test_onboard.py +0 -0
  513. {roam_code-12.18 → roam_code-12.19}/tests/test_oracle.py +0 -0
  514. {roam_code-12.18 → roam_code-12.19}/tests/test_orchestrate.py +0 -0
  515. {roam_code-12.18 → roam_code-12.19}/tests/test_orphan_routes.py +0 -0
  516. {roam_code-12.18 → roam_code-12.19}/tests/test_oss_bench_harness.py +0 -0
  517. {roam_code-12.18 → roam_code-12.19}/tests/test_over_fetch.py +0 -0
  518. {roam_code-12.18 → roam_code-12.19}/tests/test_pagerank_truncation.py +0 -0
  519. {roam_code-12.18 → roam_code-12.19}/tests/test_partition.py +0 -0
  520. {roam_code-12.18 → roam_code-12.19}/tests/test_path_coverage.py +0 -0
  521. {roam_code-12.18 → roam_code-12.19}/tests/test_patterns_cmd.py +0 -0
  522. {roam_code-12.18 → roam_code-12.19}/tests/test_performance.py +0 -0
  523. {roam_code-12.18 → roam_code-12.19}/tests/test_personalized_pagerank.py +0 -0
  524. {roam_code-12.18 → roam_code-12.19}/tests/test_plan.py +0 -0
  525. {roam_code-12.18 → roam_code-12.19}/tests/test_plugin_discovery.py +0 -0
  526. {roam_code-12.18 → roam_code-12.19}/tests/test_pr_comment_script.py +0 -0
  527. {roam_code-12.18 → roam_code-12.19}/tests/test_pr_diff.py +0 -0
  528. {roam_code-12.18 → roam_code-12.19}/tests/test_pr_risk_author.py +0 -0
  529. {roam_code-12.18 → roam_code-12.19}/tests/test_progress.py +0 -0
  530. {roam_code-12.18 → roam_code-12.19}/tests/test_progressive_disclosure.py +0 -0
  531. {roam_code-12.18 → roam_code-12.19}/tests/test_properties.py +0 -0
  532. {roam_code-12.18 → roam_code-12.19}/tests/test_pytest_fixtures.py +0 -0
  533. {roam_code-12.18 → roam_code-12.19}/tests/test_python_extractor_v2.py +0 -0
  534. {roam_code-12.18 → roam_code-12.19}/tests/test_python_idioms_e2e.py +0 -0
  535. {roam_code-12.18 → roam_code-12.19}/tests/test_python_pivot.py +0 -0
  536. {roam_code-12.18 → roam_code-12.19}/tests/test_readme_surface_consistency.py +0 -0
  537. {roam_code-12.18 → roam_code-12.19}/tests/test_realworld_feedback.py +0 -0
  538. {roam_code-12.18 → roam_code-12.19}/tests/test_refactoring_intelligence.py +0 -0
  539. {roam_code-12.18 → roam_code-12.19}/tests/test_registry_dispatch.py +0 -0
  540. {roam_code-12.18 → roam_code-12.19}/tests/test_relate.py +0 -0
  541. {roam_code-12.18 → roam_code-12.19}/tests/test_report.py +0 -0
  542. {roam_code-12.18 → roam_code-12.19}/tests/test_reset_clean.py +0 -0
  543. {roam_code-12.18 → roam_code-12.19}/tests/test_resolve.py +0 -0
  544. {roam_code-12.18 → roam_code-12.19}/tests/test_retrieve.py +0 -0
  545. {roam_code-12.18 → roam_code-12.19}/tests/test_retrieve_cross_repo.py +0 -0
  546. {roam_code-12.18 → roam_code-12.19}/tests/test_retrieve_seeds.py +0 -0
  547. {roam_code-12.18 → roam_code-12.19}/tests/test_risk.py +0 -0
  548. {roam_code-12.18 → roam_code-12.19}/tests/test_ruby.py +0 -0
  549. {roam_code-12.18 → roam_code-12.19}/tests/test_rule_profiles.py +0 -0
  550. {roam_code-12.18 → roam_code-12.19}/tests/test_rules.py +0 -0
  551. {roam_code-12.18 → roam_code-12.19}/tests/test_rules_ast_match.py +0 -0
  552. {roam_code-12.18 → roam_code-12.19}/tests/test_rules_community_pack.py +0 -0
  553. {roam_code-12.18 → roam_code-12.19}/tests/test_rules_dataflow.py +0 -0
  554. {roam_code-12.18 → roam_code-12.19}/tests/test_rules_symbol_requirements.py +0 -0
  555. {roam_code-12.18 → roam_code-12.19}/tests/test_runtime.py +0 -0
  556. {roam_code-12.18 → roam_code-12.19}/tests/test_runtime_score.py +0 -0
  557. {roam_code-12.18 → roam_code-12.19}/tests/test_salesforce.py +0 -0
  558. {roam_code-12.18 → roam_code-12.19}/tests/test_sarif_flag.py +0 -0
  559. {roam_code-12.18 → roam_code-12.19}/tests/test_sbom.py +0 -0
  560. {roam_code-12.18 → roam_code-12.19}/tests/test_scala.py +0 -0
  561. {roam_code-12.18 → roam_code-12.19}/tests/test_schema_versioning.py +0 -0
  562. {roam_code-12.18 → roam_code-12.19}/tests/test_search_explain.py +0 -0
  563. {roam_code-12.18 → roam_code-12.19}/tests/test_secrets.py +0 -0
  564. {roam_code-12.18 → roam_code-12.19}/tests/test_secrets_v2.py +0 -0
  565. {roam_code-12.18 → roam_code-12.19}/tests/test_semantic_diff.py +0 -0
  566. {roam_code-12.18 → roam_code-12.19}/tests/test_semantic_onnx.py +0 -0
  567. {roam_code-12.18 → roam_code-12.19}/tests/test_semantic_search.py +0 -0
  568. {roam_code-12.18 → roam_code-12.19}/tests/test_simulate.py +0 -0
  569. {roam_code-12.18 → roam_code-12.19}/tests/test_simulate_departure.py +0 -0
  570. {roam_code-12.18 → roam_code-12.19}/tests/test_sketch.py +0 -0
  571. {roam_code-12.18 → roam_code-12.19}/tests/test_smells.py +0 -0
  572. {roam_code-12.18 → roam_code-12.19}/tests/test_smoke.py +0 -0
  573. {roam_code-12.18 → roam_code-12.19}/tests/test_sna_metrics.py +0 -0
  574. {roam_code-12.18 → roam_code-12.19}/tests/test_spectral.py +0 -0
  575. {roam_code-12.18 → roam_code-12.19}/tests/test_split_cmd.py +0 -0
  576. {roam_code-12.18 → roam_code-12.19}/tests/test_sql.py +0 -0
  577. {roam_code-12.18 → roam_code-12.19}/tests/test_suggest_reviewers.py +0 -0
  578. {roam_code-12.18 → roam_code-12.19}/tests/test_supply_chain.py +0 -0
  579. {roam_code-12.18 → roam_code-12.19}/tests/test_surface_counts.py +0 -0
  580. {roam_code-12.18 → roam_code-12.19}/tests/test_syntax_check.py +0 -0
  581. {roam_code-12.18 → roam_code-12.19}/tests/test_taint.py +0 -0
  582. {roam_code-12.18 → roam_code-12.19}/tests/test_taint_analysis.py +0 -0
  583. {roam_code-12.18 → roam_code-12.19}/tests/test_taint_classifier.py +0 -0
  584. {roam_code-12.18 → roam_code-12.19}/tests/test_taint_intraprocedural.py +0 -0
  585. {roam_code-12.18 → roam_code-12.19}/tests/test_test_conventions.py +0 -0
  586. {roam_code-12.18 → roam_code-12.19}/tests/test_test_gaps.py +0 -0
  587. {roam_code-12.18 → roam_code-12.19}/tests/test_test_scaffold.py +0 -0
  588. {roam_code-12.18 → roam_code-12.19}/tests/test_testmap.py +0 -0
  589. {roam_code-12.18 → roam_code-12.19}/tests/test_top_flag_consistency.py +0 -0
  590. {roam_code-12.18 → roam_code-12.19}/tests/test_tour_cmd.py +0 -0
  591. {roam_code-12.18 → roam_code-12.19}/tests/test_trends.py +0 -0
  592. {roam_code-12.18 → roam_code-12.19}/tests/test_trends_cohort.py +0 -0
  593. {roam_code-12.18 → roam_code-12.19}/tests/test_triage.py +0 -0
  594. {roam_code-12.18 → roam_code-12.19}/tests/test_uses_cmd.py +0 -0
  595. {roam_code-12.18 → roam_code-12.19}/tests/test_v1215_passes.py +0 -0
  596. {roam_code-12.18 → roam_code-12.19}/tests/test_v1216_passes.py +0 -0
  597. {roam_code-12.18 → roam_code-12.19}/tests/test_v1216_passes_51_60.py +0 -0
  598. {roam_code-12.18 → roam_code-12.19}/tests/test_v1217_passes_61_80.py +0 -0
  599. {roam_code-12.18 → roam_code-12.19}/tests/test_v1218_passes_81_90.py +0 -0
  600. {roam_code-12.18 → roam_code-12.19}/tests/test_v12_2.py +0 -0
  601. {roam_code-12.18 → roam_code-12.19}/tests/test_v6_features.py +0 -0
  602. {roam_code-12.18 → roam_code-12.19}/tests/test_v71_features.py +0 -0
  603. {roam_code-12.18 → roam_code-12.19}/tests/test_v7_features.py +0 -0
  604. {roam_code-12.18 → roam_code-12.19}/tests/test_v82_features.py +0 -0
  605. {roam_code-12.18 → roam_code-12.19}/tests/test_verify.py +0 -0
  606. {roam_code-12.18 → roam_code-12.19}/tests/test_verify_imports.py +0 -0
  607. {roam_code-12.18 → roam_code-12.19}/tests/test_vibe_check.py +0 -0
  608. {roam_code-12.18 → roam_code-12.19}/tests/test_visualize.py +0 -0
  609. {roam_code-12.18 → roam_code-12.19}/tests/test_vuln.py +0 -0
  610. {roam_code-12.18 → roam_code-12.19}/tests/test_vulns_cmd.py +0 -0
  611. {roam_code-12.18 → roam_code-12.19}/tests/test_watch.py +0 -0
  612. {roam_code-12.18 → roam_code-12.19}/tests/test_why.py +0 -0
  613. {roam_code-12.18 → roam_code-12.19}/tests/test_workspace.py +0 -0
  614. {roam_code-12.18 → roam_code-12.19}/tests/test_ws_resolve_fixes.py +0 -0
  615. {roam_code-12.18 → roam_code-12.19}/tests/test_xlang.py +0 -0
  616. {roam_code-12.18 → roam_code-12.19}/tests/test_yaml_hcl.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roam-code
3
- Version: 12.18
3
+ Version: 12.19
4
4
  Summary: Instant codebase comprehension for AI coding agents
5
5
  Author: CosmoHac
6
6
  License-Expression: MIT
@@ -62,9 +62,9 @@ Dynamic: license-file
62
62
 
63
63
  **Architectural sight for AI coding agents — before they edit.**
64
64
 
65
- A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 172 specialised commands are advanced surface for specialised workflows.
65
+ A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 173 specialised commands are advanced surface for specialised workflows.
66
66
 
67
- *177 commands · 123 MCP tools · 27 languages · 100% local · zero API keys*
67
+ *178 commands · 128 MCP tools · 27 languages · 100% local · zero API keys*
68
68
 
69
69
  [![PyPI version](https://img.shields.io/pypi/v/roam-code?style=flat-square&color=blue)](https://pypi.org/project/roam-code/)
70
70
  [![GitHub stars](https://img.shields.io/github/stars/Cranot/roam-code?style=flat-square)](https://github.com/Cranot/roam-code/stargazers)
@@ -156,7 +156,7 @@ $ roam diff # blast radius of uncommitted changes
156
156
  - **`personalized_pagerank()`** in `graph/pagerank.py`: NetworkX `personalization=` wrapper with empty-seed fallback to global PR; biases ranking toward query-relevant nodes for the retrieve reranker.
157
157
  - **`.roam/config.toml`** (new): zero-dep TOML loader (stdlib `tomllib` → `tomli` → in-tree subset parser). Tunable retrieve weights (`alpha`/`beta`/`gamma`/`delta`/`epsilon`), `tokens_per_line`, `lexical_baseline`, `first_stage_token_cap`, `default_budget`, `default_k`, `default_rerank`.
158
158
  - **DX corrections from dogfood pass**: `roam --detail <cmd>` is the canonical group-level flag; misleading "use --detail" hints in 7 commands rewritten to point users at `roam --detail <cmd>`. `--top N` aliased on `complexity`/`algo`/`rules` (`--top 0` means unlimited on `rules`). `roam fingerprint` no longer refuses graphs ≥5,000 symbols (new soft-warn threshold 20k, hard cap 100k).
159
- - **177 CLI commands, 123 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
159
+ - **177 CLI commands, 128 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
160
160
 
161
161
  ## What's New in v11
162
162
 
@@ -327,7 +327,7 @@ roam health
327
327
 
328
328
  ## Commands
329
329
 
330
- **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 172 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **177 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
330
+ **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 173 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **178 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
331
331
 
332
332
  <details>
333
333
  <summary><strong>Full command reference</strong></summary>
@@ -375,6 +375,7 @@ roam health
375
375
  | `roam api [--scope <dir>]` | List the public API surface (exported public symbols + signatures) |
376
376
  | `roam exit-codes` | List every roam exit code with its meaning |
377
377
  | `roam version [--check]` | Show installed version; with `--check` also queries PyPI for newer releases |
378
+ | `roam audit [--brief]` | One-shot AI Agent Readiness Audit — chains health + debt + dead + risk + test-pyramid + api into a single envelope |
378
379
  | `roam disambiguate <name>` | List every symbol matching the name with file/line/kind/signature/docstring snippet to pick the right one |
379
380
  | `roam pre-commit [--install\|--print]` | Install or preview a roam-critique git pre-commit hook |
380
381
  | `roam mcp-status` | MCP server health: preset, registered tools, backpressure limits, cache entries, watcher state |
@@ -992,7 +993,7 @@ ROAM_MCP_LITE=0 roam mcp
992
993
  Core preset tools: `roam_affected_tests`, `roam_batch_get`, `roam_batch_search`, `roam_complete`, `roam_complexity_report`, `roam_context`, `roam_dead_code`, `roam_deps`, `roam_diagnose`, `roam_diagnose_issue`, `roam_diff`, `roam_expand_toolset`, `roam_explore`, `roam_file_info`, `roam_health`, `roam_impact`, `roam_pr_risk`, `roam_preflight`, `roam_prepare_change`, `roam_review_change`, `roam_search_symbol`, `roam_syntax_check`, `roam_trace`, `roam_understand`, `roam_uses`.
993
994
 
994
995
  <details>
995
- <summary><strong>MCP tool list (all 123)</strong></summary>
996
+ <summary><strong>MCP tool list (all 128)</strong></summary>
996
997
 
997
998
  | Tool | Description |
998
999
  |------|-------------|
@@ -1116,6 +1117,11 @@ Core preset tools: `roam_affected_tests`, `roam_batch_get`, `roam_batch_search`,
1116
1117
  | `roam_reset` | Reset the roam index and cached data |
1117
1118
  | `roam_clean` | Remove stale or orphaned index entries |
1118
1119
  | `roam_catalog` | Machine-readable list of every registered MCP tool with capability flags (read_only / destructive / core) |
1120
+ | `roam_alerts` | Active health alerts: thresholds breached on tangle, complexity, churn, or coverage |
1121
+ | `roam_timeline` | Chronological commits that touched the file owning a symbol |
1122
+ | `roam_test_impact` | Tests transitively reachable from changed symbols (sharper than affected_tests) |
1123
+ | `roam_disambiguate` | List every symbol matching a name with file/line/kind/PageRank — pick the right overload |
1124
+ | `roam_why_fail` | Triage a failing test/symbol: recently-changed reachable symbols ranked by recency |
1119
1125
  | `roam_batch_search` | Batch symbol search: run multiple pattern queries in a single call |
1120
1126
  | `roam_batch_get` | Batch context retrieval: fetch multiple symbols/files in a single call |
1121
1127
  | `roam_dev_profile` | Developer productivity profile: commit patterns, specialization, and impact |
@@ -1728,7 +1734,7 @@ Optional: Local semantic ONNX stack (`numpy`, `onnxruntime`, `tokenizers`) via `
1728
1734
  ### Shipped
1729
1735
 
1730
1736
  - [x] MCP v2 agent surface: in-process execution, compound operations, presets, schemas, annotations, and compatibility profiles.
1731
- - [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 123 MCP tools.
1737
+ - [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 128 MCP tools.
1732
1738
  - [x] CI hardening: composite action, changed-only mode, trend-aware gates, sticky PR updater, and SARIF guardrails.
1733
1739
  - [x] Performance foundation: FTS5/BM25 search, O(changed) incremental indexing, DB/index optimizations.
1734
1740
  - [x] Agent governance suite: `vibe-check`, `ai-readiness`, `verify`, `ai-ratio`, `duplicates`, advanced `algo` scoring/SARIF.
@@ -4,9 +4,9 @@
4
4
 
5
5
  **Architectural sight for AI coding agents — before they edit.**
6
6
 
7
- A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 172 specialised commands are advanced surface for specialised workflows.
7
+ A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 173 specialised commands are advanced surface for specialised workflows.
8
8
 
9
- *177 commands · 123 MCP tools · 27 languages · 100% local · zero API keys*
9
+ *178 commands · 128 MCP tools · 27 languages · 100% local · zero API keys*
10
10
 
11
11
  [![PyPI version](https://img.shields.io/pypi/v/roam-code?style=flat-square&color=blue)](https://pypi.org/project/roam-code/)
12
12
  [![GitHub stars](https://img.shields.io/github/stars/Cranot/roam-code?style=flat-square)](https://github.com/Cranot/roam-code/stargazers)
@@ -98,7 +98,7 @@ $ roam diff # blast radius of uncommitted changes
98
98
  - **`personalized_pagerank()`** in `graph/pagerank.py`: NetworkX `personalization=` wrapper with empty-seed fallback to global PR; biases ranking toward query-relevant nodes for the retrieve reranker.
99
99
  - **`.roam/config.toml`** (new): zero-dep TOML loader (stdlib `tomllib` → `tomli` → in-tree subset parser). Tunable retrieve weights (`alpha`/`beta`/`gamma`/`delta`/`epsilon`), `tokens_per_line`, `lexical_baseline`, `first_stage_token_cap`, `default_budget`, `default_k`, `default_rerank`.
100
100
  - **DX corrections from dogfood pass**: `roam --detail <cmd>` is the canonical group-level flag; misleading "use --detail" hints in 7 commands rewritten to point users at `roam --detail <cmd>`. `--top N` aliased on `complexity`/`algo`/`rules` (`--top 0` means unlimited on `rules`). `roam fingerprint` no longer refuses graphs ≥5,000 symbols (new soft-warn threshold 20k, hard cap 100k).
101
- - **177 CLI commands, 123 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
101
+ - **177 CLI commands, 128 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
102
102
 
103
103
  ## What's New in v11
104
104
 
@@ -269,7 +269,7 @@ roam health
269
269
 
270
270
  ## Commands
271
271
 
272
- **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 172 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **177 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
272
+ **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 173 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **178 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
273
273
 
274
274
  <details>
275
275
  <summary><strong>Full command reference</strong></summary>
@@ -317,6 +317,7 @@ roam health
317
317
  | `roam api [--scope <dir>]` | List the public API surface (exported public symbols + signatures) |
318
318
  | `roam exit-codes` | List every roam exit code with its meaning |
319
319
  | `roam version [--check]` | Show installed version; with `--check` also queries PyPI for newer releases |
320
+ | `roam audit [--brief]` | One-shot AI Agent Readiness Audit — chains health + debt + dead + risk + test-pyramid + api into a single envelope |
320
321
  | `roam disambiguate <name>` | List every symbol matching the name with file/line/kind/signature/docstring snippet to pick the right one |
321
322
  | `roam pre-commit [--install\|--print]` | Install or preview a roam-critique git pre-commit hook |
322
323
  | `roam mcp-status` | MCP server health: preset, registered tools, backpressure limits, cache entries, watcher state |
@@ -934,7 +935,7 @@ ROAM_MCP_LITE=0 roam mcp
934
935
  Core preset tools: `roam_affected_tests`, `roam_batch_get`, `roam_batch_search`, `roam_complete`, `roam_complexity_report`, `roam_context`, `roam_dead_code`, `roam_deps`, `roam_diagnose`, `roam_diagnose_issue`, `roam_diff`, `roam_expand_toolset`, `roam_explore`, `roam_file_info`, `roam_health`, `roam_impact`, `roam_pr_risk`, `roam_preflight`, `roam_prepare_change`, `roam_review_change`, `roam_search_symbol`, `roam_syntax_check`, `roam_trace`, `roam_understand`, `roam_uses`.
935
936
 
936
937
  <details>
937
- <summary><strong>MCP tool list (all 123)</strong></summary>
938
+ <summary><strong>MCP tool list (all 128)</strong></summary>
938
939
 
939
940
  | Tool | Description |
940
941
  |------|-------------|
@@ -1058,6 +1059,11 @@ Core preset tools: `roam_affected_tests`, `roam_batch_get`, `roam_batch_search`,
1058
1059
  | `roam_reset` | Reset the roam index and cached data |
1059
1060
  | `roam_clean` | Remove stale or orphaned index entries |
1060
1061
  | `roam_catalog` | Machine-readable list of every registered MCP tool with capability flags (read_only / destructive / core) |
1062
+ | `roam_alerts` | Active health alerts: thresholds breached on tangle, complexity, churn, or coverage |
1063
+ | `roam_timeline` | Chronological commits that touched the file owning a symbol |
1064
+ | `roam_test_impact` | Tests transitively reachable from changed symbols (sharper than affected_tests) |
1065
+ | `roam_disambiguate` | List every symbol matching a name with file/line/kind/PageRank — pick the right overload |
1066
+ | `roam_why_fail` | Triage a failing test/symbol: recently-changed reachable symbols ranked by recency |
1061
1067
  | `roam_batch_search` | Batch symbol search: run multiple pattern queries in a single call |
1062
1068
  | `roam_batch_get` | Batch context retrieval: fetch multiple symbols/files in a single call |
1063
1069
  | `roam_dev_profile` | Developer productivity profile: commit patterns, specialization, and impact |
@@ -1670,7 +1676,7 @@ Optional: Local semantic ONNX stack (`numpy`, `onnxruntime`, `tokenizers`) via `
1670
1676
  ### Shipped
1671
1677
 
1672
1678
  - [x] MCP v2 agent surface: in-process execution, compound operations, presets, schemas, annotations, and compatibility profiles.
1673
- - [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 123 MCP tools.
1679
+ - [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 128 MCP tools.
1674
1680
  - [x] CI hardening: composite action, changed-only mode, trend-aware gates, sticky PR updater, and SARIF guardrails.
1675
1681
  - [x] Performance foundation: FTS5/BM25 search, O(changed) incremental indexing, DB/index optimizations.
1676
1682
  - [x] Agent governance suite: `vibe-check`, `ai-readiness`, `verify`, `ai-ratio`, `duplicates`, advanced `algo` scoring/SARIF.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "roam-code"
7
- version = "12.18"
7
+ version = "12.19"
8
8
  description = "Instant codebase comprehension for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -127,6 +127,7 @@ _COMMANDS = {
127
127
  "exit-codes": ("roam.commands.cmd_exit_codes", "exit_codes"),
128
128
  "version": ("roam.commands.cmd_version", "version"),
129
129
  "disambiguate": ("roam.commands.cmd_disambiguate", "disambiguate"),
130
+ "audit": ("roam.commands.cmd_audit", "audit"),
130
131
  "pre-commit": ("roam.commands.cmd_pre_commit", "pre_commit"),
131
132
  "mcp-status": ("roam.commands.cmd_mcp_status", "mcp_status"),
132
133
  "test-impact": ("roam.commands.cmd_test_impact", "test_impact"),
@@ -245,6 +246,7 @@ _CATEGORIES = {
245
246
  "mcp-status",
246
247
  "ci-setup",
247
248
  "adrs",
249
+ "audit",
248
250
  "changelog",
249
251
  "exit-codes",
250
252
  "help-search",
@@ -12,7 +12,7 @@ import click
12
12
 
13
13
  from roam.commands.changed_files import get_changed_files, resolve_changed_to_db
14
14
  from roam.commands.resolve import ensure_index
15
- from roam.db.connection import find_project_root, open_db
15
+ from roam.db.connection import batched_in, find_project_root, open_db
16
16
  from roam.output.formatter import abbrev_kind, json_envelope, loc, to_json
17
17
 
18
18
  # ---------------------------------------------------------------------------
@@ -308,28 +308,30 @@ def _check_cross_cluster(conn, changed_sym_ids):
308
308
 
309
309
 
310
310
  def _check_orphaned_symbols(conn, changed_sym_ids):
311
- """Check for symbols in changed files with zero incoming edges."""
311
+ """Check for symbols in changed files with zero incoming edges.
312
+
313
+ Pass 94 — single batched query for in-degree + symbol metadata
314
+ instead of two queries per changed symbol.
315
+ """
312
316
  challenges = []
313
317
  if not changed_sym_ids:
314
318
  return challenges
315
319
 
316
- for sid in changed_sym_ids:
317
- try:
318
- row = conn.execute("SELECT COUNT(*) as cnt FROM edges WHERE target_id = ?", (sid,)).fetchone()
319
- except Exception:
320
- continue
321
- if not row or row["cnt"] != 0:
322
- continue
320
+ sid_list = list(changed_sym_ids)
321
+ # One query per batch instead of two queries per symbol.
322
+ rows = batched_in(
323
+ conn,
324
+ "SELECT s.id, s.name, s.kind, f.path AS file_path, s.line_start, "
325
+ " (SELECT COUNT(*) FROM edges WHERE target_id = s.id) AS in_degree "
326
+ " FROM symbols s JOIN files f ON s.file_id = f.id "
327
+ " WHERE s.id IN ({ph})",
328
+ sid_list,
329
+ )
330
+ sym_by_id = {r["id"]: r for r in rows if r["in_degree"] == 0}
323
331
 
324
- try:
325
- sym = conn.execute(
326
- "SELECT s.name, s.kind, f.path as file_path, s.line_start "
327
- "FROM symbols s JOIN files f ON s.file_id = f.id WHERE s.id = ?",
328
- (sid,),
329
- ).fetchone()
330
- except Exception:
331
- continue
332
- if not sym:
332
+ for sid in changed_sym_ids:
333
+ sym = sym_by_id.get(sid)
334
+ if sym is None:
333
335
  continue
334
336
 
335
337
  # Only flag substantive symbols
@@ -371,25 +373,23 @@ def _check_high_fan_out(conn, changed_sym_ids):
371
373
 
372
374
  _FAN_OUT_THRESHOLD = 10
373
375
 
374
- for sid in changed_sym_ids:
375
- try:
376
- row = conn.execute("SELECT COUNT(*) as cnt FROM edges WHERE source_id = ?", (sid,)).fetchone()
377
- except Exception:
378
- continue
379
- if not row or row["cnt"] <= _FAN_OUT_THRESHOLD:
380
- continue
376
+ # Pass 94 — single batched query for fan-out + metadata.
377
+ sid_list = list(changed_sym_ids)
378
+ rows = batched_in(
379
+ conn,
380
+ "SELECT s.id, s.name, s.kind, f.path AS file_path, s.line_start, "
381
+ " (SELECT COUNT(*) FROM edges WHERE source_id = s.id) AS fan_out "
382
+ " FROM symbols s JOIN files f ON s.file_id = f.id "
383
+ " WHERE s.id IN ({ph})",
384
+ sid_list,
385
+ )
386
+ sym_by_id = {r["id"]: r for r in rows if r["fan_out"] > _FAN_OUT_THRESHOLD}
381
387
 
382
- fan_out = row["cnt"]
383
- try:
384
- sym = conn.execute(
385
- "SELECT s.name, s.kind, f.path as file_path, s.line_start "
386
- "FROM symbols s JOIN files f ON s.file_id = f.id WHERE s.id = ?",
387
- (sid,),
388
- ).fetchone()
389
- except Exception:
390
- continue
391
- if not sym:
388
+ for sid in changed_sym_ids:
389
+ sym = sym_by_id.get(sid)
390
+ if sym is None:
392
391
  continue
392
+ fan_out = sym["fan_out"]
393
393
 
394
394
  file_path = (sym["file_path"] or "").replace("\\", "/")
395
395
  name = sym["name"] or ""
@@ -243,11 +243,17 @@ def affected(ctx, base_ref, max_depth, use_changed):
243
243
 
244
244
  changed_paths = set(file_map.keys())
245
245
 
246
- # Collect all symbol IDs in changed files
246
+ # Collect all symbol IDs in changed files. Pass 94 — single
247
+ # batched IN-clause replaces N round-trips (was one query per
248
+ # changed file; now one query for the whole set).
247
249
  start_sym_ids = set()
248
- for path, fid in file_map.items():
249
- syms = conn.execute("SELECT id FROM symbols WHERE file_id = ?", (fid,)).fetchall()
250
- start_sym_ids.update(s["id"] for s in syms)
250
+ if file_map:
251
+ sym_rows = batched_in(
252
+ conn,
253
+ "SELECT id FROM symbols WHERE file_id IN ({ph})",
254
+ list(file_map.values()),
255
+ )
256
+ start_sym_ids.update(s["id"] for s in sym_rows)
251
257
 
252
258
  # BFS forward to find all dependents
253
259
  reachable = _bfs_forward_with_depth(conn, start_sym_ids, max_depth)
@@ -699,8 +699,14 @@ def _write_with_preserve(filepath, content):
699
699
  is_flag=True,
700
700
  help="Write directly to project root (CLAUDE/AGENTS/CODEX/GEMINI/.cursorrules)",
701
701
  )
702
+ @click.option(
703
+ "--brief",
704
+ "brief_mode",
705
+ is_flag=True,
706
+ help="Pass 100 — emit a compact summary (top-level fields only) instead of the full agent doc.",
707
+ )
702
708
  @click.pass_context
703
- def agent_export(ctx, output, fmt, profile, bundle, write_flag):
709
+ def agent_export(ctx, output, fmt, profile, bundle, write_flag, brief_mode):
704
710
  """Generate an AI agent context file from the roam index.
705
711
 
706
712
  Produces a concise markdown document with architecture, key files,
@@ -781,6 +787,36 @@ def agent_export(ctx, output, fmt, profile, bundle, write_flag):
781
787
 
782
788
  # JSON output
783
789
  if json_mode:
790
+ envelope_kwargs = dict(
791
+ format=formats[0],
792
+ formats=formats,
793
+ profile=profile,
794
+ bundle=bundle,
795
+ project_name=project_name,
796
+ )
797
+ if not brief_mode:
798
+ # Pass 100 — full payload only when --brief is OFF.
799
+ envelope_kwargs.update(
800
+ languages=languages,
801
+ stats=stats,
802
+ directory_layout=layout,
803
+ key_files=key_files,
804
+ entry_points=entry_points,
805
+ hotspots=hotspots,
806
+ test_info=test_info,
807
+ health_summary=(
808
+ {
809
+ "score": health.get("health_score"),
810
+ "cycles": health.get("cycles", 0),
811
+ "god_components": health.get("god_components", 0),
812
+ "dead_exports": health.get("dead_exports", 0),
813
+ }
814
+ if health
815
+ else None
816
+ ),
817
+ layers=layers,
818
+ clusters=clusters,
819
+ )
784
820
  click.echo(
785
821
  to_json(
786
822
  json_envelope(
@@ -794,29 +830,9 @@ def agent_export(ctx, output, fmt, profile, bundle, write_flag):
794
830
  "sections": section_count,
795
831
  "files": stats["files"],
796
832
  "symbols": stats["symbols"],
833
+ "brief": brief_mode,
797
834
  },
798
- format=formats[0],
799
- formats=formats,
800
- profile=profile,
801
- bundle=bundle,
802
- project_name=project_name,
803
- languages=languages,
804
- stats=stats,
805
- directory_layout=layout,
806
- key_files=key_files,
807
- entry_points=entry_points,
808
- hotspots=hotspots,
809
- test_info=test_info,
810
- health_summary={
811
- "score": health.get("health_score"),
812
- "cycles": health.get("cycles", 0),
813
- "god_components": health.get("god_components", 0),
814
- "dead_exports": health.get("dead_exports", 0),
815
- }
816
- if health
817
- else None,
818
- layers=layers,
819
- clusters=clusters,
835
+ **envelope_kwargs,
820
836
  )
821
837
  )
822
838
  )
@@ -0,0 +1,169 @@
1
+ """``roam audit`` — AI Agent Readiness Audit.
2
+
3
+ Pass 97 — Priority 1 strategic blocker per build_priorities.md. Chains
4
+ ``index → describe → health → risk → dead → owner → test-map → pr-risk``
5
+ into a single structured-JSON envelope. The artifact paying customers
6
+ buy: a one-shot audit that calibrates how ready a codebase is for
7
+ agent-driven work.
8
+
9
+ Sections:
10
+
11
+ - ``health`` — composite health score with category breakdown
12
+ - ``debt`` — total estimated debt + top hotspots
13
+ - ``dead`` — unused-symbol count + top wasted-LOC files
14
+ - ``risk`` — surface high-risk files (churn × complexity × fan-in)
15
+ - ``test_pyramid`` — unit/integration/e2e/smoke distribution
16
+ - ``coverage`` — imported-coverage % when available
17
+ - ``api`` — count of public symbols (the agent-facing surface)
18
+
19
+ Each section runs the corresponding sub-command in --json mode and
20
+ extracts a small set of high-signal fields. Failures from individual
21
+ sections are surfaced as ``{"error": ...}`` rows so the audit never
22
+ fails the whole report.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import json as _json
28
+
29
+ import click
30
+ from click.testing import CliRunner
31
+
32
+ from roam.commands.resolve import ensure_index
33
+ from roam.output.formatter import json_envelope, to_json
34
+
35
+
36
+ def _capture(args: list[str]) -> dict:
37
+ """Invoke a roam subcommand in --json mode in-process."""
38
+ from roam.cli import cli
39
+
40
+ runner = CliRunner()
41
+ result = runner.invoke(cli, ["--json", *args])
42
+ if result.exit_code not in (0, 5): # 5 = gate failure (still produces JSON)
43
+ return {
44
+ "_error": f"exit {result.exit_code}",
45
+ "_command": args,
46
+ "_output_head": (result.output or "")[:200],
47
+ }
48
+ try:
49
+ return _json.loads(result.output)
50
+ except Exception as exc:
51
+ return {
52
+ "_error": f"non-JSON output: {exc}",
53
+ "_command": args,
54
+ "_output_head": (result.output or "")[:200],
55
+ }
56
+
57
+
58
+ def _summary_field(payload: dict, *keys: str, default=None):
59
+ summary = payload.get("summary") or {}
60
+ for k in keys:
61
+ if k in summary and summary[k] is not None:
62
+ return summary[k]
63
+ return default
64
+
65
+
66
+ @click.command()
67
+ @click.option(
68
+ "--brief",
69
+ is_flag=True,
70
+ help="Drop per-section detail; keep only the top-level summary scores.",
71
+ )
72
+ @click.pass_context
73
+ def audit(ctx, brief) -> None:
74
+ """One-shot AI Agent Readiness Audit.
75
+
76
+ Bundles health, debt, dead-code, risk, test-pyramid, coverage, and
77
+ API-surface signals into a single envelope. Designed as the
78
+ structured artifact a paid audit attaches to its report.
79
+ """
80
+ json_mode = ctx.obj.get("json") if ctx.obj else False
81
+ ensure_index()
82
+
83
+ health = _capture(["health"])
84
+ debt = _capture(["debt"])
85
+ dead = _capture(["dead"])
86
+ test_pyramid = _capture(["test-pyramid"])
87
+ api = _capture(["api", "--limit", "0"])
88
+ stats = _capture(["stats"])
89
+ hotspots = _capture(["hotspots", "--danger"])
90
+
91
+ # Top-level scores so consumers can branch fast.
92
+ health_score = _summary_field(health, "health_score", "score")
93
+ debt_total = _summary_field(debt, "total_minutes", "estimated_minutes", "total")
94
+ dead_count = _summary_field(dead, "dead_count", "total")
95
+ danger_count = _summary_field(hotspots, "count", "danger_count", default=0)
96
+ pyramid_total = _summary_field(test_pyramid, "total", default=0)
97
+ api_count = _summary_field(api, "count", default=0)
98
+ file_total = _summary_field(stats, "file_total", default=0)
99
+ sym_total = _summary_field(stats, "symbol_total", default=0)
100
+ coverage_pct = _summary_field(health, "imported_coverage_pct")
101
+
102
+ # Verdict — stack-rank the most pressing dimension.
103
+ pressures = []
104
+ if isinstance(health_score, (int, float)) and health_score < 60:
105
+ pressures.append(f"health {health_score}/100")
106
+ if isinstance(danger_count, int) and danger_count > 0:
107
+ pressures.append(f"{danger_count} danger-zone file(s)")
108
+ if isinstance(coverage_pct, (int, float)) and coverage_pct < 40:
109
+ pressures.append(f"coverage {coverage_pct:.0f}%")
110
+ if pressures:
111
+ verdict = "AUDIT — pressures: " + ", ".join(pressures)
112
+ else:
113
+ verdict = (
114
+ f"AUDIT — health {health_score or '?'}/100, "
115
+ f"{file_total} files, {sym_total} symbols, "
116
+ f"{api_count} public-API symbols"
117
+ )
118
+
119
+ summary = {
120
+ "verdict": verdict,
121
+ "health_score": health_score,
122
+ "debt_total": debt_total,
123
+ "dead_count": dead_count,
124
+ "danger_zone_count": danger_count,
125
+ "test_count": pyramid_total,
126
+ "api_surface": api_count,
127
+ "imported_coverage_pct": coverage_pct,
128
+ "file_total": file_total,
129
+ "symbol_total": sym_total,
130
+ }
131
+
132
+ sections = {
133
+ "health": health if not brief else {"summary": health.get("summary", {})},
134
+ "debt": debt if not brief else {"summary": debt.get("summary", {})},
135
+ "dead": dead if not brief else {"summary": dead.get("summary", {})},
136
+ "test_pyramid": test_pyramid if not brief else {"summary": test_pyramid.get("summary", {})},
137
+ "hotspots_danger": hotspots if not brief else {"summary": hotspots.get("summary", {})},
138
+ "stats": stats if not brief else {"summary": stats.get("summary", {})},
139
+ }
140
+
141
+ if json_mode:
142
+ click.echo(
143
+ to_json(
144
+ json_envelope(
145
+ "audit",
146
+ summary=summary,
147
+ sections=sections,
148
+ api_count=api_count,
149
+ )
150
+ )
151
+ )
152
+ return
153
+
154
+ click.echo(f"VERDICT: {verdict}")
155
+ click.echo()
156
+ click.echo(f"{'Metric':<28} Value")
157
+ click.echo(f"{'-' * 28} {'-' * 30}")
158
+ for label, value in [
159
+ ("health score (0-100)", health_score),
160
+ ("debt (total)", debt_total),
161
+ ("dead symbols", dead_count),
162
+ ("danger-zone files", danger_count),
163
+ ("test files indexed", pyramid_total),
164
+ ("public API surface", api_count),
165
+ ("imported coverage %", coverage_pct),
166
+ ("total files", file_total),
167
+ ("total symbols", sym_total),
168
+ ]:
169
+ click.echo(f"{label:<28} {value}")
@@ -111,11 +111,21 @@ def complexity(ctx, target, limit, threshold, by_file, bumpy_road, include_tooli
111
111
  try:
112
112
  count = conn.execute("SELECT COUNT(*) FROM symbol_metrics").fetchone()[0]
113
113
  except Exception:
114
- click.echo("No complexity data found. Re-index with: roam index --force")
115
- raise SystemExit(1)
116
-
117
- if count == 0:
118
- click.echo("No complexity data found. Re-index with: roam index --force")
114
+ count = -1
115
+ if count <= 0:
116
+ verdict = "No complexity data found. Re-index with: roam index --force"
117
+ if json_mode:
118
+ click.echo(
119
+ to_json(
120
+ json_envelope(
121
+ "complexity",
122
+ summary={"verdict": verdict, "total": 0},
123
+ results=[],
124
+ )
125
+ )
126
+ )
127
+ else:
128
+ click.echo(verdict)
119
129
  raise SystemExit(1)
120
130
 
121
131
  if bumpy_road:
@@ -179,7 +189,19 @@ def complexity(ctx, target, limit, threshold, by_file, bumpy_road, include_tooli
179
189
  sarif = complexity_to_sarif([], threshold=threshold or 0)
180
190
  click.echo(write_sarif(sarif))
181
191
  return
182
- click.echo("No matching symbols found.")
192
+ verdict = "No matching symbols found."
193
+ if json_mode:
194
+ click.echo(
195
+ to_json(
196
+ json_envelope(
197
+ "complexity",
198
+ summary={"verdict": verdict, "total": 0},
199
+ results=[],
200
+ )
201
+ )
202
+ )
203
+ else:
204
+ click.echo(verdict)
183
205
  return
184
206
 
185
207
  if sarif_mode:
@@ -398,7 +420,19 @@ def _bumpy_road(conn, json_mode, limit, threshold):
398
420
  ).fetchall()
399
421
 
400
422
  if not rows:
401
- click.echo("No bumpy-road files found.")
423
+ verdict = "No bumpy-road files found."
424
+ if json_mode:
425
+ click.echo(
426
+ to_json(
427
+ json_envelope(
428
+ "complexity",
429
+ summary={"verdict": verdict, "total": 0},
430
+ bumpy_road=[],
431
+ )
432
+ )
433
+ )
434
+ else:
435
+ click.echo(verdict)
402
436
  return
403
437
 
404
438
  if json_mode:
@@ -543,18 +543,19 @@ def _no_mutating_options(
543
543
  exclude_pattern,
544
544
  remove_pattern,
545
545
  ) -> bool:
546
- return all(
547
- value is None
548
- for value in (
549
- db_dir,
550
- use_local_cache,
551
- semantic_backend,
552
- onnx_model,
553
- onnx_tokenizer,
554
- onnx_max_length,
555
- exclude_pattern,
556
- remove_pattern,
557
- )
546
+ # Pass 91 — ``use_local_cache`` is a ``is_flag=True`` Click option,
547
+ # so its default is ``False`` not ``None``. The previous all(... is
548
+ # None) check returned False even when nothing was passed, leaving
549
+ # ``roam config`` (no flags, no --show) silent in --json mode.
550
+ return (
551
+ db_dir is None
552
+ and not use_local_cache
553
+ and semantic_backend is None
554
+ and onnx_model is None
555
+ and onnx_tokenizer is None
556
+ and onnx_max_length is None
557
+ and exclude_pattern is None
558
+ and remove_pattern is None
558
559
  )
559
560
 
560
561