roam-code 8.2.0__tar.gz → 9.0.0__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 (169) hide show
  1. {roam_code-8.2.0 → roam_code-9.0.0}/PKG-INFO +30 -13
  2. {roam_code-8.2.0 → roam_code-9.0.0}/README.md +28 -11
  3. {roam_code-8.2.0 → roam_code-9.0.0}/pyproject.toml +2 -2
  4. roam_code-9.0.0/src/roam/catalog/detectors.py +959 -0
  5. roam_code-9.0.0/src/roam/catalog/tasks.py +246 -0
  6. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/cli.py +2 -1
  7. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_affected_tests.py +30 -3
  8. roam_code-9.0.0/src/roam/commands/cmd_clusters.py +315 -0
  9. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_dead.py +80 -87
  10. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_describe.py +82 -79
  11. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_health.py +11 -3
  12. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_impact.py +62 -68
  13. roam_code-9.0.0/src/roam/commands/cmd_layers.py +248 -0
  14. roam_code-9.0.0/src/roam/commands/cmd_math.py +130 -0
  15. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_module.py +55 -57
  16. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_pr_risk.py +85 -26
  17. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_understand.py +156 -98
  18. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_why.py +112 -112
  19. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/metrics_history.py +86 -50
  20. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/db/connection.py +6 -0
  21. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/db/schema.py +16 -0
  22. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/complexity.py +361 -5
  23. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/indexer.py +229 -246
  24. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/parser.py +2 -0
  25. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/relations.py +52 -39
  26. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/test_conventions.py +155 -0
  27. roam_code-9.0.0/src/roam/languages/csharp_lang.py +1126 -0
  28. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/foxpro_lang.py +129 -117
  29. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/generic_lang.py +107 -117
  30. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/javascript_lang.py +74 -91
  31. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/php_lang.py +31 -46
  32. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/python_lang.py +70 -49
  33. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/registry.py +5 -1
  34. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/mcp_server.py +28 -0
  35. roam_code-9.0.0/src/roam/output/__init__.py +0 -0
  36. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/workspace/db.py +0 -35
  37. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/PKG-INFO +30 -13
  38. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/SOURCES.txt +7 -0
  39. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_anomaly.py +3 -3
  40. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_commands_health.py +26 -0
  41. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_commands_workflow.py +35 -0
  42. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_comprehensive.py +42 -25
  43. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_fixes.py +14 -14
  44. roam_code-9.0.0/tests/test_framework_detection.py +277 -0
  45. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_languages.py +641 -1
  46. roam_code-9.0.0/tests/test_math.py +853 -0
  47. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_pr_risk_author.py +31 -0
  48. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_python_extractor_v2.py +23 -0
  49. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_resolve.py +13 -13
  50. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_salesforce.py +4 -4
  51. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_test_conventions.py +76 -1
  52. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_v6_features.py +2 -2
  53. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_v7_features.py +4 -4
  54. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_visualize.py +4 -4
  55. roam_code-8.2.0/src/roam/commands/cmd_clusters.py +0 -320
  56. roam_code-8.2.0/src/roam/commands/cmd_layers.py +0 -244
  57. {roam_code-8.2.0 → roam_code-9.0.0}/LICENSE +0 -0
  58. {roam_code-8.2.0 → roam_code-9.0.0}/setup.cfg +0 -0
  59. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/__init__.py +0 -0
  60. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/__main__.py +0 -0
  61. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/bridges/__init__.py +0 -0
  62. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/bridges/base.py +0 -0
  63. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/bridges/bridge_protobuf.py +0 -0
  64. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/bridges/bridge_salesforce.py +0 -0
  65. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/bridges/registry.py +0 -0
  66. {roam_code-8.2.0/src/roam/commands → roam_code-9.0.0/src/roam/catalog}/__init__.py +0 -0
  67. {roam_code-8.2.0/src/roam/db → roam_code-9.0.0/src/roam/commands}/__init__.py +0 -0
  68. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/changed_files.py +0 -0
  69. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_alerts.py +0 -0
  70. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_breaking.py +0 -0
  71. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_bus_factor.py +0 -0
  72. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_complexity.py +0 -0
  73. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_context.py +0 -0
  74. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_conventions.py +0 -0
  75. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_coupling.py +0 -0
  76. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_coverage_gaps.py +0 -0
  77. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_debt.py +0 -0
  78. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_deps.py +0 -0
  79. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_diagnose.py +0 -0
  80. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_diff.py +0 -0
  81. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_digest.py +0 -0
  82. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_doc_staleness.py +0 -0
  83. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_entry_points.py +0 -0
  84. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_fan.py +0 -0
  85. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_file.py +0 -0
  86. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_fitness.py +0 -0
  87. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_fn_coupling.py +0 -0
  88. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_grep.py +0 -0
  89. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_index.py +0 -0
  90. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_init.py +0 -0
  91. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_map.py +0 -0
  92. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_owner.py +0 -0
  93. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_patterns.py +0 -0
  94. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_preflight.py +0 -0
  95. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_report.py +0 -0
  96. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_risk.py +0 -0
  97. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_safe_delete.py +0 -0
  98. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_safe_zones.py +0 -0
  99. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_search.py +0 -0
  100. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_sketch.py +0 -0
  101. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_snapshot.py +0 -0
  102. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_split.py +0 -0
  103. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_symbol.py +0 -0
  104. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_testmap.py +0 -0
  105. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_tour.py +0 -0
  106. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_trace.py +0 -0
  107. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_trend.py +0 -0
  108. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_uses.py +0 -0
  109. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_visualize.py +0 -0
  110. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_weather.py +0 -0
  111. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_ws.py +0 -0
  112. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/cmd_xlang.py +0 -0
  113. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/context_helpers.py +0 -0
  114. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/gate_presets.py +0 -0
  115. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/graph_helpers.py +0 -0
  116. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/commands/resolve.py +0 -0
  117. {roam_code-8.2.0/src/roam/output → roam_code-9.0.0/src/roam/db}/__init__.py +0 -0
  118. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/db/queries.py +0 -0
  119. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/__init__.py +0 -0
  120. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/anomaly.py +0 -0
  121. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/builder.py +0 -0
  122. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/clusters.py +0 -0
  123. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/cycles.py +0 -0
  124. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/layers.py +0 -0
  125. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/pagerank.py +0 -0
  126. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/graph/pathfinding.py +0 -0
  127. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/__init__.py +0 -0
  128. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/discovery.py +0 -0
  129. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/file_roles.py +0 -0
  130. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/git_stats.py +0 -0
  131. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/incremental.py +0 -0
  132. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/index/symbols.py +0 -0
  133. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/__init__.py +0 -0
  134. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/apex_lang.py +0 -0
  135. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/aura_lang.py +0 -0
  136. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/base.py +0 -0
  137. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/c_lang.py +0 -0
  138. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/go_lang.py +0 -0
  139. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/java_lang.py +0 -0
  140. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/rust_lang.py +0 -0
  141. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/sfxml_lang.py +0 -0
  142. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/typescript_lang.py +0 -0
  143. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/languages/visualforce_lang.py +0 -0
  144. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/output/formatter.py +0 -0
  145. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/output/sarif.py +0 -0
  146. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/workspace/__init__.py +0 -0
  147. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/workspace/aggregator.py +0 -0
  148. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/workspace/api_scanner.py +0 -0
  149. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam/workspace/config.py +0 -0
  150. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/dependency_links.txt +0 -0
  151. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/entry_points.txt +0 -0
  152. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/requires.txt +0 -0
  153. {roam_code-8.2.0 → roam_code-9.0.0}/src/roam_code.egg-info/top_level.txt +0 -0
  154. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_basic.py +0 -0
  155. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_bridges.py +0 -0
  156. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_commands_architecture.py +0 -0
  157. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_commands_exploration.py +0 -0
  158. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_commands_refactoring.py +0 -0
  159. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_dead_aging.py +0 -0
  160. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_file_roles.py +0 -0
  161. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_formatters.py +0 -0
  162. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_foxpro.py +0 -0
  163. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_gate_presets.py +0 -0
  164. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_json_contracts.py +0 -0
  165. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_performance.py +0 -0
  166. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_smoke.py +0 -0
  167. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_v71_features.py +0 -0
  168. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_v82_features.py +0 -0
  169. {roam_code-8.2.0 → roam_code-9.0.0}/tests/test_workspace.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roam-code
3
- Version: 8.2.0
3
+ Version: 9.0.0
4
4
  Summary: Instant codebase comprehension for AI coding agents
5
5
  Author: CosmoHac
6
- License-Expression: MIT
6
+ License: MIT
7
7
  Project-URL: Homepage, https://github.com/Cranot/roam-code
8
8
  Project-URL: Repository, https://github.com/Cranot/roam-code
9
9
  Project-URL: Issues, https://github.com/Cranot/roam-code/issues
@@ -211,7 +211,7 @@ roam health
211
211
 
212
212
  ## Commands
213
213
 
214
- The [5 core commands](#core-commands) shown above cover ~80% of agent workflows. 55 total commands are organized into 7 categories.
214
+ The [5 core commands](#core-commands) shown above cover ~80% of agent workflows. 56 total commands are organized into 7 categories.
215
215
 
216
216
  <details>
217
217
  <summary><strong>Full command reference</strong></summary>
@@ -252,6 +252,7 @@ The [5 core commands](#core-commands) shown above cover ~80% of agent workflows.
252
252
  |---------|-------------|
253
253
  | `roam health [--no-framework]` | Composite health score (0-100): weighted geometric mean of tangle ratio, god components, bottlenecks, layer violations. Includes propagation cost and algebraic connectivity |
254
254
  | `roam complexity [--bumpy-road]` | Per-function cognitive complexity (SonarSource-compatible, triangular nesting penalty) + Halstead metrics (volume, difficulty, effort, bugs) + cyclomatic density |
255
+ | `roam math [--task T] [--confidence C]` | Algorithm anti-pattern detection: 23-pattern catalog detects suboptimal algorithms (O(n^2) loops, N+1 queries, quadratic string building, branching recursion, loop-invariant calls) and suggests better approaches with Big-O improvements. Confidence calibration via caller-count and bounded-loop analysis |
255
256
  | `roam weather [-n N]` | Hotspots ranked by geometric mean of churn x complexity (percentile-normalized) |
256
257
  | `roam debt` | Hotspot-weighted tech debt prioritization with SQALE remediation cost estimates |
257
258
  | `roam fitness [--explain]` | Architectural fitness functions from `.roam/fitness.yaml` |
@@ -808,6 +809,7 @@ Zero infrastructure, zero vendor lock-in, zero data leaving your network.
808
809
  | Go | `.go` | structs, interfaces, functions, methods, fields | imports, calls | embedded structs |
809
810
  | Rust | `.rs` | structs, traits, impls, enums, functions | use, calls | impl Trait for Struct |
810
811
  | C / C++ | `.c` `.h` `.cpp` `.hpp` `.cc` | structs, classes, functions, namespaces, templates | includes, calls | extends |
812
+ | C# | `.cs` | classes, interfaces, structs, enums, records, methods, constructors, properties, delegates, events, fields | using directives, calls, `new`, attributes | extends, implements |
811
813
  | PHP | `.php` | classes, interfaces, traits, enums, methods, properties | namespace use, calls, static calls, `new` | extends, implements, use (traits) |
812
814
  | Visual FoxPro | `.prg` | functions, procedures, classes, methods, properties, constants | DO, SET PROCEDURE/CLASSLIB, CREATEOBJECT, `=func()`, `obj.method()` | DEFINE CLASS ... AS |
813
815
  | Vue | `.vue` | via `<script>` block extraction (TS/JS) | imports, calls, type refs | extends, implements |
@@ -830,7 +832,7 @@ Cross-language edges mean `roam impact AccountService` shows blast radius across
830
832
 
831
833
  ### Tier 2 -- Generic extraction
832
834
 
833
- Ruby (`.rb`), C# (`.cs`), Kotlin (`.kt` `.kts`), Swift (`.swift`), Scala (`.scala` `.sc`)
835
+ Ruby (`.rb`), Kotlin (`.kt` `.kts`), Swift (`.swift`), Scala (`.scala` `.sc`)
834
836
 
835
837
  Tier 2 languages get symbol extraction and basic inheritance via a generic tree-sitter walker.
836
838
 
@@ -986,7 +988,7 @@ Static analysis trade-offs:
986
988
  - **No runtime analysis** -- can't trace dynamic dispatch, reflection, or eval'd code
987
989
  - **Import resolution is heuristic** -- complex re-exports or conditional imports may not resolve
988
990
  - **Limited cross-language edges** -- Salesforce and multi-repo API edges are supported, but not arbitrary FFI
989
- - **Tier 2 languages** (Ruby, C#, Kotlin, Swift, Scala) get basic symbol extraction only
991
+ - **Tier 2 languages** (Ruby, Kotlin, Swift, Scala) get basic symbol extraction only
990
992
  - **Large monorepos** (100k+ files) may have slow initial indexing
991
993
 
992
994
  ## Troubleshooting
@@ -1023,7 +1025,7 @@ Delete `.roam/` from your project root to clean up local data.
1023
1025
  git clone https://github.com/Cranot/roam-code.git
1024
1026
  cd roam-code
1025
1027
  pip install -e ".[dev]" # includes pytest, ruff
1026
- pytest tests/ # 1729 tests, Python 3.9-3.13
1028
+ pytest tests/ # 1847 tests, Python 3.9-3.13
1027
1029
 
1028
1030
  # Or use Make targets:
1029
1031
  make dev # install with dev extras
@@ -1038,10 +1040,9 @@ make lint # ruff check
1038
1040
  roam-code/
1039
1041
  ├── pyproject.toml
1040
1042
  ├── action.yml # Reusable GitHub Action
1041
- ├── CHANGELOG.md
1042
1043
  ├── src/roam/
1043
1044
  │ ├── __init__.py # Version (from pyproject.toml)
1044
- │ ├── cli.py # Click CLI (55 commands, 7 categories)
1045
+ │ ├── cli.py # Click CLI (57 commands, 7 categories)
1045
1046
  │ ├── mcp_server.py # MCP server (19 tools, 2 resources)
1046
1047
  │ ├── db/
1047
1048
  │ │ ├── connection.py # SQLite (WAL, pragmas, batched IN)
@@ -1055,12 +1056,21 @@ roam-code/
1055
1056
  │ │ ├── relations.py # Reference resolution -> edges
1056
1057
  │ │ ├── complexity.py # Cognitive complexity (SonarSource) + Halstead metrics
1057
1058
  │ │ ├── git_stats.py # Churn, co-change, blame, Renyi entropy
1058
- │ │ └── incremental.py # mtime + hash change detection
1059
+ │ │ ├── incremental.py # mtime + hash change detection
1060
+ │ │ ├── file_roles.py # Smart file role classifier
1061
+ │ │ └── test_conventions.py # Pluggable test naming adapters
1059
1062
  │ ├── languages/
1060
1063
  │ │ ├── base.py # Abstract LanguageExtractor
1061
1064
  │ │ ├── registry.py # Language detection + aliasing
1062
- │ │ ├── *_lang.py # One file per language (13 Tier 1)
1065
+ │ │ ├── *_lang.py # One file per language (14 Tier 1)
1063
1066
  │ │ └── generic_lang.py # Tier 2 fallback
1067
+ │ ├── bridges/
1068
+ │ │ ├── base.py, registry.py # Cross-language bridge framework
1069
+ │ │ ├── bridge_salesforce.py # Apex <-> Aura/LWC/Visualforce
1070
+ │ │ └── bridge_protobuf.py # .proto -> Go/Java/Python stubs
1071
+ │ ├── catalog/
1072
+ │ │ ├── tasks.py # Universal algorithm catalog (23 patterns)
1073
+ │ │ └── detectors.py # Anti-pattern detectors with confidence calibration
1064
1074
  │ ├── workspace/
1065
1075
  │ │ ├── config.py # .roam-workspace.json
1066
1076
  │ │ ├── db.py # Workspace overlay DB
@@ -1071,15 +1081,17 @@ roam-code/
1071
1081
  │ │ ├── cycles.py, clusters.py # Tarjan SCC, propagation cost, Louvain, modularity Q
1072
1082
  │ │ ├── layers.py, pathfinding.py # Topo layers, k-shortest paths
1073
1083
  │ │ ├── split.py, why.py # Decomposition, role classification
1084
+ │ │ └── anomaly.py # Statistical anomaly detection
1074
1085
  │ ├── commands/
1075
1086
  │ │ ├── resolve.py # Shared symbol resolution
1076
1087
  │ │ ├── graph_helpers.py # Shared graph utilities (adj builders, BFS)
1077
1088
  │ │ ├── context_helpers.py # Data-gathering helpers for context command
1089
+ │ │ ├── gate_presets.py # Framework-specific gate rules
1078
1090
  │ │ └── cmd_*.py # One module per command
1079
1091
  │ └── output/
1080
1092
  │ ├── formatter.py # Token-efficient formatting
1081
1093
  │ └── sarif.py # SARIF 2.1.0 output
1082
- └── tests/ # 1729 tests across 30 test files
1094
+ └── tests/ # Test suite across 30+ test files
1083
1095
  ```
1084
1096
 
1085
1097
  </details>
@@ -1107,9 +1119,14 @@ Optional: [fastmcp](https://github.com/jlowin/fastmcp) (MCP server)
1107
1119
  - [x] Multi-repo workspace support (v7.4)
1108
1120
  - [x] Research-backed algorithms: adaptive PageRank, Personalized PageRank, Mann-Kendall, NPMI, Sen's slope, sigmoid-bounded health, Gini layer balance (v7.4)
1109
1121
  - [x] Advanced math: Halstead metrics, Renyi entropy, propagation cost, algebraic connectivity, modularity Q-score, conductance, edge betweenness, SQALE remediation cost, multiplicative PR risk, weighted geometric mean health, dead code confidence scoring, cyclomatic density (v7.5)
1122
+ - [x] C# Tier 1 support (v8.0)
1123
+ - [x] Deep Python extractor: instance attrs, assignment type refs, forward refs (v8.1)
1124
+ - [x] Internal complexity reduction: 50+ functions refactored below CC=25 (v9.0)
1125
+ - [x] Scoring math audit: fixed boolean-op double-counting, unified percentile implementations (v9.0)
1126
+ - [x] Test speed optimization: in-process indexing for fixtures (v9.0)
1127
+ - [x] Algorithm anti-pattern detection: 23-pattern catalog, AST signal extraction, confidence calibration (v9.0)
1110
1128
  - [ ] Terminal demo GIF
1111
1129
  - [ ] Ruby Tier 1 support
1112
- - [ ] C# Tier 1 support
1113
1130
  - [ ] `--sarif` CLI flag for direct SARIF export
1114
1131
  - [ ] Docker image for CI
1115
1132
  - [ ] VS Code extension
@@ -1120,7 +1137,7 @@ Optional: [fastmcp](https://github.com/jlowin/fastmcp) (MCP server)
1120
1137
  git clone https://github.com/Cranot/roam-code.git
1121
1138
  cd roam-code
1122
1139
  pip install -e .
1123
- pytest tests/ # All 1729 tests must pass
1140
+ pytest tests/ # All 1847 tests must pass
1124
1141
  ```
1125
1142
 
1126
1143
  Good first contributions: add a [Tier 1 language](src/roam/languages/) (see `go_lang.py` or `php_lang.py` as templates), improve reference resolution, add benchmark repos, extend SARIF converters, add MCP tools.
@@ -176,7 +176,7 @@ roam health
176
176
 
177
177
  ## Commands
178
178
 
179
- The [5 core commands](#core-commands) shown above cover ~80% of agent workflows. 55 total commands are organized into 7 categories.
179
+ The [5 core commands](#core-commands) shown above cover ~80% of agent workflows. 56 total commands are organized into 7 categories.
180
180
 
181
181
  <details>
182
182
  <summary><strong>Full command reference</strong></summary>
@@ -217,6 +217,7 @@ The [5 core commands](#core-commands) shown above cover ~80% of agent workflows.
217
217
  |---------|-------------|
218
218
  | `roam health [--no-framework]` | Composite health score (0-100): weighted geometric mean of tangle ratio, god components, bottlenecks, layer violations. Includes propagation cost and algebraic connectivity |
219
219
  | `roam complexity [--bumpy-road]` | Per-function cognitive complexity (SonarSource-compatible, triangular nesting penalty) + Halstead metrics (volume, difficulty, effort, bugs) + cyclomatic density |
220
+ | `roam math [--task T] [--confidence C]` | Algorithm anti-pattern detection: 23-pattern catalog detects suboptimal algorithms (O(n^2) loops, N+1 queries, quadratic string building, branching recursion, loop-invariant calls) and suggests better approaches with Big-O improvements. Confidence calibration via caller-count and bounded-loop analysis |
220
221
  | `roam weather [-n N]` | Hotspots ranked by geometric mean of churn x complexity (percentile-normalized) |
221
222
  | `roam debt` | Hotspot-weighted tech debt prioritization with SQALE remediation cost estimates |
222
223
  | `roam fitness [--explain]` | Architectural fitness functions from `.roam/fitness.yaml` |
@@ -773,6 +774,7 @@ Zero infrastructure, zero vendor lock-in, zero data leaving your network.
773
774
  | Go | `.go` | structs, interfaces, functions, methods, fields | imports, calls | embedded structs |
774
775
  | Rust | `.rs` | structs, traits, impls, enums, functions | use, calls | impl Trait for Struct |
775
776
  | C / C++ | `.c` `.h` `.cpp` `.hpp` `.cc` | structs, classes, functions, namespaces, templates | includes, calls | extends |
777
+ | C# | `.cs` | classes, interfaces, structs, enums, records, methods, constructors, properties, delegates, events, fields | using directives, calls, `new`, attributes | extends, implements |
776
778
  | PHP | `.php` | classes, interfaces, traits, enums, methods, properties | namespace use, calls, static calls, `new` | extends, implements, use (traits) |
777
779
  | Visual FoxPro | `.prg` | functions, procedures, classes, methods, properties, constants | DO, SET PROCEDURE/CLASSLIB, CREATEOBJECT, `=func()`, `obj.method()` | DEFINE CLASS ... AS |
778
780
  | Vue | `.vue` | via `<script>` block extraction (TS/JS) | imports, calls, type refs | extends, implements |
@@ -795,7 +797,7 @@ Cross-language edges mean `roam impact AccountService` shows blast radius across
795
797
 
796
798
  ### Tier 2 -- Generic extraction
797
799
 
798
- Ruby (`.rb`), C# (`.cs`), Kotlin (`.kt` `.kts`), Swift (`.swift`), Scala (`.scala` `.sc`)
800
+ Ruby (`.rb`), Kotlin (`.kt` `.kts`), Swift (`.swift`), Scala (`.scala` `.sc`)
799
801
 
800
802
  Tier 2 languages get symbol extraction and basic inheritance via a generic tree-sitter walker.
801
803
 
@@ -951,7 +953,7 @@ Static analysis trade-offs:
951
953
  - **No runtime analysis** -- can't trace dynamic dispatch, reflection, or eval'd code
952
954
  - **Import resolution is heuristic** -- complex re-exports or conditional imports may not resolve
953
955
  - **Limited cross-language edges** -- Salesforce and multi-repo API edges are supported, but not arbitrary FFI
954
- - **Tier 2 languages** (Ruby, C#, Kotlin, Swift, Scala) get basic symbol extraction only
956
+ - **Tier 2 languages** (Ruby, Kotlin, Swift, Scala) get basic symbol extraction only
955
957
  - **Large monorepos** (100k+ files) may have slow initial indexing
956
958
 
957
959
  ## Troubleshooting
@@ -988,7 +990,7 @@ Delete `.roam/` from your project root to clean up local data.
988
990
  git clone https://github.com/Cranot/roam-code.git
989
991
  cd roam-code
990
992
  pip install -e ".[dev]" # includes pytest, ruff
991
- pytest tests/ # 1729 tests, Python 3.9-3.13
993
+ pytest tests/ # 1847 tests, Python 3.9-3.13
992
994
 
993
995
  # Or use Make targets:
994
996
  make dev # install with dev extras
@@ -1003,10 +1005,9 @@ make lint # ruff check
1003
1005
  roam-code/
1004
1006
  ├── pyproject.toml
1005
1007
  ├── action.yml # Reusable GitHub Action
1006
- ├── CHANGELOG.md
1007
1008
  ├── src/roam/
1008
1009
  │ ├── __init__.py # Version (from pyproject.toml)
1009
- │ ├── cli.py # Click CLI (55 commands, 7 categories)
1010
+ │ ├── cli.py # Click CLI (57 commands, 7 categories)
1010
1011
  │ ├── mcp_server.py # MCP server (19 tools, 2 resources)
1011
1012
  │ ├── db/
1012
1013
  │ │ ├── connection.py # SQLite (WAL, pragmas, batched IN)
@@ -1020,12 +1021,21 @@ roam-code/
1020
1021
  │ │ ├── relations.py # Reference resolution -> edges
1021
1022
  │ │ ├── complexity.py # Cognitive complexity (SonarSource) + Halstead metrics
1022
1023
  │ │ ├── git_stats.py # Churn, co-change, blame, Renyi entropy
1023
- │ │ └── incremental.py # mtime + hash change detection
1024
+ │ │ ├── incremental.py # mtime + hash change detection
1025
+ │ │ ├── file_roles.py # Smart file role classifier
1026
+ │ │ └── test_conventions.py # Pluggable test naming adapters
1024
1027
  │ ├── languages/
1025
1028
  │ │ ├── base.py # Abstract LanguageExtractor
1026
1029
  │ │ ├── registry.py # Language detection + aliasing
1027
- │ │ ├── *_lang.py # One file per language (13 Tier 1)
1030
+ │ │ ├── *_lang.py # One file per language (14 Tier 1)
1028
1031
  │ │ └── generic_lang.py # Tier 2 fallback
1032
+ │ ├── bridges/
1033
+ │ │ ├── base.py, registry.py # Cross-language bridge framework
1034
+ │ │ ├── bridge_salesforce.py # Apex <-> Aura/LWC/Visualforce
1035
+ │ │ └── bridge_protobuf.py # .proto -> Go/Java/Python stubs
1036
+ │ ├── catalog/
1037
+ │ │ ├── tasks.py # Universal algorithm catalog (23 patterns)
1038
+ │ │ └── detectors.py # Anti-pattern detectors with confidence calibration
1029
1039
  │ ├── workspace/
1030
1040
  │ │ ├── config.py # .roam-workspace.json
1031
1041
  │ │ ├── db.py # Workspace overlay DB
@@ -1036,15 +1046,17 @@ roam-code/
1036
1046
  │ │ ├── cycles.py, clusters.py # Tarjan SCC, propagation cost, Louvain, modularity Q
1037
1047
  │ │ ├── layers.py, pathfinding.py # Topo layers, k-shortest paths
1038
1048
  │ │ ├── split.py, why.py # Decomposition, role classification
1049
+ │ │ └── anomaly.py # Statistical anomaly detection
1039
1050
  │ ├── commands/
1040
1051
  │ │ ├── resolve.py # Shared symbol resolution
1041
1052
  │ │ ├── graph_helpers.py # Shared graph utilities (adj builders, BFS)
1042
1053
  │ │ ├── context_helpers.py # Data-gathering helpers for context command
1054
+ │ │ ├── gate_presets.py # Framework-specific gate rules
1043
1055
  │ │ └── cmd_*.py # One module per command
1044
1056
  │ └── output/
1045
1057
  │ ├── formatter.py # Token-efficient formatting
1046
1058
  │ └── sarif.py # SARIF 2.1.0 output
1047
- └── tests/ # 1729 tests across 30 test files
1059
+ └── tests/ # Test suite across 30+ test files
1048
1060
  ```
1049
1061
 
1050
1062
  </details>
@@ -1072,9 +1084,14 @@ Optional: [fastmcp](https://github.com/jlowin/fastmcp) (MCP server)
1072
1084
  - [x] Multi-repo workspace support (v7.4)
1073
1085
  - [x] Research-backed algorithms: adaptive PageRank, Personalized PageRank, Mann-Kendall, NPMI, Sen's slope, sigmoid-bounded health, Gini layer balance (v7.4)
1074
1086
  - [x] Advanced math: Halstead metrics, Renyi entropy, propagation cost, algebraic connectivity, modularity Q-score, conductance, edge betweenness, SQALE remediation cost, multiplicative PR risk, weighted geometric mean health, dead code confidence scoring, cyclomatic density (v7.5)
1087
+ - [x] C# Tier 1 support (v8.0)
1088
+ - [x] Deep Python extractor: instance attrs, assignment type refs, forward refs (v8.1)
1089
+ - [x] Internal complexity reduction: 50+ functions refactored below CC=25 (v9.0)
1090
+ - [x] Scoring math audit: fixed boolean-op double-counting, unified percentile implementations (v9.0)
1091
+ - [x] Test speed optimization: in-process indexing for fixtures (v9.0)
1092
+ - [x] Algorithm anti-pattern detection: 23-pattern catalog, AST signal extraction, confidence calibration (v9.0)
1075
1093
  - [ ] Terminal demo GIF
1076
1094
  - [ ] Ruby Tier 1 support
1077
- - [ ] C# Tier 1 support
1078
1095
  - [ ] `--sarif` CLI flag for direct SARIF export
1079
1096
  - [ ] Docker image for CI
1080
1097
  - [ ] VS Code extension
@@ -1085,7 +1102,7 @@ Optional: [fastmcp](https://github.com/jlowin/fastmcp) (MCP server)
1085
1102
  git clone https://github.com/Cranot/roam-code.git
1086
1103
  cd roam-code
1087
1104
  pip install -e .
1088
- pytest tests/ # All 1729 tests must pass
1105
+ pytest tests/ # All 1847 tests must pass
1089
1106
  ```
1090
1107
 
1091
1108
  Good first contributions: add a [Tier 1 language](src/roam/languages/) (see `go_lang.py` or `php_lang.py` as templates), improve reference resolution, add benchmark repos, extend SARIF converters, add MCP tools.
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "roam-code"
7
- version = "8.2.0"
7
+ version = "9.0.0"
8
8
  description = "Instant codebase comprehension for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
11
- license = "MIT"
11
+ license = {text = "MIT"}
12
12
  authors = [
13
13
  {name = "CosmoHac"},
14
14
  ]