roam-code 12.41__tar.gz → 12.43__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 (667) hide show
  1. {roam_code-12.41 → roam_code-12.43}/PKG-INFO +7 -4
  2. {roam_code-12.41 → roam_code-12.43}/README.md +6 -3
  3. {roam_code-12.41 → roam_code-12.43}/pyproject.toml +1 -1
  4. roam_code-12.43/src/roam/capability.py +250 -0
  5. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/detectors.py +131 -0
  6. {roam_code-12.41 → roam_code-12.43}/src/roam/cli.py +6 -0
  7. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_article_12_check.py +17 -0
  8. roam_code-12.43/src/roam/commands/cmd_capabilities.py +129 -0
  9. roam_code-12.43/src/roam/commands/cmd_compare.py +223 -0
  10. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_permit.py +18 -0
  11. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_postmortem.py +17 -0
  12. roam_code-12.43/src/roam/commands/cmd_skill_generate.py +256 -0
  13. {roam_code-12.41 → roam_code-12.43}/src/roam/competitor_site_data.py +1 -1
  14. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp-server-card.json +1 -1
  15. {roam_code-12.41 → roam_code-12.43}/src/roam/output/sarif.py +137 -6
  16. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/PKG-INFO +7 -4
  17. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/SOURCES.txt +8 -0
  18. roam_code-12.43/tests/test_capability_registry.py +137 -0
  19. roam_code-12.43/tests/test_compare_cli.py +121 -0
  20. roam_code-12.43/tests/test_sarif_enrichment.py +154 -0
  21. roam_code-12.43/tests/test_skill_generate.py +74 -0
  22. {roam_code-12.41 → roam_code-12.43}/LICENSE +0 -0
  23. {roam_code-12.41 → roam_code-12.43}/setup.cfg +0 -0
  24. {roam_code-12.41 → roam_code-12.43}/src/roam/__init__.py +0 -0
  25. {roam_code-12.41 → roam_code-12.43}/src/roam/__main__.py +0 -0
  26. {roam_code-12.41 → roam_code-12.43}/src/roam/analysis/__init__.py +0 -0
  27. {roam_code-12.41 → roam_code-12.43}/src/roam/analysis/effects.py +0 -0
  28. {roam_code-12.41 → roam_code-12.43}/src/roam/analysis/taint.py +0 -0
  29. {roam_code-12.41 → roam_code-12.43}/src/roam/api.py +0 -0
  30. {roam_code-12.41 → roam_code-12.43}/src/roam/ask/__init__.py +0 -0
  31. {roam_code-12.41 → roam_code-12.43}/src/roam/ask/classifier.py +0 -0
  32. {roam_code-12.41 → roam_code-12.43}/src/roam/ask/recipes.py +0 -0
  33. {roam_code-12.41 → roam_code-12.43}/src/roam/ask/runner.py +0 -0
  34. {roam_code-12.41 → roam_code-12.43}/src/roam/ask/workflow.py +0 -0
  35. {roam_code-12.41 → roam_code-12.43}/src/roam/attest/__init__.py +0 -0
  36. {roam_code-12.41 → roam_code-12.43}/src/roam/attest/cga.py +0 -0
  37. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/__init__.py +0 -0
  38. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/base.py +0 -0
  39. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_config.py +0 -0
  40. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_django.py +0 -0
  41. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_protobuf.py +0 -0
  42. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_rest_api.py +0 -0
  43. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_salesforce.py +0 -0
  44. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/bridge_template.py +0 -0
  45. {roam_code-12.41 → roam_code-12.43}/src/roam/bridges/registry.py +0 -0
  46. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/__init__.py +0 -0
  47. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/fixes.py +0 -0
  48. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/python_idioms.py +0 -0
  49. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/smells.py +0 -0
  50. {roam_code-12.41 → roam_code-12.43}/src/roam/catalog/tasks.py +0 -0
  51. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/__init__.py +0 -0
  52. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/audit_trail_helpers.py +0 -0
  53. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/changed_files.py +0 -0
  54. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_adrs.py +0 -0
  55. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_adversarial.py +0 -0
  56. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_affected.py +0 -0
  57. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_affected_tests.py +0 -0
  58. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_agent_context.py +0 -0
  59. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_agent_export.py +0 -0
  60. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_agent_plan.py +0 -0
  61. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ai_ratio.py +0 -0
  62. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ai_readiness.py +0 -0
  63. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_alerts.py +0 -0
  64. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_annotate.py +0 -0
  65. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_api.py +0 -0
  66. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_api_changes.py +0 -0
  67. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_api_drift.py +0 -0
  68. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ask.py +0 -0
  69. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_attest.py +0 -0
  70. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_audit.py +0 -0
  71. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_audit_trail_conformance.py +0 -0
  72. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_audit_trail_export.py +0 -0
  73. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_audit_trail_verify.py +0 -0
  74. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_auth_gaps.py +0 -0
  75. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_bisect.py +0 -0
  76. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_breaking.py +0 -0
  77. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_budget.py +0 -0
  78. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_bus_factor.py +0 -0
  79. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_capsule.py +0 -0
  80. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_cga.py +0 -0
  81. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_changelog.py +0 -0
  82. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_check_rules.py +0 -0
  83. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ci_setup.py +0 -0
  84. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_clean.py +0 -0
  85. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_clones.py +0 -0
  86. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_closure.py +0 -0
  87. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_clusters.py +0 -0
  88. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_codeowners.py +0 -0
  89. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_complexity.py +0 -0
  90. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_config.py +0 -0
  91. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_congestion.py +0 -0
  92. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_context.py +0 -0
  93. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_conventions.py +0 -0
  94. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_coupling.py +0 -0
  95. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_coverage_gaps.py +0 -0
  96. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_critique.py +0 -0
  97. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_cut.py +0 -0
  98. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_dark_matter.py +0 -0
  99. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_dashboard.py +0 -0
  100. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_dead.py +0 -0
  101. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_debt.py +0 -0
  102. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_deps.py +0 -0
  103. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_describe.py +0 -0
  104. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_dev_profile.py +0 -0
  105. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_diagnose.py +0 -0
  106. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_diff.py +0 -0
  107. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_disambiguate.py +0 -0
  108. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_doc_staleness.py +0 -0
  109. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_docs_coverage.py +0 -0
  110. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_doctor.py +0 -0
  111. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_dogfood.py +0 -0
  112. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_drift.py +0 -0
  113. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_duplicates.py +0 -0
  114. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_effects.py +0 -0
  115. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_endpoints.py +0 -0
  116. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_entry_points.py +0 -0
  117. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_eval_retrieve.py +0 -0
  118. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_exit_codes.py +0 -0
  119. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_fan.py +0 -0
  120. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_file.py +0 -0
  121. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_fingerprint.py +0 -0
  122. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_fitness.py +0 -0
  123. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_flag_dead.py +0 -0
  124. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_fleet.py +0 -0
  125. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_fn_coupling.py +0 -0
  126. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_forecast.py +0 -0
  127. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_graph_export.py +0 -0
  128. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_graph_stats.py +0 -0
  129. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_grep.py +0 -0
  130. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_guard.py +0 -0
  131. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_health.py +0 -0
  132. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_help_search.py +0 -0
  133. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_hooks.py +0 -0
  134. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_hotspots.py +0 -0
  135. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_hover.py +0 -0
  136. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_impact.py +0 -0
  137. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_index.py +0 -0
  138. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_index_bundle.py +0 -0
  139. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_index_stats.py +0 -0
  140. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ingest_trace.py +0 -0
  141. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_init.py +0 -0
  142. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_intent.py +0 -0
  143. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_invariants.py +0 -0
  144. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_layers.py +0 -0
  145. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_map.py +0 -0
  146. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_math.py +0 -0
  147. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_mcp_setup.py +0 -0
  148. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_mcp_status.py +0 -0
  149. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_metrics.py +0 -0
  150. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_metrics_push.py +0 -0
  151. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_migration_safety.py +0 -0
  152. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_minimap.py +0 -0
  153. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_missing_index.py +0 -0
  154. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_module.py +0 -0
  155. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_mutate.py +0 -0
  156. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_n1.py +0 -0
  157. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_oracle.py +0 -0
  158. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_orchestrate.py +0 -0
  159. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_orphan_imports.py +0 -0
  160. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_orphan_routes.py +0 -0
  161. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_over_fetch.py +0 -0
  162. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_owner.py +0 -0
  163. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_partition.py +0 -0
  164. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_path_coverage.py +0 -0
  165. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_patterns.py +0 -0
  166. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_plan.py +0 -0
  167. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_plan_refactor.py +0 -0
  168. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_plugins.py +0 -0
  169. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pr_analyze.py +0 -0
  170. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pr_comment_render.py +0 -0
  171. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pr_diff.py +0 -0
  172. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pr_prep.py +0 -0
  173. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pr_risk.py +0 -0
  174. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pre_commit.py +0 -0
  175. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_preflight.py +0 -0
  176. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_py_modern.py +0 -0
  177. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_py_types.py +0 -0
  178. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_pytest_fixtures.py +0 -0
  179. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_recipes.py +0 -0
  180. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_recommend.py +0 -0
  181. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_relate.py +0 -0
  182. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_report.py +0 -0
  183. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_reset.py +0 -0
  184. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_retrieve.py +0 -0
  185. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_risk.py +0 -0
  186. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_rules.py +0 -0
  187. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_rules_validate.py +0 -0
  188. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_safe_delete.py +0 -0
  189. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_safe_zones.py +0 -0
  190. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_sbom.py +0 -0
  191. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_schema.py +0 -0
  192. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_search.py +0 -0
  193. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_search_semantic.py +0 -0
  194. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_secrets.py +0 -0
  195. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_semantic_diff.py +0 -0
  196. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_simulate.py +0 -0
  197. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_simulate_departure.py +0 -0
  198. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_sketch.py +0 -0
  199. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_smells.py +0 -0
  200. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_spectral.py +0 -0
  201. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_split.py +0 -0
  202. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_stats.py +0 -0
  203. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_suggest_refactoring.py +0 -0
  204. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_suggest_reviewers.py +0 -0
  205. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_supply_chain.py +0 -0
  206. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_suppress.py +0 -0
  207. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_symbol.py +0 -0
  208. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_syntax_check.py +0 -0
  209. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_taint.py +0 -0
  210. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_telemetry.py +0 -0
  211. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_test_gaps.py +0 -0
  212. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_test_impact.py +0 -0
  213. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_test_pyramid.py +0 -0
  214. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_test_scaffold.py +0 -0
  215. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_testmap.py +0 -0
  216. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_timeline.py +0 -0
  217. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_tour.py +0 -0
  218. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_trace.py +0 -0
  219. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_trends.py +0 -0
  220. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_triage.py +0 -0
  221. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_understand.py +0 -0
  222. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_uses.py +0 -0
  223. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_verify.py +0 -0
  224. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_verify_imports.py +0 -0
  225. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_version.py +0 -0
  226. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_vibe_check.py +0 -0
  227. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_visualize.py +0 -0
  228. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_vuln_map.py +0 -0
  229. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_vuln_reach.py +0 -0
  230. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_vulns.py +0 -0
  231. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_watch.py +0 -0
  232. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_weather.py +0 -0
  233. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_why.py +0 -0
  234. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_why_fail.py +0 -0
  235. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_workflow.py +0 -0
  236. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_ws.py +0 -0
  237. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/cmd_xlang.py +0 -0
  238. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/codeowners_helpers.py +0 -0
  239. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/context_helpers.py +0 -0
  240. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/finding_suppress.py +0 -0
  241. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/gate_presets.py +0 -0
  242. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/git_helpers.py +0 -0
  243. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/graph_helpers.py +0 -0
  244. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/metrics_history.py +0 -0
  245. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/next_steps.py +0 -0
  246. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/pr_analyze/__init__.py +0 -0
  247. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/pr_analyze/audit_trail.py +0 -0
  248. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/pr_analyze/cache.py +0 -0
  249. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/pr_analyze/rules.py +0 -0
  250. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/resolve.py +0 -0
  251. {roam_code-12.41 → roam_code-12.43}/src/roam/commands/suppression.py +0 -0
  252. {roam_code-12.41 → roam_code-12.43}/src/roam/config.py +0 -0
  253. {roam_code-12.41 → roam_code-12.43}/src/roam/coverage_reports.py +0 -0
  254. {roam_code-12.41 → roam_code-12.43}/src/roam/critique/__init__.py +0 -0
  255. {roam_code-12.41 → roam_code-12.43}/src/roam/critique/aggregator.py +0 -0
  256. {roam_code-12.41 → roam_code-12.43}/src/roam/critique/checks.py +0 -0
  257. {roam_code-12.41 → roam_code-12.43}/src/roam/db/__init__.py +0 -0
  258. {roam_code-12.41 → roam_code-12.43}/src/roam/db/connection.py +0 -0
  259. {roam_code-12.41 → roam_code-12.43}/src/roam/db/queries.py +0 -0
  260. {roam_code-12.41 → roam_code-12.43}/src/roam/db/schema.py +0 -0
  261. {roam_code-12.41 → roam_code-12.43}/src/roam/eval/__init__.py +0 -0
  262. {roam_code-12.41 → roam_code-12.43}/src/roam/eval/harness.py +0 -0
  263. {roam_code-12.41 → roam_code-12.43}/src/roam/exit_codes.py +0 -0
  264. {roam_code-12.41 → roam_code-12.43}/src/roam/fleet/__init__.py +0 -0
  265. {roam_code-12.41 → roam_code-12.43}/src/roam/fleet/adapters.py +0 -0
  266. {roam_code-12.41 → roam_code-12.43}/src/roam/fleet/manifest.py +0 -0
  267. {roam_code-12.41 → roam_code-12.43}/src/roam/git_utils.py +0 -0
  268. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/__init__.py +0 -0
  269. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/anomaly.py +0 -0
  270. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/builder.py +0 -0
  271. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/clone_detect.py +0 -0
  272. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/clusters.py +0 -0
  273. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/cycles.py +0 -0
  274. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/dark_matter.py +0 -0
  275. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/diff.py +0 -0
  276. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/fingerprint.py +0 -0
  277. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/layers.py +0 -0
  278. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/pagerank.py +0 -0
  279. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/partition.py +0 -0
  280. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/pathfinding.py +0 -0
  281. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/propagation.py +0 -0
  282. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/simulate.py +0 -0
  283. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/spectral.py +0 -0
  284. {roam_code-12.41 → roam_code-12.43}/src/roam/graph/stats.py +0 -0
  285. {roam_code-12.41 → roam_code-12.43}/src/roam/index/__init__.py +0 -0
  286. {roam_code-12.41 → roam_code-12.43}/src/roam/index/complexity.py +0 -0
  287. {roam_code-12.41 → roam_code-12.43}/src/roam/index/discovery.py +0 -0
  288. {roam_code-12.41 → roam_code-12.43}/src/roam/index/django_post.py +0 -0
  289. {roam_code-12.41 → roam_code-12.43}/src/roam/index/file_roles.py +0 -0
  290. {roam_code-12.41 → roam_code-12.43}/src/roam/index/git_stats.py +0 -0
  291. {roam_code-12.41 → roam_code-12.43}/src/roam/index/gitignore.py +0 -0
  292. {roam_code-12.41 → roam_code-12.43}/src/roam/index/incremental.py +0 -0
  293. {roam_code-12.41 → roam_code-12.43}/src/roam/index/indexer.py +0 -0
  294. {roam_code-12.41 → roam_code-12.43}/src/roam/index/parser.py +0 -0
  295. {roam_code-12.41 → roam_code-12.43}/src/roam/index/pytest_fixtures.py +0 -0
  296. {roam_code-12.41 → roam_code-12.43}/src/roam/index/registry_dispatch.py +0 -0
  297. {roam_code-12.41 → roam_code-12.43}/src/roam/index/relations.py +0 -0
  298. {roam_code-12.41 → roam_code-12.43}/src/roam/index/symbols.py +0 -0
  299. {roam_code-12.41 → roam_code-12.43}/src/roam/index/test_conventions.py +0 -0
  300. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/__init__.py +0 -0
  301. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/apex_lang.py +0 -0
  302. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/aura_lang.py +0 -0
  303. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/base.py +0 -0
  304. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/c_lang.py +0 -0
  305. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/csharp_lang.py +0 -0
  306. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/extractor_schema.py +0 -0
  307. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/extractors/kotlin.yaml +0 -0
  308. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/foxpro_lang.py +0 -0
  309. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/generic_lang.py +0 -0
  310. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/go_lang.py +0 -0
  311. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/hcl_lang.py +0 -0
  312. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/java_lang.py +0 -0
  313. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/javascript_lang.py +0 -0
  314. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/kotlin_lang.py +0 -0
  315. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/php_lang.py +0 -0
  316. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/python_lang.py +0 -0
  317. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/query_engine.py +0 -0
  318. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/registry.py +0 -0
  319. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/ruby_lang.py +0 -0
  320. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/rust_lang.py +0 -0
  321. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/scala_lang.py +0 -0
  322. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/sfxml_lang.py +0 -0
  323. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/sql_lang.py +0 -0
  324. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/swift_lang.py +0 -0
  325. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/typescript_lang.py +0 -0
  326. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/visualforce_lang.py +0 -0
  327. {roam_code-12.41 → roam_code-12.43}/src/roam/languages/yaml_lang.py +0 -0
  328. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/__init__.py +0 -0
  329. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/completions.py +0 -0
  330. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/concurrency.py +0 -0
  331. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/progress.py +0 -0
  332. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/sampling.py +0 -0
  333. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/session.py +0 -0
  334. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_extras/watcher.py +0 -0
  335. {roam_code-12.41 → roam_code-12.43}/src/roam/mcp_server.py +0 -0
  336. {roam_code-12.41 → roam_code-12.43}/src/roam/observability.py +0 -0
  337. {roam_code-12.41 → roam_code-12.43}/src/roam/output/__init__.py +0 -0
  338. {roam_code-12.41 → roam_code-12.43}/src/roam/output/confidence.py +0 -0
  339. {roam_code-12.41 → roam_code-12.43}/src/roam/output/errors.py +0 -0
  340. {roam_code-12.41 → roam_code-12.43}/src/roam/output/file_role_hints.py +0 -0
  341. {roam_code-12.41 → roam_code-12.43}/src/roam/output/formatter.py +0 -0
  342. {roam_code-12.41 → roam_code-12.43}/src/roam/output/framework_filter.py +0 -0
  343. {roam_code-12.41 → roam_code-12.43}/src/roam/output/mermaid.py +0 -0
  344. {roam_code-12.41 → roam_code-12.43}/src/roam/output/project_shape.py +0 -0
  345. {roam_code-12.41 → roam_code-12.43}/src/roam/output/schema_registry.py +0 -0
  346. {roam_code-12.41 → roam_code-12.43}/src/roam/plugins.py +0 -0
  347. {roam_code-12.41 → roam_code-12.43}/src/roam/refactor/__init__.py +0 -0
  348. {roam_code-12.41 → roam_code-12.43}/src/roam/refactor/codegen.py +0 -0
  349. {roam_code-12.41 → roam_code-12.43}/src/roam/refactor/transforms.py +0 -0
  350. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/__init__.py +0 -0
  351. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/learned_ranker.py +0 -0
  352. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/pipeline.py +0 -0
  353. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/rerank.py +0 -0
  354. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/seeds.py +0 -0
  355. {roam_code-12.41 → roam_code-12.43}/src/roam/retrieve/semantic.py +0 -0
  356. {roam_code-12.41 → roam_code-12.43}/src/roam/rules/__init__.py +0 -0
  357. {roam_code-12.41 → roam_code-12.43}/src/roam/rules/ast_match.py +0 -0
  358. {roam_code-12.41 → roam_code-12.43}/src/roam/rules/builtin.py +0 -0
  359. {roam_code-12.41 → roam_code-12.43}/src/roam/rules/dataflow.py +0 -0
  360. {roam_code-12.41 → roam_code-12.43}/src/roam/rules/engine.py +0 -0
  361. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/__init__.py +0 -0
  362. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/daemon.py +0 -0
  363. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/graph_backend.py +0 -0
  364. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/hotspots.py +0 -0
  365. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/lock_modes.py +0 -0
  366. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/lockmgr.py +0 -0
  367. {roam_code-12.41 → roam_code-12.43}/src/roam/runtime/trace_ingest.py +0 -0
  368. {roam_code-12.41 → roam_code-12.43}/src/roam/search/__init__.py +0 -0
  369. {roam_code-12.41 → roam_code-12.43}/src/roam/search/framework_packs.py +0 -0
  370. {roam_code-12.41 → roam_code-12.43}/src/roam/search/index_embeddings.py +0 -0
  371. {roam_code-12.41 → roam_code-12.43}/src/roam/search/onnx_embeddings.py +0 -0
  372. {roam_code-12.41 → roam_code-12.43}/src/roam/search/tfidf.py +0 -0
  373. {roam_code-12.41 → roam_code-12.43}/src/roam/security/__init__.py +0 -0
  374. {roam_code-12.41 → roam_code-12.43}/src/roam/security/aibom_extension.py +0 -0
  375. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_classifier.py +0 -0
  376. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_engine.py +0 -0
  377. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/api_error_leak.yaml +0 -0
  378. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/java_fileupload_path_traversal.yaml +0 -0
  379. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/js_insecure_jwt_decode.yaml +0 -0
  380. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/js_localstorage_secrets.yaml +0 -0
  381. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/js_prototype_pollution.yaml +0 -0
  382. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/js_ssrf.yaml +0 -0
  383. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/js_xss.yaml +0 -0
  384. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_basic.yaml +0 -0
  385. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_deserialization.yaml +0 -0
  386. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_path_traversal.yaml +0 -0
  387. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_socketio_remote_source.yaml +0 -0
  388. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_sqli.yaml +0 -0
  389. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/python_urllib_open_redirect.yaml +0 -0
  390. {roam_code-12.41 → roam_code-12.43}/src/roam/security/taint_rules/vue_v_html.yaml +0 -0
  391. {roam_code-12.41 → roam_code-12.43}/src/roam/security/vuln_reach.py +0 -0
  392. {roam_code-12.41 → roam_code-12.43}/src/roam/security/vuln_store.py +0 -0
  393. {roam_code-12.41 → roam_code-12.43}/src/roam/surface_counts.py +0 -0
  394. {roam_code-12.41 → roam_code-12.43}/src/roam/telemetry.py +0 -0
  395. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/__init__.py +0 -0
  396. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/Jenkinsfile +0 -0
  397. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/__init__.py +0 -0
  398. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/agent-review.yml +0 -0
  399. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/azure-pipelines.yml +0 -0
  400. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/bitbucket-pipelines.yml +0 -0
  401. {roam_code-12.41 → roam_code-12.43}/src/roam/templates/ci/gitlab-ci.yml +0 -0
  402. {roam_code-12.41 → roam_code-12.43}/src/roam/workspace/__init__.py +0 -0
  403. {roam_code-12.41 → roam_code-12.43}/src/roam/workspace/aggregator.py +0 -0
  404. {roam_code-12.41 → roam_code-12.43}/src/roam/workspace/api_scanner.py +0 -0
  405. {roam_code-12.41 → roam_code-12.43}/src/roam/workspace/config.py +0 -0
  406. {roam_code-12.41 → roam_code-12.43}/src/roam/workspace/db.py +0 -0
  407. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/dependency_links.txt +0 -0
  408. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/entry_points.txt +0 -0
  409. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/requires.txt +0 -0
  410. {roam_code-12.41 → roam_code-12.43}/src/roam_code.egg-info/top_level.txt +0 -0
  411. {roam_code-12.41 → roam_code-12.43}/tests/test_adrs.py +0 -0
  412. {roam_code-12.41 → roam_code-12.43}/tests/test_adversarial.py +0 -0
  413. {roam_code-12.41 → roam_code-12.43}/tests/test_affected.py +0 -0
  414. {roam_code-12.41 → roam_code-12.43}/tests/test_agent_export.py +0 -0
  415. {roam_code-12.41 → roam_code-12.43}/tests/test_agent_mode.py +0 -0
  416. {roam_code-12.41 → roam_code-12.43}/tests/test_agent_plan_context.py +0 -0
  417. {roam_code-12.41 → roam_code-12.43}/tests/test_ai_ratio.py +0 -0
  418. {roam_code-12.41 → roam_code-12.43}/tests/test_ai_readiness.py +0 -0
  419. {roam_code-12.41 → roam_code-12.43}/tests/test_alerts_cmd.py +0 -0
  420. {roam_code-12.41 → roam_code-12.43}/tests/test_annotations.py +0 -0
  421. {roam_code-12.41 → roam_code-12.43}/tests/test_anomaly.py +0 -0
  422. {roam_code-12.41 → roam_code-12.43}/tests/test_api_changes.py +0 -0
  423. {roam_code-12.41 → roam_code-12.43}/tests/test_api_drift.py +0 -0
  424. {roam_code-12.41 → roam_code-12.43}/tests/test_ask.py +0 -0
  425. {roam_code-12.41 → roam_code-12.43}/tests/test_attest.py +0 -0
  426. {roam_code-12.41 → roam_code-12.43}/tests/test_audit_trail_aggregate.py +0 -0
  427. {roam_code-12.41 → roam_code-12.43}/tests/test_audit_trail_conformance.py +0 -0
  428. {roam_code-12.41 → roam_code-12.43}/tests/test_audit_trail_sequence.py +0 -0
  429. {roam_code-12.41 → roam_code-12.43}/tests/test_audit_trail_verify.py +0 -0
  430. {roam_code-12.41 → roam_code-12.43}/tests/test_auth_gaps.py +0 -0
  431. {roam_code-12.41 → roam_code-12.43}/tests/test_backend_fixes_round2.py +0 -0
  432. {roam_code-12.41 → roam_code-12.43}/tests/test_backend_fixes_round3.py +0 -0
  433. {roam_code-12.41 → roam_code-12.43}/tests/test_basic.py +0 -0
  434. {roam_code-12.41 → roam_code-12.43}/tests/test_batch_mcp.py +0 -0
  435. {roam_code-12.41 → roam_code-12.43}/tests/test_bisect.py +0 -0
  436. {roam_code-12.41 → roam_code-12.43}/tests/test_bridge_django.py +0 -0
  437. {roam_code-12.41 → roam_code-12.43}/tests/test_bridges.py +0 -0
  438. {roam_code-12.41 → roam_code-12.43}/tests/test_bridges_extended.py +0 -0
  439. {roam_code-12.41 → roam_code-12.43}/tests/test_budget.py +0 -0
  440. {roam_code-12.41 → roam_code-12.43}/tests/test_budget_flag.py +0 -0
  441. {roam_code-12.41 → roam_code-12.43}/tests/test_budget_phase2.py +0 -0
  442. {roam_code-12.41 → roam_code-12.43}/tests/test_bus_factor.py +0 -0
  443. {roam_code-12.41 → roam_code-12.43}/tests/test_capsule.py +0 -0
  444. {roam_code-12.41 → roam_code-12.43}/tests/test_cga.py +0 -0
  445. {roam_code-12.41 → roam_code-12.43}/tests/test_check_rules.py +0 -0
  446. {roam_code-12.41 → roam_code-12.43}/tests/test_ci_gate_eval.py +0 -0
  447. {roam_code-12.41 → roam_code-12.43}/tests/test_ci_sarif_guard.py +0 -0
  448. {roam_code-12.41 → roam_code-12.43}/tests/test_ci_setup.py +0 -0
  449. {roam_code-12.41 → roam_code-12.43}/tests/test_clones.py +0 -0
  450. {roam_code-12.41 → roam_code-12.43}/tests/test_closure.py +0 -0
  451. {roam_code-12.41 → roam_code-12.43}/tests/test_codeowners.py +0 -0
  452. {roam_code-12.41 → roam_code-12.43}/tests/test_commands_architecture.py +0 -0
  453. {roam_code-12.41 → roam_code-12.43}/tests/test_commands_exploration.py +0 -0
  454. {roam_code-12.41 → roam_code-12.43}/tests/test_commands_health.py +0 -0
  455. {roam_code-12.41 → roam_code-12.43}/tests/test_commands_refactoring.py +0 -0
  456. {roam_code-12.41 → roam_code-12.43}/tests/test_commands_workflow.py +0 -0
  457. {roam_code-12.41 → roam_code-12.43}/tests/test_competitor_site_data.py +0 -0
  458. {roam_code-12.41 → roam_code-12.43}/tests/test_comprehensive.py +0 -0
  459. {roam_code-12.41 → roam_code-12.43}/tests/test_config.py +0 -0
  460. {roam_code-12.41 → roam_code-12.43}/tests/test_congestion.py +0 -0
  461. {roam_code-12.41 → roam_code-12.43}/tests/test_context_propagation.py +0 -0
  462. {roam_code-12.41 → roam_code-12.43}/tests/test_conventions_cmd.py +0 -0
  463. {roam_code-12.41 → roam_code-12.43}/tests/test_coverage_gaps_cmd.py +0 -0
  464. {roam_code-12.41 → roam_code-12.43}/tests/test_coverage_ingestion.py +0 -0
  465. {roam_code-12.41 → roam_code-12.43}/tests/test_critique.py +0 -0
  466. {roam_code-12.41 → roam_code-12.43}/tests/test_cut.py +0 -0
  467. {roam_code-12.41 → roam_code-12.43}/tests/test_dark_matter.py +0 -0
  468. {roam_code-12.41 → roam_code-12.43}/tests/test_dark_matter_helpers.py +0 -0
  469. {roam_code-12.41 → roam_code-12.43}/tests/test_dashboard.py +0 -0
  470. {roam_code-12.41 → roam_code-12.43}/tests/test_dataflow_dead.py +0 -0
  471. {roam_code-12.41 → roam_code-12.43}/tests/test_dead_aging.py +0 -0
  472. {roam_code-12.41 → roam_code-12.43}/tests/test_defer_loading.py +0 -0
  473. {roam_code-12.41 → roam_code-12.43}/tests/test_demo_gif_asset.py +0 -0
  474. {roam_code-12.41 → roam_code-12.43}/tests/test_describe.py +0 -0
  475. {roam_code-12.41 → roam_code-12.43}/tests/test_detail_flag_hints.py +0 -0
  476. {roam_code-12.41 → roam_code-12.43}/tests/test_detector_precision.py +0 -0
  477. {roam_code-12.41 → roam_code-12.43}/tests/test_deterministic_output.py +0 -0
  478. {roam_code-12.41 → roam_code-12.43}/tests/test_dev_profile.py +0 -0
  479. {roam_code-12.41 → roam_code-12.43}/tests/test_difficulty_scoring.py +0 -0
  480. {roam_code-12.41 → roam_code-12.43}/tests/test_doc_consistency.py +0 -0
  481. {roam_code-12.41 → roam_code-12.43}/tests/test_doc_staleness.py +0 -0
  482. {roam_code-12.41 → roam_code-12.43}/tests/test_docker_assets.py +0 -0
  483. {roam_code-12.41 → roam_code-12.43}/tests/test_docs_coverage.py +0 -0
  484. {roam_code-12.41 → roam_code-12.43}/tests/test_docs_site_quality.py +0 -0
  485. {roam_code-12.41 → roam_code-12.43}/tests/test_doctor.py +0 -0
  486. {roam_code-12.41 → roam_code-12.43}/tests/test_dogfood.py +0 -0
  487. {roam_code-12.41 → roam_code-12.43}/tests/test_drift.py +0 -0
  488. {roam_code-12.41 → roam_code-12.43}/tests/test_drift_by_team.py +0 -0
  489. {roam_code-12.41 → roam_code-12.43}/tests/test_duplicates.py +0 -0
  490. {roam_code-12.41 → roam_code-12.43}/tests/test_effects.py +0 -0
  491. {roam_code-12.41 → roam_code-12.43}/tests/test_effects_propagation.py +0 -0
  492. {roam_code-12.41 → roam_code-12.43}/tests/test_endpoints.py +0 -0
  493. {roam_code-12.41 → roam_code-12.43}/tests/test_entry_points_cmd.py +0 -0
  494. {roam_code-12.41 → roam_code-12.43}/tests/test_eval_retrieve.py +0 -0
  495. {roam_code-12.41 → roam_code-12.43}/tests/test_except_pass_narrow.py +0 -0
  496. {roam_code-12.41 → roam_code-12.43}/tests/test_exclude_patterns.py +0 -0
  497. {roam_code-12.41 → roam_code-12.43}/tests/test_exit_codes.py +0 -0
  498. {roam_code-12.41 → roam_code-12.43}/tests/test_extractor_grammar_drift.py +0 -0
  499. {roam_code-12.41 → roam_code-12.43}/tests/test_fallback_contracts.py +0 -0
  500. {roam_code-12.41 → roam_code-12.43}/tests/test_file_roles.py +0 -0
  501. {roam_code-12.41 → roam_code-12.43}/tests/test_finding_suppress.py +0 -0
  502. {roam_code-12.41 → roam_code-12.43}/tests/test_fingerprint.py +0 -0
  503. {roam_code-12.41 → roam_code-12.43}/tests/test_fixes.py +0 -0
  504. {roam_code-12.41 → roam_code-12.43}/tests/test_flag_dead.py +0 -0
  505. {roam_code-12.41 → roam_code-12.43}/tests/test_fleet.py +0 -0
  506. {roam_code-12.41 → roam_code-12.43}/tests/test_fn_coupling.py +0 -0
  507. {roam_code-12.41 → roam_code-12.43}/tests/test_forecast.py +0 -0
  508. {roam_code-12.41 → roam_code-12.43}/tests/test_formatters.py +0 -0
  509. {roam_code-12.41 → roam_code-12.43}/tests/test_foxpro.py +0 -0
  510. {roam_code-12.41 → roam_code-12.43}/tests/test_framework_detection.py +0 -0
  511. {roam_code-12.41 → roam_code-12.43}/tests/test_gate_presets.py +0 -0
  512. {roam_code-12.41 → roam_code-12.43}/tests/test_git_helpers.py +0 -0
  513. {roam_code-12.41 → roam_code-12.43}/tests/test_git_utils.py +0 -0
  514. {roam_code-12.41 → roam_code-12.43}/tests/test_guard.py +0 -0
  515. {roam_code-12.41 → roam_code-12.43}/tests/test_health_gate.py +0 -0
  516. {roam_code-12.41 → roam_code-12.43}/tests/test_hooks.py +0 -0
  517. {roam_code-12.41 → roam_code-12.43}/tests/test_hotspots.py +0 -0
  518. {roam_code-12.41 → roam_code-12.43}/tests/test_hover.py +0 -0
  519. {roam_code-12.41 → roam_code-12.43}/tests/test_index.py +0 -0
  520. {roam_code-12.41 → roam_code-12.43}/tests/test_index_bundle.py +0 -0
  521. {roam_code-12.41 → roam_code-12.43}/tests/test_init_cmd.py +0 -0
  522. {roam_code-12.41 → roam_code-12.43}/tests/test_install_check.py +0 -0
  523. {roam_code-12.41 → roam_code-12.43}/tests/test_intent.py +0 -0
  524. {roam_code-12.41 → roam_code-12.43}/tests/test_invariants.py +0 -0
  525. {roam_code-12.41 → roam_code-12.43}/tests/test_json_contracts.py +0 -0
  526. {roam_code-12.41 → roam_code-12.43}/tests/test_json_error_envelope.py +0 -0
  527. {roam_code-12.41 → roam_code-12.43}/tests/test_kotlin_swift_extractors.py +0 -0
  528. {roam_code-12.41 → roam_code-12.43}/tests/test_language_corpus.py +0 -0
  529. {roam_code-12.41 → roam_code-12.43}/tests/test_languages.py +0 -0
  530. {roam_code-12.41 → roam_code-12.43}/tests/test_laravel_fp_fixes.py +0 -0
  531. {roam_code-12.41 → roam_code-12.43}/tests/test_library_api.py +0 -0
  532. {roam_code-12.41 → roam_code-12.43}/tests/test_math.py +0 -0
  533. {roam_code-12.41 → roam_code-12.43}/tests/test_math_fp_fixes.py +0 -0
  534. {roam_code-12.41 → roam_code-12.43}/tests/test_math_tips.py +0 -0
  535. {roam_code-12.41 → roam_code-12.43}/tests/test_mcp_extras.py +0 -0
  536. {roam_code-12.41 → roam_code-12.43}/tests/test_mcp_server.py +0 -0
  537. {roam_code-12.41 → roam_code-12.43}/tests/test_mcp_setup.py +0 -0
  538. {roam_code-12.41 → roam_code-12.43}/tests/test_mermaid.py +0 -0
  539. {roam_code-12.41 → roam_code-12.43}/tests/test_metrics_cmd.py +0 -0
  540. {roam_code-12.41 → roam_code-12.43}/tests/test_metrics_push.py +0 -0
  541. {roam_code-12.41 → roam_code-12.43}/tests/test_migration_safety.py +0 -0
  542. {roam_code-12.41 → roam_code-12.43}/tests/test_minimap.py +0 -0
  543. {roam_code-12.41 → roam_code-12.43}/tests/test_missing_index.py +0 -0
  544. {roam_code-12.41 → roam_code-12.43}/tests/test_mutate.py +0 -0
  545. {roam_code-12.41 → roam_code-12.43}/tests/test_n1.py +0 -0
  546. {roam_code-12.41 → roam_code-12.43}/tests/test_next_steps.py +0 -0
  547. {roam_code-12.41 → roam_code-12.43}/tests/test_onboard.py +0 -0
  548. {roam_code-12.41 → roam_code-12.43}/tests/test_oracle.py +0 -0
  549. {roam_code-12.41 → roam_code-12.43}/tests/test_orchestrate.py +0 -0
  550. {roam_code-12.41 → roam_code-12.43}/tests/test_orphan_routes.py +0 -0
  551. {roam_code-12.41 → roam_code-12.43}/tests/test_oss_bench_harness.py +0 -0
  552. {roam_code-12.41 → roam_code-12.43}/tests/test_over_fetch.py +0 -0
  553. {roam_code-12.41 → roam_code-12.43}/tests/test_pagerank_truncation.py +0 -0
  554. {roam_code-12.41 → roam_code-12.43}/tests/test_partition.py +0 -0
  555. {roam_code-12.41 → roam_code-12.43}/tests/test_path_coverage.py +0 -0
  556. {roam_code-12.41 → roam_code-12.43}/tests/test_patterns_cmd.py +0 -0
  557. {roam_code-12.41 → roam_code-12.43}/tests/test_performance.py +0 -0
  558. {roam_code-12.41 → roam_code-12.43}/tests/test_personalized_pagerank.py +0 -0
  559. {roam_code-12.41 → roam_code-12.43}/tests/test_pivot_phase0_commands.py +0 -0
  560. {roam_code-12.41 → roam_code-12.43}/tests/test_plan.py +0 -0
  561. {roam_code-12.41 → roam_code-12.43}/tests/test_plugin_discovery.py +0 -0
  562. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_analyze.py +0 -0
  563. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_analyze_cache.py +0 -0
  564. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_analyze_edge_cases.py +0 -0
  565. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_analyze_helpers.py +0 -0
  566. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_analyze_v2_signals.py +0 -0
  567. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_comment_render.py +0 -0
  568. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_comment_script.py +0 -0
  569. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_diff.py +0 -0
  570. {roam_code-12.41 → roam_code-12.43}/tests/test_pr_risk_author.py +0 -0
  571. {roam_code-12.41 → roam_code-12.43}/tests/test_progress.py +0 -0
  572. {roam_code-12.41 → roam_code-12.43}/tests/test_progressive_disclosure.py +0 -0
  573. {roam_code-12.41 → roam_code-12.43}/tests/test_properties.py +0 -0
  574. {roam_code-12.41 → roam_code-12.43}/tests/test_pytest_fixtures.py +0 -0
  575. {roam_code-12.41 → roam_code-12.43}/tests/test_python_extractor_v2.py +0 -0
  576. {roam_code-12.41 → roam_code-12.43}/tests/test_python_idioms_e2e.py +0 -0
  577. {roam_code-12.41 → roam_code-12.43}/tests/test_python_pivot.py +0 -0
  578. {roam_code-12.41 → roam_code-12.43}/tests/test_readme_surface_consistency.py +0 -0
  579. {roam_code-12.41 → roam_code-12.43}/tests/test_realworld_feedback.py +0 -0
  580. {roam_code-12.41 → roam_code-12.43}/tests/test_refactoring_intelligence.py +0 -0
  581. {roam_code-12.41 → roam_code-12.43}/tests/test_registry_dispatch.py +0 -0
  582. {roam_code-12.41 → roam_code-12.43}/tests/test_regression_fp_corpus.py +0 -0
  583. {roam_code-12.41 → roam_code-12.43}/tests/test_relate.py +0 -0
  584. {roam_code-12.41 → roam_code-12.43}/tests/test_report.py +0 -0
  585. {roam_code-12.41 → roam_code-12.43}/tests/test_reset_clean.py +0 -0
  586. {roam_code-12.41 → roam_code-12.43}/tests/test_resolve.py +0 -0
  587. {roam_code-12.41 → roam_code-12.43}/tests/test_retrieve.py +0 -0
  588. {roam_code-12.41 → roam_code-12.43}/tests/test_retrieve_cross_repo.py +0 -0
  589. {roam_code-12.41 → roam_code-12.43}/tests/test_retrieve_seeds.py +0 -0
  590. {roam_code-12.41 → roam_code-12.43}/tests/test_risk.py +0 -0
  591. {roam_code-12.41 → roam_code-12.43}/tests/test_ruby.py +0 -0
  592. {roam_code-12.41 → roam_code-12.43}/tests/test_rule_profiles.py +0 -0
  593. {roam_code-12.41 → roam_code-12.43}/tests/test_rules.py +0 -0
  594. {roam_code-12.41 → roam_code-12.43}/tests/test_rules_ast_match.py +0 -0
  595. {roam_code-12.41 → roam_code-12.43}/tests/test_rules_community_pack.py +0 -0
  596. {roam_code-12.41 → roam_code-12.43}/tests/test_rules_dataflow.py +0 -0
  597. {roam_code-12.41 → roam_code-12.43}/tests/test_rules_symbol_requirements.py +0 -0
  598. {roam_code-12.41 → roam_code-12.43}/tests/test_rules_validate.py +0 -0
  599. {roam_code-12.41 → roam_code-12.43}/tests/test_runtime.py +0 -0
  600. {roam_code-12.41 → roam_code-12.43}/tests/test_runtime_score.py +0 -0
  601. {roam_code-12.41 → roam_code-12.43}/tests/test_salesforce.py +0 -0
  602. {roam_code-12.41 → roam_code-12.43}/tests/test_sarif_flag.py +0 -0
  603. {roam_code-12.41 → roam_code-12.43}/tests/test_sbom.py +0 -0
  604. {roam_code-12.41 → roam_code-12.43}/tests/test_scala.py +0 -0
  605. {roam_code-12.41 → roam_code-12.43}/tests/test_schema_versioning.py +0 -0
  606. {roam_code-12.41 → roam_code-12.43}/tests/test_search_explain.py +0 -0
  607. {roam_code-12.41 → roam_code-12.43}/tests/test_secrets.py +0 -0
  608. {roam_code-12.41 → roam_code-12.43}/tests/test_secrets_v2.py +0 -0
  609. {roam_code-12.41 → roam_code-12.43}/tests/test_semantic_diff.py +0 -0
  610. {roam_code-12.41 → roam_code-12.43}/tests/test_semantic_onnx.py +0 -0
  611. {roam_code-12.41 → roam_code-12.43}/tests/test_semantic_search.py +0 -0
  612. {roam_code-12.41 → roam_code-12.43}/tests/test_simulate.py +0 -0
  613. {roam_code-12.41 → roam_code-12.43}/tests/test_simulate_departure.py +0 -0
  614. {roam_code-12.41 → roam_code-12.43}/tests/test_sketch.py +0 -0
  615. {roam_code-12.41 → roam_code-12.43}/tests/test_smells.py +0 -0
  616. {roam_code-12.41 → roam_code-12.43}/tests/test_smoke.py +0 -0
  617. {roam_code-12.41 → roam_code-12.43}/tests/test_sna_metrics.py +0 -0
  618. {roam_code-12.41 → roam_code-12.43}/tests/test_spectral.py +0 -0
  619. {roam_code-12.41 → roam_code-12.43}/tests/test_split_cmd.py +0 -0
  620. {roam_code-12.41 → roam_code-12.43}/tests/test_sql.py +0 -0
  621. {roam_code-12.41 → roam_code-12.43}/tests/test_suggest_reviewers.py +0 -0
  622. {roam_code-12.41 → roam_code-12.43}/tests/test_supply_chain.py +0 -0
  623. {roam_code-12.41 → roam_code-12.43}/tests/test_surface_counts.py +0 -0
  624. {roam_code-12.41 → roam_code-12.43}/tests/test_syntax_check.py +0 -0
  625. {roam_code-12.41 → roam_code-12.43}/tests/test_taint.py +0 -0
  626. {roam_code-12.41 → roam_code-12.43}/tests/test_taint_analysis.py +0 -0
  627. {roam_code-12.41 → roam_code-12.43}/tests/test_taint_classifier.py +0 -0
  628. {roam_code-12.41 → roam_code-12.43}/tests/test_taint_intraprocedural.py +0 -0
  629. {roam_code-12.41 → roam_code-12.43}/tests/test_test_conventions.py +0 -0
  630. {roam_code-12.41 → roam_code-12.43}/tests/test_test_gaps.py +0 -0
  631. {roam_code-12.41 → roam_code-12.43}/tests/test_test_scaffold.py +0 -0
  632. {roam_code-12.41 → roam_code-12.43}/tests/test_testmap.py +0 -0
  633. {roam_code-12.41 → roam_code-12.43}/tests/test_top_flag_consistency.py +0 -0
  634. {roam_code-12.41 → roam_code-12.43}/tests/test_tour_cmd.py +0 -0
  635. {roam_code-12.41 → roam_code-12.43}/tests/test_trends.py +0 -0
  636. {roam_code-12.41 → roam_code-12.43}/tests/test_trends_cohort.py +0 -0
  637. {roam_code-12.41 → roam_code-12.43}/tests/test_triage.py +0 -0
  638. {roam_code-12.41 → roam_code-12.43}/tests/test_uses_cmd.py +0 -0
  639. {roam_code-12.41 → roam_code-12.43}/tests/test_v1215_passes.py +0 -0
  640. {roam_code-12.41 → roam_code-12.43}/tests/test_v1216_passes.py +0 -0
  641. {roam_code-12.41 → roam_code-12.43}/tests/test_v1216_passes_41_50.py +0 -0
  642. {roam_code-12.41 → roam_code-12.43}/tests/test_v1216_passes_51_60.py +0 -0
  643. {roam_code-12.41 → roam_code-12.43}/tests/test_v1217_passes_61_80.py +0 -0
  644. {roam_code-12.41 → roam_code-12.43}/tests/test_v1218_passes_81_90.py +0 -0
  645. {roam_code-12.41 → roam_code-12.43}/tests/test_v1219_passes_91_100.py +0 -0
  646. {roam_code-12.41 → roam_code-12.43}/tests/test_v1220_passes_101_110.py +0 -0
  647. {roam_code-12.41 → roam_code-12.43}/tests/test_v1221_query_timeout.py +0 -0
  648. {roam_code-12.41 → roam_code-12.43}/tests/test_v1221_untested_commands.py +0 -0
  649. {roam_code-12.41 → roam_code-12.43}/tests/test_v12_2.py +0 -0
  650. {roam_code-12.41 → roam_code-12.43}/tests/test_v2_edge_cases.py +0 -0
  651. {roam_code-12.41 → roam_code-12.43}/tests/test_v2_integration.py +0 -0
  652. {roam_code-12.41 → roam_code-12.43}/tests/test_v6_features.py +0 -0
  653. {roam_code-12.41 → roam_code-12.43}/tests/test_v71_features.py +0 -0
  654. {roam_code-12.41 → roam_code-12.43}/tests/test_v7_features.py +0 -0
  655. {roam_code-12.41 → roam_code-12.43}/tests/test_v82_features.py +0 -0
  656. {roam_code-12.41 → roam_code-12.43}/tests/test_verify.py +0 -0
  657. {roam_code-12.41 → roam_code-12.43}/tests/test_verify_imports.py +0 -0
  658. {roam_code-12.41 → roam_code-12.43}/tests/test_vibe_check.py +0 -0
  659. {roam_code-12.41 → roam_code-12.43}/tests/test_visualize.py +0 -0
  660. {roam_code-12.41 → roam_code-12.43}/tests/test_vuln.py +0 -0
  661. {roam_code-12.41 → roam_code-12.43}/tests/test_vulns_cmd.py +0 -0
  662. {roam_code-12.41 → roam_code-12.43}/tests/test_watch.py +0 -0
  663. {roam_code-12.41 → roam_code-12.43}/tests/test_why.py +0 -0
  664. {roam_code-12.41 → roam_code-12.43}/tests/test_workspace.py +0 -0
  665. {roam_code-12.41 → roam_code-12.43}/tests/test_ws_resolve_fixes.py +0 -0
  666. {roam_code-12.41 → roam_code-12.43}/tests/test_xlang.py +0 -0
  667. {roam_code-12.41 → roam_code-12.43}/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.41
3
+ Version: 12.43
4
4
  Summary: Instant codebase comprehension for AI coding agents
5
5
  Author: CosmoHac
6
6
  License-Expression: Apache-2.0
@@ -64,9 +64,9 @@ Dynamic: license-file
64
64
 
65
65
  **Architectural sight for AI coding agents — before they edit.**
66
66
 
67
- 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 185 specialised commands are advanced surface for specialised workflows.
67
+ 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 188 specialised commands are advanced surface for specialised workflows.
68
68
 
69
- *190 commands · 136 MCP tools · 27 languages · 100% local · zero API keys*
69
+ *193 commands · 136 MCP tools · 27 languages · 100% local · zero API keys*
70
70
 
71
71
  [![PyPI version](https://img.shields.io/pypi/v/roam-code?style=flat-square&color=blue)](https://pypi.org/project/roam-code/)
72
72
  [![GitHub stars](https://img.shields.io/github/stars/Cranot/roam-code?style=flat-square)](https://github.com/Cranot/roam-code/stargazers)
@@ -334,7 +334,7 @@ roam health
334
334
 
335
335
  ## Commands
336
336
 
337
- **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 185 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 **190 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.
337
+ **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 188 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 **193 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.
338
338
 
339
339
  <details>
340
340
  <summary><strong>Full command reference</strong></summary>
@@ -383,6 +383,9 @@ roam health
383
383
  | `roam audit-trail-export [--format md\|json\|csv] [--since T] [--verdict V] [--aggregate]` | Export the audit trail for procurement / compliance review; `--aggregate` rolls up per actor / repo / verdict / month |
384
384
  | `roam audit-trail-conformance-check [--retention-days N] [--gate]` | Score the audit trail against an EU AI Act Article 12 checklist (chain integrity, timestamps, actors, reproducibility, retention) |
385
385
  | `roam article-12-check [--output F] [--pdf F]` | EU AI Act Article 12 readiness assessment; 6-item checklist → 1-page Markdown / PDF report. Captures Article-12-curious leads (Aug 2 2026 deadline). |
386
+ | `roam capabilities [--emit yaml\|json\|text] [--category X] [--ai-safe-only]` | Emit the decorator-driven capability registry — every command's machine-readable shape (inputs, outputs, ai_safe flag, since-version). For Roam Review GitHub App + MCP filtering. |
387
+ | `roam skill-generate [--target claude\|cursor\|continue\|aider] [--output F]` | Generate an agent-runtime skill manifest from the capability registry. SKILL.md / .mdc / config snippets — derived from decorators, never hand-edited. |
388
+ | `roam compare <baseline.db> <target.db> [--top N] [--threshold N]` | Structural delta between two indices: symbols added/removed/moved + per-file complexity deltas + IMPROVED/SIDEWAYS/REGRESSED verdict. The "did this refactor actually work?" tool. |
386
389
  | `roam permit [--staged] [--input F] [--symbol N]` | Structural-permission verdict facade for AI agents: ALLOW/REVIEW/BLOCK over critique + preflight + blast-radius. Exit codes 0/5/6 for Cursor rules / Claude Code hooks / pre-commit / CI gates. |
387
390
  | `roam postmortem <commit-range> [--limit N] [--show N]` | Replay current detectors against past commits; reports findings that would have surfaced pre-merge. The "would Roam have caught my Q1 incident?" demo. |
388
391
  | `roam rules-validate [PATH] [--against DIFF] [--strict] [--gate] [--explain]` | Lint a `.roam/rules.yml` for typos, schema mistakes, unknown patterns, duplicate IDs; optional dry-run against a sample diff |
@@ -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 185 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 188 specialised commands are advanced surface for specialised workflows.
8
8
 
9
- *190 commands · 136 MCP tools · 27 languages · 100% local · zero API keys*
9
+ *193 commands · 136 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)
@@ -274,7 +274,7 @@ roam health
274
274
 
275
275
  ## Commands
276
276
 
277
- **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 185 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 **190 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.
277
+ **Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 188 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 **193 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.
278
278
 
279
279
  <details>
280
280
  <summary><strong>Full command reference</strong></summary>
@@ -323,6 +323,9 @@ roam health
323
323
  | `roam audit-trail-export [--format md\|json\|csv] [--since T] [--verdict V] [--aggregate]` | Export the audit trail for procurement / compliance review; `--aggregate` rolls up per actor / repo / verdict / month |
324
324
  | `roam audit-trail-conformance-check [--retention-days N] [--gate]` | Score the audit trail against an EU AI Act Article 12 checklist (chain integrity, timestamps, actors, reproducibility, retention) |
325
325
  | `roam article-12-check [--output F] [--pdf F]` | EU AI Act Article 12 readiness assessment; 6-item checklist → 1-page Markdown / PDF report. Captures Article-12-curious leads (Aug 2 2026 deadline). |
326
+ | `roam capabilities [--emit yaml\|json\|text] [--category X] [--ai-safe-only]` | Emit the decorator-driven capability registry — every command's machine-readable shape (inputs, outputs, ai_safe flag, since-version). For Roam Review GitHub App + MCP filtering. |
327
+ | `roam skill-generate [--target claude\|cursor\|continue\|aider] [--output F]` | Generate an agent-runtime skill manifest from the capability registry. SKILL.md / .mdc / config snippets — derived from decorators, never hand-edited. |
328
+ | `roam compare <baseline.db> <target.db> [--top N] [--threshold N]` | Structural delta between two indices: symbols added/removed/moved + per-file complexity deltas + IMPROVED/SIDEWAYS/REGRESSED verdict. The "did this refactor actually work?" tool. |
326
329
  | `roam permit [--staged] [--input F] [--symbol N]` | Structural-permission verdict facade for AI agents: ALLOW/REVIEW/BLOCK over critique + preflight + blast-radius. Exit codes 0/5/6 for Cursor rules / Claude Code hooks / pre-commit / CI gates. |
327
330
  | `roam postmortem <commit-range> [--limit N] [--show N]` | Replay current detectors against past commits; reports findings that would have surfaced pre-merge. The "would Roam have caught my Q1 incident?" demo. |
328
331
  | `roam rules-validate [PATH] [--against DIFF] [--strict] [--gate] [--explain]` | Lint a `.roam/rules.yml` for typos, schema mistakes, unknown patterns, duplicate IDs; optional dry-run against a sample diff |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "roam-code"
7
- version = "12.41"
7
+ version = "12.43"
8
8
  description = "Instant codebase comprehension for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,250 @@
1
+ """Capability Registry — decorator-driven introspection for roam commands.
2
+
3
+ Phase 1 of the v2 monetization plan (per build_priorities.md). The
4
+ architect's correction: the per-command capability YAML must be derived
5
+ from decorators, not hand-edited. This module implements the decorator
6
+ plus an emitter that walks all registered commands and produces a
7
+ machine-readable manifest.
8
+
9
+ Usage:
10
+
11
+ from roam.capability import roam_capability
12
+
13
+ @roam_capability(
14
+ category="review",
15
+ summary="Verify a patch against the indexed graph.",
16
+ inputs=["diff_text"],
17
+ outputs=["verdict", "findings"],
18
+ ai_safe=True,
19
+ since="12.0",
20
+ )
21
+ @click.command()
22
+ def critique(...):
23
+ ...
24
+
25
+ The introspection layer (``CapabilityRegistry``) collects every
26
+ ``@roam_capability``-decorated callable when it's imported, and
27
+ ``emit_yaml`` / ``emit_json`` serialises the catalog.
28
+
29
+ The downstream consumer is the Roam Review GitHub App (Phase 2): it
30
+ reads the manifest at startup so it knows which commands are AI-safe to
31
+ expose as webhook actions vs which need human approval.
32
+ """
33
+
34
+ from __future__ import annotations
35
+
36
+ from dataclasses import dataclass, field
37
+ from typing import Any, Callable, TypeVar
38
+
39
+ F = TypeVar("F", bound=Callable[..., Any])
40
+
41
+
42
+ @dataclass(frozen=True)
43
+ class Capability:
44
+ """One decorated command's metadata."""
45
+
46
+ name: str
47
+ category: str
48
+ summary: str
49
+ inputs: tuple[str, ...] = ()
50
+ outputs: tuple[str, ...] = ()
51
+ examples: tuple[str, ...] = ()
52
+ tags: tuple[str, ...] = ()
53
+ ai_safe: bool = False
54
+ requires_index: bool = True
55
+ since: str | None = None
56
+ deprecated: bool = False
57
+ module: str = ""
58
+ func_name: str = ""
59
+
60
+
61
+ @dataclass
62
+ class CapabilityRegistry:
63
+ """Process-wide registry of capability-decorated callables.
64
+
65
+ Populated as a side-effect of importing any decorated command module.
66
+ """
67
+
68
+ items: dict[str, Capability] = field(default_factory=dict)
69
+
70
+ def register(self, cap: Capability) -> None:
71
+ if cap.name in self.items:
72
+ existing = self.items[cap.name]
73
+ if existing.module != cap.module:
74
+ raise ValueError(
75
+ f"capability name collision: {cap.name!r} already registered from "
76
+ f"{existing.module!r}; tried to register from {cap.module!r}"
77
+ )
78
+ self.items[cap.name] = cap
79
+
80
+ def get(self, name: str) -> Capability | None:
81
+ return self.items.get(name)
82
+
83
+ def all(self) -> list[Capability]:
84
+ return sorted(self.items.values(), key=lambda c: (c.category, c.name))
85
+
86
+ def by_category(self) -> dict[str, list[Capability]]:
87
+ out: dict[str, list[Capability]] = {}
88
+ for cap in self.all():
89
+ out.setdefault(cap.category, []).append(cap)
90
+ return out
91
+
92
+ def to_dict(self) -> dict[str, Any]:
93
+ return {
94
+ "schema_version": 1,
95
+ "generated_by": "roam.capability.CapabilityRegistry",
96
+ "count": len(self.items),
97
+ "capabilities": [
98
+ {
99
+ "name": cap.name,
100
+ "category": cap.category,
101
+ "summary": cap.summary,
102
+ "inputs": list(cap.inputs),
103
+ "outputs": list(cap.outputs),
104
+ "examples": list(cap.examples),
105
+ "tags": list(cap.tags),
106
+ "ai_safe": cap.ai_safe,
107
+ "requires_index": cap.requires_index,
108
+ "since": cap.since,
109
+ "deprecated": cap.deprecated,
110
+ "module": cap.module,
111
+ "func_name": cap.func_name,
112
+ }
113
+ for cap in self.all()
114
+ ],
115
+ }
116
+
117
+
118
+ REGISTRY = CapabilityRegistry()
119
+
120
+
121
+ def roam_capability(
122
+ *,
123
+ category: str,
124
+ summary: str,
125
+ name: str | None = None,
126
+ inputs: tuple[str, ...] | list[str] = (),
127
+ outputs: tuple[str, ...] | list[str] = (),
128
+ examples: tuple[str, ...] | list[str] = (),
129
+ tags: tuple[str, ...] | list[str] = (),
130
+ ai_safe: bool = False,
131
+ requires_index: bool = True,
132
+ since: str | None = None,
133
+ deprecated: bool = False,
134
+ ) -> Callable[[F], F]:
135
+ """Mark a Click command as a capability for introspection.
136
+
137
+ Place ABOVE ``@click.command()`` so the decorator wraps a Click
138
+ Command instance — the introspection then has access to the
139
+ Click metadata as well.
140
+ """
141
+
142
+ def deco(func: F) -> F:
143
+ cap_name = name or _derive_name(func)
144
+ # For Click Commands, the original module is on the callback
145
+ callback = getattr(func, "callback", None)
146
+ module = (
147
+ getattr(callback, "__module__", "")
148
+ if callback is not None
149
+ else getattr(func, "__module__", "")
150
+ )
151
+ func_name = (
152
+ getattr(callback, "__name__", "")
153
+ if callback is not None
154
+ else getattr(func, "__name__", "")
155
+ )
156
+ cap = Capability(
157
+ name=cap_name,
158
+ category=category,
159
+ summary=summary,
160
+ inputs=tuple(inputs),
161
+ outputs=tuple(outputs),
162
+ examples=tuple(examples),
163
+ tags=tuple(tags),
164
+ ai_safe=ai_safe,
165
+ requires_index=requires_index,
166
+ since=since,
167
+ deprecated=deprecated,
168
+ module=module,
169
+ func_name=func_name,
170
+ )
171
+ REGISTRY.register(cap)
172
+ # Stash on the function for later introspection (e.g. roam capabilities --explain X)
173
+ setattr(func, "__roam_capability__", cap)
174
+ return func
175
+
176
+ return deco
177
+
178
+
179
+ def _derive_name(func: Callable[..., Any]) -> str:
180
+ """Derive the CLI command name from the function or Click Command.
181
+
182
+ Order of preference:
183
+ 1. ``func.name`` — set by ``@click.command(name=...)``
184
+ 2. ``func.__name__`` — set by Python on a function
185
+ 3. ``func.callback.__name__`` — Click stores the original here
186
+ Strips a leading ``cmd_`` and converts underscores to dashes.
187
+ """
188
+ candidates: list[str] = []
189
+ name_attr = getattr(func, "name", None)
190
+ if isinstance(name_attr, str) and name_attr:
191
+ candidates.append(name_attr)
192
+ fn_name = getattr(func, "__name__", "")
193
+ if isinstance(fn_name, str) and fn_name:
194
+ candidates.append(fn_name)
195
+ callback = getattr(func, "callback", None)
196
+ if callback is not None:
197
+ cb_name = getattr(callback, "__name__", "")
198
+ if isinstance(cb_name, str) and cb_name:
199
+ candidates.append(cb_name)
200
+ for cand in candidates:
201
+ if cand and cand != "Command": # skip the click class name
202
+ if cand.startswith("cmd_"):
203
+ cand = cand[4:]
204
+ return cand.replace("_", "-")
205
+ return "<anonymous>"
206
+
207
+
208
+ def emit_yaml() -> str:
209
+ """Emit the capability catalog as YAML using the in-tree minimal emitter.
210
+
211
+ Avoids the PyYAML dependency to stay aligned with the rules engine's
212
+ fallback strategy (see roam.rules.engine._emit_simple_yaml).
213
+ """
214
+ data = REGISTRY.to_dict()
215
+ lines: list[str] = [
216
+ f"schema_version: {data['schema_version']}",
217
+ f"generated_by: {data['generated_by']}",
218
+ f"count: {data['count']}",
219
+ "capabilities:",
220
+ ]
221
+ for cap in data["capabilities"]:
222
+ lines.append(f" - name: {cap['name']}")
223
+ lines.append(f" category: {cap['category']}")
224
+ lines.append(f" summary: {_yaml_str(cap['summary'])}")
225
+ if cap["inputs"]:
226
+ lines.append(f" inputs: [{', '.join(_yaml_str(s) for s in cap['inputs'])}]")
227
+ if cap["outputs"]:
228
+ lines.append(f" outputs: [{', '.join(_yaml_str(s) for s in cap['outputs'])}]")
229
+ if cap["examples"]:
230
+ lines.append(" examples:")
231
+ for ex in cap["examples"]:
232
+ lines.append(f" - {_yaml_str(ex)}")
233
+ if cap["tags"]:
234
+ lines.append(f" tags: [{', '.join(_yaml_str(t) for t in cap['tags'])}]")
235
+ lines.append(f" ai_safe: {str(cap['ai_safe']).lower()}")
236
+ lines.append(f" requires_index: {str(cap['requires_index']).lower()}")
237
+ if cap["since"]:
238
+ lines.append(f" since: {_yaml_str(cap['since'])}")
239
+ if cap["deprecated"]:
240
+ lines.append(" deprecated: true")
241
+ lines.append(f" module: {cap['module']}")
242
+ lines.append(f" func_name: {cap['func_name']}")
243
+ return "\n".join(lines) + "\n"
244
+
245
+
246
+ def _yaml_str(s: str) -> str:
247
+ """Quote a string for YAML if needed."""
248
+ if any(c in s for c in (':', '#', '\n', '"', "'", '[', ']', '{', '}', ',', '&', '*', '!', '|', '>')):
249
+ return '"' + s.replace('\\', '\\\\').replace('"', '\\"') + '"'
250
+ return s
@@ -2485,6 +2485,135 @@ def detect_async_blocking_sleep(conn: sqlite3.Connection) -> list[dict]:
2485
2485
  return results
2486
2486
 
2487
2487
 
2488
+ # R5 (2026-05-07) — `asyncio.create_task(coro())` whose return value is
2489
+ # discarded. The task is gc-collected before it runs to completion. The
2490
+ # fix is to either store the task in a long-lived collection or `await`
2491
+ # it. PEP 649 / Python 3.11+ docs explicitly call this a footgun.
2492
+ _RE_FIRE_AND_FORGET_TASK = re.compile(
2493
+ r"^\s*(?:asyncio\.)?create_task\s*\(",
2494
+ re.MULTILINE,
2495
+ )
2496
+ _RE_STORED_TASK = re.compile(
2497
+ r"^\s*(?:\w+\s*[+\-*/]?=\s*|\w+\s*\.\s*append\s*\(\s*|\w+\s*\.\s*add\s*\(\s*|return\s+|await\s+)"
2498
+ r"(?:asyncio\.)?create_task\s*\(",
2499
+ re.MULTILINE,
2500
+ )
2501
+
2502
+
2503
+ def detect_async_fire_and_forget(conn: sqlite3.Connection) -> list[dict]:
2504
+ """``asyncio.create_task(...)`` whose return value is discarded.
2505
+
2506
+ Background tasks that aren't held in a long-lived reference get
2507
+ garbage-collected before they finish. Python 3.11+ explicitly warns
2508
+ about this footgun. The fix is to store the task somewhere that
2509
+ survives until ``await`` time, or just ``await`` it directly.
2510
+
2511
+ Conservative: Python only, only fires when the line clearly creates
2512
+ a task without storing it.
2513
+ """
2514
+ try:
2515
+ rows = conn.execute(
2516
+ "SELECT s.id, s.name, s.qualified_name, s.kind, f.path AS file_path, "
2517
+ "s.line_start, s.line_end "
2518
+ "FROM symbols s "
2519
+ "JOIN files f ON s.file_id = f.id "
2520
+ "WHERE s.kind IN ('function', 'method') "
2521
+ "AND f.language = 'python'"
2522
+ ).fetchall()
2523
+ except Exception:
2524
+ return []
2525
+ results = []
2526
+ for r in rows:
2527
+ if _is_test_path(r["file_path"]):
2528
+ continue
2529
+ snippet = _read_symbol_source(r["file_path"], r["line_start"], r["line_end"]) or ""
2530
+ if "create_task" not in snippet:
2531
+ continue
2532
+ # Subtract stored-task lines from total create_task occurrences
2533
+ total = len(_RE_FIRE_AND_FORGET_TASK.findall(snippet))
2534
+ stored = len(_RE_STORED_TASK.findall(snippet))
2535
+ leaked = total - stored
2536
+ if leaked <= 0:
2537
+ continue
2538
+ results.append(
2539
+ _finding(
2540
+ "async-fire-and-forget-task",
2541
+ "leaked-asyncio-task",
2542
+ r,
2543
+ f"{leaked} asyncio.create_task call(s) whose return value isn't stored — gc may discard the task before it completes",
2544
+ "high",
2545
+ snippet=snippet,
2546
+ matched_patterns=[
2547
+ f"create_task occurrences: {total}",
2548
+ f"stored: {stored}, leaked: {leaked}",
2549
+ ],
2550
+ )
2551
+ )
2552
+ results[-1]["fix"] = "Store the task: `tasks.append(asyncio.create_task(coro()))` and await it later, or `await asyncio.create_task(coro())` directly."
2553
+ return results
2554
+
2555
+
2556
+ # R5 (2026-05-07) — `asyncio.run(...)` inside an async function. This
2557
+ # raises RuntimeError because the event loop is already running. The
2558
+ # fix is to call the coroutine directly with `await` instead.
2559
+ _RE_NESTED_ASYNCIO_RUN = re.compile(
2560
+ r"^\s*(?:asyncio\.)?run\s*\(",
2561
+ re.MULTILINE,
2562
+ )
2563
+
2564
+
2565
+ def detect_async_nested_run(conn: sqlite3.Connection) -> list[dict]:
2566
+ """``asyncio.run()`` invoked inside another async function.
2567
+
2568
+ ``asyncio.run`` creates a new event loop. If one is already running
2569
+ (which it is, inside an async function), this raises ``RuntimeError:
2570
+ asyncio.run() cannot be called from a running event loop``. The fix
2571
+ is to ``await`` the coroutine directly.
2572
+
2573
+ Python only, fires only when the host is async.
2574
+ """
2575
+ try:
2576
+ rows = conn.execute(
2577
+ "SELECT s.id, s.name, s.qualified_name, s.kind, f.path AS file_path, "
2578
+ "s.line_start, s.line_end "
2579
+ "FROM symbols s "
2580
+ "JOIN files f ON s.file_id = f.id "
2581
+ "WHERE s.kind IN ('function', 'method') "
2582
+ "AND s.is_async = 1 "
2583
+ "AND f.language = 'python'"
2584
+ ).fetchall()
2585
+ except Exception:
2586
+ return []
2587
+ results = []
2588
+ for r in rows:
2589
+ if _is_test_path(r["file_path"]):
2590
+ continue
2591
+ snippet = _read_symbol_source(r["file_path"], r["line_start"], r["line_end"]) or ""
2592
+ if "asyncio.run(" not in snippet:
2593
+ continue
2594
+ # Heuristic: must be `asyncio.run(` (not `await asyncio.run(`); the
2595
+ # latter is also wrong but caught by other linters more reliably.
2596
+ match_count = snippet.count("asyncio.run(")
2597
+ if match_count == 0:
2598
+ continue
2599
+ results.append(
2600
+ _finding(
2601
+ "async-nested-run",
2602
+ "asyncio-run-in-async",
2603
+ r,
2604
+ "asyncio.run() invoked inside an async function — raises RuntimeError at runtime (loop already running)",
2605
+ "high",
2606
+ snippet=snippet,
2607
+ matched_patterns=[
2608
+ "is_async = 1",
2609
+ f"asyncio.run( occurrences: {match_count}",
2610
+ ],
2611
+ )
2612
+ )
2613
+ results[-1]["fix"] = "Replace `asyncio.run(coro())` with `await coro()` — you're already inside an event loop."
2614
+ return results
2615
+
2616
+
2488
2617
  # X2 (2026-05-06) — Python: `except Exception:` / `except BaseException:`
2489
2618
  # without `raise` is the canonical "swallowing bug" pattern. Catches
2490
2619
  # KeyboardInterrupt, MemoryError, SystemExit silently. The fix is to
@@ -3927,6 +4056,8 @@ _MATH_DETECTORS = [
3927
4056
  ("io-in-loop", "loop-query", detect_io_in_loop),
3928
4057
  ("serial-await-loop", "for-of-await", detect_serial_await_loop),
3929
4058
  ("async-blocking-sleep", "blocking-call-in-async", detect_async_blocking_sleep),
4059
+ ("async-fire-and-forget-task", "leaked-asyncio-task", detect_async_fire_and_forget),
4060
+ ("async-nested-run", "asyncio-run-in-async", detect_async_nested_run),
3930
4061
  ("broad-except-swallow", "swallow-exception", detect_broad_except_swallow),
3931
4062
  ("spread-accumulator", "spread-rebind", detect_spread_accumulator),
3932
4063
  ("defer-in-loop", "loop-defer", detect_defer_in_loop),
@@ -86,6 +86,9 @@ _COMMANDS = {
86
86
  "permit": ("roam.commands.cmd_permit", "permit_cmd"),
87
87
  "postmortem": ("roam.commands.cmd_postmortem", "postmortem_cmd"),
88
88
  "article-12-check": ("roam.commands.cmd_article_12_check", "article_12_check_cmd"),
89
+ "capabilities": ("roam.commands.cmd_capabilities", "capabilities_cmd"),
90
+ "skill-generate": ("roam.commands.cmd_skill_generate", "skill_generate_cmd"),
91
+ "compare": ("roam.commands.cmd_compare", "compare_cmd"),
89
92
  "guard": ("roam.commands.cmd_guard", "guard"),
90
93
  "init": ("roam.commands.cmd_init", "init"),
91
94
  "config": ("roam.commands.cmd_config", "config"),
@@ -290,6 +293,9 @@ _CATEGORIES = {
290
293
  "audit-trail-export",
291
294
  "audit-trail-conformance-check",
292
295
  "article-12-check",
296
+ "capabilities",
297
+ "skill-generate",
298
+ "compare",
293
299
  "dogfood",
294
300
  "suppress",
295
301
  "pr-diff",
@@ -295,6 +295,23 @@ def _render_pdf_report(markdown_text: str, output_path: Path) -> bool:
295
295
  return True
296
296
 
297
297
 
298
+ from roam.capability import roam_capability
299
+
300
+
301
+ @roam_capability(
302
+ category="compliance",
303
+ summary="EU AI Act Article 12 readiness assessment — 6-item checklist over the current repo.",
304
+ inputs=["repo_path"],
305
+ outputs=["readiness_score", "checklist_results", "markdown_report"],
306
+ examples=[
307
+ "roam article-12-check",
308
+ "roam article-12-check --pdf report.pdf",
309
+ ],
310
+ tags=["compliance", "eu-ai-act", "audit", "phase0"],
311
+ ai_safe=True,
312
+ requires_index=False,
313
+ since="12.40",
314
+ )
298
315
  @click.command(name="article-12-check")
299
316
  @click.option(
300
317
  "--output",
@@ -0,0 +1,129 @@
1
+ """roam capabilities — emit the capability registry as YAML / JSON.
2
+
3
+ Phase 1 of the v2 monetization plan. Reads the in-process
4
+ ``roam.capability.REGISTRY`` (populated by ``@roam_capability``
5
+ decorators on commands as they're imported) and writes a manifest
6
+ suitable for downstream consumers (Roam Review GitHub App, MCP server,
7
+ documentation generators).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+
14
+ import click
15
+
16
+ from roam.capability import REGISTRY, emit_yaml
17
+ from roam.output.formatter import json_envelope, to_json
18
+
19
+
20
+ @click.command()
21
+ @click.option(
22
+ "--emit",
23
+ type=click.Choice(["yaml", "json", "text"]),
24
+ default="text",
25
+ show_default=True,
26
+ help="Output format. yaml/json for machine consumption, text for human reading.",
27
+ )
28
+ @click.option(
29
+ "--category",
30
+ type=str,
31
+ default=None,
32
+ help="Filter to one category (e.g. review, refactor, architecture).",
33
+ )
34
+ @click.option(
35
+ "--ai-safe-only",
36
+ is_flag=True,
37
+ help="Show only capabilities marked ai_safe=True (safe for an AI agent to call without human approval).",
38
+ )
39
+ @click.pass_context
40
+ def capabilities_cmd(ctx, emit: str, category: str | None, ai_safe_only: bool) -> None:
41
+ """Emit the capability registry — every command's machine-readable shape.
42
+
43
+ The manifest is what the Roam Review GitHub App reads to decide which
44
+ commands an AI agent can call without human approval, and what tools
45
+ the MCP server should expose by default.
46
+
47
+ Imports trigger registration. Run ``roam capabilities --emit yaml``
48
+ to produce a stable manifest after every release.
49
+ """
50
+ # Force-load known command modules so the registry is populated.
51
+ _populate_registry()
52
+
53
+ items = REGISTRY.all()
54
+ if category:
55
+ items = [c for c in items if c.category == category]
56
+ if ai_safe_only:
57
+ items = [c for c in items if c.ai_safe]
58
+
59
+ json_mode = ctx.obj.get("json") if ctx.obj else False
60
+
61
+ if emit == "yaml":
62
+ click.echo(emit_yaml())
63
+ return
64
+ if emit == "json" or json_mode:
65
+ envelope = json_envelope(
66
+ "capabilities",
67
+ summary={
68
+ "count": len(items),
69
+ "category_filter": category,
70
+ "ai_safe_only": ai_safe_only,
71
+ },
72
+ capabilities=[
73
+ {
74
+ "name": c.name,
75
+ "category": c.category,
76
+ "summary": c.summary,
77
+ "inputs": list(c.inputs),
78
+ "outputs": list(c.outputs),
79
+ "ai_safe": c.ai_safe,
80
+ "since": c.since,
81
+ }
82
+ for c in items
83
+ ],
84
+ )
85
+ click.echo(to_json(envelope))
86
+ return
87
+
88
+ # Text output
89
+ if not items:
90
+ click.echo("No registered capabilities (registry empty).")
91
+ return
92
+ click.echo(f"{len(items)} registered capabilities:")
93
+ last_cat = None
94
+ for c in items:
95
+ if c.category != last_cat:
96
+ click.echo(f"\n [{c.category}]")
97
+ last_cat = c.category
98
+ flags = []
99
+ if c.ai_safe:
100
+ flags.append("ai-safe")
101
+ if c.deprecated:
102
+ flags.append("deprecated")
103
+ flag_str = f" ({', '.join(flags)})" if flags else ""
104
+ click.echo(f" {c.name:30} {c.summary}{flag_str}")
105
+
106
+
107
+ def _populate_registry() -> None:
108
+ """Import known capability-decorated command modules to populate the registry.
109
+
110
+ Today this lists commands explicitly. Once the decorator has been
111
+ applied to all 190 commands, this becomes a sweep of
112
+ ``roam.commands.cmd_*``.
113
+ """
114
+ import importlib
115
+
116
+ decorated_modules = [
117
+ "roam.commands.cmd_critique",
118
+ "roam.commands.cmd_preflight",
119
+ "roam.commands.cmd_understand",
120
+ "roam.commands.cmd_permit",
121
+ "roam.commands.cmd_postmortem",
122
+ "roam.commands.cmd_article_12_check",
123
+ ]
124
+ for mod in decorated_modules:
125
+ try:
126
+ importlib.import_module(mod)
127
+ except Exception:
128
+ # Best-effort; if a command module fails to import, skip it
129
+ pass