ripplet 0.1.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 (217) hide show
  1. ripplet-0.1.0.0/LICENSE +105 -0
  2. ripplet-0.1.0.0/PKG-INFO +375 -0
  3. ripplet-0.1.0.0/README.md +329 -0
  4. ripplet-0.1.0.0/pyproject.toml +68 -0
  5. ripplet-0.1.0.0/setup.cfg +4 -0
  6. ripplet-0.1.0.0/src/ripplet/__init__.py +7 -0
  7. ripplet-0.1.0.0/src/ripplet/change/__init__.py +0 -0
  8. ripplet-0.1.0.0/src/ripplet/change/check.py +949 -0
  9. ripplet-0.1.0.0/src/ripplet/change/plan.py +329 -0
  10. ripplet-0.1.0.0/src/ripplet/change/rename.py +148 -0
  11. ripplet-0.1.0.0/src/ripplet/change/review.py +197 -0
  12. ripplet-0.1.0.0/src/ripplet/change/revisions.py +160 -0
  13. ripplet-0.1.0.0/src/ripplet/change/rules.py +403 -0
  14. ripplet-0.1.0.0/src/ripplet/change/verify.py +80 -0
  15. ripplet-0.1.0.0/src/ripplet/cli.py +1328 -0
  16. ripplet-0.1.0.0/src/ripplet/config.py +100 -0
  17. ripplet-0.1.0.0/src/ripplet/context/__init__.py +2 -0
  18. ripplet-0.1.0.0/src/ripplet/context/agent_hooks.py +193 -0
  19. ripplet-0.1.0.0/src/ripplet/context/fileview.py +240 -0
  20. ripplet-0.1.0.0/src/ripplet/context/grepview.py +103 -0
  21. ripplet-0.1.0.0/src/ripplet/context/guard.py +287 -0
  22. ripplet-0.1.0.0/src/ripplet/context/hook.py +214 -0
  23. ripplet-0.1.0.0/src/ripplet/context/integrations.py +390 -0
  24. ripplet-0.1.0.0/src/ripplet/context/rules.py +392 -0
  25. ripplet-0.1.0.0/src/ripplet/core/__init__.py +3 -0
  26. ripplet-0.1.0.0/src/ripplet/core/confidence.py +8 -0
  27. ripplet-0.1.0.0/src/ripplet/core/errors.py +9 -0
  28. ripplet-0.1.0.0/src/ripplet/core/identifiers.py +75 -0
  29. ripplet-0.1.0.0/src/ripplet/core/models.py +97 -0
  30. ripplet-0.1.0.0/src/ripplet/core/provenance.py +13 -0
  31. ripplet-0.1.0.0/src/ripplet/core/schema.py +19 -0
  32. ripplet-0.1.0.0/src/ripplet/coverage/__init__.py +1 -0
  33. ripplet-0.1.0.0/src/ripplet/coverage/adapters/__init__.py +2 -0
  34. ripplet-0.1.0.0/src/ripplet/coverage/adapters/base.py +107 -0
  35. ripplet-0.1.0.0/src/ripplet/coverage/adapters/cobertura.py +111 -0
  36. ripplet-0.1.0.0/src/ripplet/coverage/adapters/coverage_py.py +83 -0
  37. ripplet-0.1.0.0/src/ripplet/coverage/adapters/istanbul.py +128 -0
  38. ripplet-0.1.0.0/src/ripplet/coverage/adapters/lcov.py +134 -0
  39. ripplet-0.1.0.0/src/ripplet/coverage/analysis.py +225 -0
  40. ripplet-0.1.0.0/src/ripplet/coverage/mapping.py +330 -0
  41. ripplet-0.1.0.0/src/ripplet/coverage/models.py +95 -0
  42. ripplet-0.1.0.0/src/ripplet/coverage/service.py +153 -0
  43. ripplet-0.1.0.0/src/ripplet/coverage/store.py +93 -0
  44. ripplet-0.1.0.0/src/ripplet/diagnostics.py +8 -0
  45. ripplet-0.1.0.0/src/ripplet/discovery/__init__.py +1 -0
  46. ripplet-0.1.0.0/src/ripplet/discovery/ignore_rules.py +107 -0
  47. ripplet-0.1.0.0/src/ripplet/discovery/manifests.py +32 -0
  48. ripplet-0.1.0.0/src/ripplet/discovery/scanner.py +59 -0
  49. ripplet-0.1.0.0/src/ripplet/discovery/watch.py +135 -0
  50. ripplet-0.1.0.0/src/ripplet/discovery/workspace.py +28 -0
  51. ripplet-0.1.0.0/src/ripplet/evaluation/__init__.py +1 -0
  52. ripplet-0.1.0.0/src/ripplet/evaluation/agent_bench.py +728 -0
  53. ripplet-0.1.0.0/src/ripplet/evaluation/benchmarks.py +4 -0
  54. ripplet-0.1.0.0/src/ripplet/evaluation/datasets.py +3 -0
  55. ripplet-0.1.0.0/src/ripplet/evaluation/import_bench.py +288 -0
  56. ripplet-0.1.0.0/src/ripplet/evaluation/metrics.py +17 -0
  57. ripplet-0.1.0.0/src/ripplet/evaluation/ranking_bench.py +182 -0
  58. ripplet-0.1.0.0/src/ripplet/evaluation/regression.py +11 -0
  59. ripplet-0.1.0.0/src/ripplet/evaluation/retrieval_bench.py +471 -0
  60. ripplet-0.1.0.0/src/ripplet/evaluation/selection_bench.py +353 -0
  61. ripplet-0.1.0.0/src/ripplet/evaluation/stageprofile.py +79 -0
  62. ripplet-0.1.0.0/src/ripplet/evaluation/token_accounting.py +135 -0
  63. ripplet-0.1.0.0/src/ripplet/exports/__init__.py +1 -0
  64. ripplet-0.1.0.0/src/ripplet/exports/graphml_exporter.py +10 -0
  65. ripplet-0.1.0.0/src/ripplet/exports/html_exporter.py +9 -0
  66. ripplet-0.1.0.0/src/ripplet/exports/json_exporter.py +18 -0
  67. ripplet-0.1.0.0/src/ripplet/exports/markdown_exporter.py +5 -0
  68. ripplet-0.1.0.0/src/ripplet/extraction/__init__.py +1 -0
  69. ripplet-0.1.0.0/src/ripplet/extraction/code/__init__.py +1 -0
  70. ripplet-0.1.0.0/src/ripplet/extraction/code/base.py +7 -0
  71. ripplet-0.1.0.0/src/ripplet/extraction/code/blade.py +117 -0
  72. ripplet-0.1.0.0/src/ripplet/extraction/code/call_graph.py +2 -0
  73. ripplet-0.1.0.0/src/ripplet/extraction/code/cpp_resolve.py +449 -0
  74. ripplet-0.1.0.0/src/ripplet/extraction/code/csharp_resolve.py +523 -0
  75. ripplet-0.1.0.0/src/ripplet/extraction/code/dart_resolve.py +508 -0
  76. ripplet-0.1.0.0/src/ripplet/extraction/code/gdscript_resolve.py +414 -0
  77. ripplet-0.1.0.0/src/ripplet/extraction/code/go_resolve.py +415 -0
  78. ripplet-0.1.0.0/src/ripplet/extraction/code/imports.py +1 -0
  79. ripplet-0.1.0.0/src/ripplet/extraction/code/java_resolve.py +563 -0
  80. ripplet-0.1.0.0/src/ripplet/extraction/code/js_resolve.py +658 -0
  81. ripplet-0.1.0.0/src/ripplet/extraction/code/jsts.py +1624 -0
  82. ripplet-0.1.0.0/src/ripplet/extraction/code/kotlin_resolve.py +610 -0
  83. ripplet-0.1.0.0/src/ripplet/extraction/code/lua_resolve.py +436 -0
  84. ripplet-0.1.0.0/src/ripplet/extraction/code/module_resolution.py +440 -0
  85. ripplet-0.1.0.0/src/ripplet/extraction/code/php_resolve.py +512 -0
  86. ripplet-0.1.0.0/src/ripplet/extraction/code/py_resolve.py +735 -0
  87. ripplet-0.1.0.0/src/ripplet/extraction/code/python_extractor.py +1449 -0
  88. ripplet-0.1.0.0/src/ripplet/extraction/code/route_resolve.py +510 -0
  89. ripplet-0.1.0.0/src/ripplet/extraction/code/ruby_resolve.py +227 -0
  90. ripplet-0.1.0.0/src/ripplet/extraction/code/rust_resolve.py +572 -0
  91. ripplet-0.1.0.0/src/ripplet/extraction/code/swift_resolve.py +516 -0
  92. ripplet-0.1.0.0/src/ripplet/extraction/code/symbols.py +2 -0
  93. ripplet-0.1.0.0/src/ripplet/extraction/code/tree_sitter.py +322 -0
  94. ripplet-0.1.0.0/src/ripplet/extraction/code/ts_universal.py +6232 -0
  95. ripplet-0.1.0.0/src/ripplet/extraction/code/type_resolution.py +1 -0
  96. ripplet-0.1.0.0/src/ripplet/extraction/code/typed_params.py +1494 -0
  97. ripplet-0.1.0.0/src/ripplet/extraction/documents/__init__.py +1 -0
  98. ripplet-0.1.0.0/src/ripplet/extraction/documents/images.py +4 -0
  99. ripplet-0.1.0.0/src/ripplet/extraction/documents/markdown.py +70 -0
  100. ripplet-0.1.0.0/src/ripplet/extraction/documents/office.py +4 -0
  101. ripplet-0.1.0.0/src/ripplet/extraction/documents/pdf.py +5 -0
  102. ripplet-0.1.0.0/src/ripplet/extraction/documents/transcripts.py +4 -0
  103. ripplet-0.1.0.0/src/ripplet/extraction/incremental.py +7 -0
  104. ripplet-0.1.0.0/src/ripplet/extraction/integrations/__init__.py +1 -0
  105. ripplet-0.1.0.0/src/ripplet/extraction/integrations/base.py +6 -0
  106. ripplet-0.1.0.0/src/ripplet/extraction/integrations/git.py +31 -0
  107. ripplet-0.1.0.0/src/ripplet/extraction/integrations/github.py +3 -0
  108. ripplet-0.1.0.0/src/ripplet/extraction/integrations/runtime.py +13 -0
  109. ripplet-0.1.0.0/src/ripplet/extraction/normalization.py +12 -0
  110. ripplet-0.1.0.0/src/ripplet/extraction/pipeline.py +573 -0
  111. ripplet-0.1.0.0/src/ripplet/extraction/registry.py +11 -0
  112. ripplet-0.1.0.0/src/ripplet/extraction/structured/__init__.py +1 -0
  113. ripplet-0.1.0.0/src/ripplet/extraction/structured/infra.py +38 -0
  114. ripplet-0.1.0.0/src/ripplet/extraction/structured/infrastructure.py +2 -0
  115. ripplet-0.1.0.0/src/ripplet/extraction/structured/json.py +2 -0
  116. ripplet-0.1.0.0/src/ripplet/extraction/structured/json_ext.py +30 -0
  117. ripplet-0.1.0.0/src/ripplet/extraction/structured/schema_code.py +393 -0
  118. ripplet-0.1.0.0/src/ripplet/extraction/structured/sql.py +325 -0
  119. ripplet-0.1.0.0/src/ripplet/extraction/structured/terraform.py +173 -0
  120. ripplet-0.1.0.0/src/ripplet/extraction/structured/toml.py +2 -0
  121. ripplet-0.1.0.0/src/ripplet/extraction/structured/toml_ext.py +36 -0
  122. ripplet-0.1.0.0/src/ripplet/extraction/structured/yaml.py +2 -0
  123. ripplet-0.1.0.0/src/ripplet/extraction/structured/yaml_ext.py +257 -0
  124. ripplet-0.1.0.0/src/ripplet/extraction/validation.py +13 -0
  125. ripplet-0.1.0.0/src/ripplet/graph/__init__.py +1 -0
  126. ripplet-0.1.0.0/src/ripplet/graph/algorithms.py +90 -0
  127. ripplet-0.1.0.0/src/ripplet/graph/builder.py +120 -0
  128. ripplet-0.1.0.0/src/ripplet/graph/communities.py +17 -0
  129. ripplet-0.1.0.0/src/ripplet/graph/deduplication.py +3 -0
  130. ripplet-0.1.0.0/src/ripplet/graph/dispatch_impl.py +130 -0
  131. ripplet-0.1.0.0/src/ripplet/graph/dispatch_link.py +160 -0
  132. ripplet-0.1.0.0/src/ripplet/graph/go_build.py +51 -0
  133. ripplet-0.1.0.0/src/ripplet/graph/http_link.py +812 -0
  134. ripplet-0.1.0.0/src/ripplet/graph/impact.py +125 -0
  135. ripplet-0.1.0.0/src/ripplet/graph/infra_link.py +102 -0
  136. ripplet-0.1.0.0/src/ripplet/graph/py_callbind.py +1081 -0
  137. ripplet-0.1.0.0/src/ripplet/graph/resolver.py +52 -0
  138. ripplet-0.1.0.0/src/ripplet/graph/sql_link.py +285 -0
  139. ripplet-0.1.0.0/src/ripplet/graph/temporal.py +11 -0
  140. ripplet-0.1.0.0/src/ripplet/graph/type_refs.py +108 -0
  141. ripplet-0.1.0.0/src/ripplet/graph/typed_callbind.py +1010 -0
  142. ripplet-0.1.0.0/src/ripplet/legacy.py +88 -0
  143. ripplet-0.1.0.0/src/ripplet/mcp/__init__.py +1 -0
  144. ripplet-0.1.0.0/src/ripplet/mcp/budget.py +205 -0
  145. ripplet-0.1.0.0/src/ripplet/mcp/freshness.py +108 -0
  146. ripplet-0.1.0.0/src/ripplet/mcp/prompts.py +1 -0
  147. ripplet-0.1.0.0/src/ripplet/mcp/resources.py +1 -0
  148. ripplet-0.1.0.0/src/ripplet/mcp/server.py +310 -0
  149. ripplet-0.1.0.0/src/ripplet/mcp/tools.py +988 -0
  150. ripplet-0.1.0.0/src/ripplet/precise/__init__.py +0 -0
  151. ripplet-0.1.0.0/src/ripplet/precise/scip.py +233 -0
  152. ripplet-0.1.0.0/src/ripplet/query/__init__.py +1 -0
  153. ripplet-0.1.0.0/src/ripplet/query/evidence.py +16 -0
  154. ripplet-0.1.0.0/src/ripplet/query/executor.py +368 -0
  155. ripplet-0.1.0.0/src/ripplet/query/factpack.py +235 -0
  156. ripplet-0.1.0.0/src/ripplet/query/formatter.py +9 -0
  157. ripplet-0.1.0.0/src/ripplet/query/planner.py +22 -0
  158. ripplet-0.1.0.0/src/ripplet/query/scoping.py +118 -0
  159. ripplet-0.1.0.0/src/ripplet/retrieval/__init__.py +1 -0
  160. ripplet-0.1.0.0/src/ripplet/retrieval/abstention.py +99 -0
  161. ripplet-0.1.0.0/src/ripplet/retrieval/context_packer.py +61 -0
  162. ripplet-0.1.0.0/src/ripplet/retrieval/embeddings.py +275 -0
  163. ripplet-0.1.0.0/src/ripplet/retrieval/error_trace.py +228 -0
  164. ripplet-0.1.0.0/src/ripplet/retrieval/expansion.py +12 -0
  165. ripplet-0.1.0.0/src/ripplet/retrieval/feature_slice.py +222 -0
  166. ripplet-0.1.0.0/src/ripplet/retrieval/fusion.py +12 -0
  167. ripplet-0.1.0.0/src/ripplet/retrieval/lexical.py +3 -0
  168. ripplet-0.1.0.0/src/ripplet/retrieval/multihop.py +271 -0
  169. ripplet-0.1.0.0/src/ripplet/retrieval/repo_map.py +193 -0
  170. ripplet-0.1.0.0/src/ripplet/retrieval/reranking.py +67 -0
  171. ripplet-0.1.0.0/src/ripplet/retrieval/routechain.py +105 -0
  172. ripplet-0.1.0.0/src/ripplet/retrieval/routes.py +244 -0
  173. ripplet-0.1.0.0/src/ripplet/retrieval/semantic.py +286 -0
  174. ripplet-0.1.0.0/src/ripplet/retrieval/spans.py +335 -0
  175. ripplet-0.1.0.0/src/ripplet/retrieval/symbols.py +8 -0
  176. ripplet-0.1.0.0/src/ripplet/retrieval/task_context.py +371 -0
  177. ripplet-0.1.0.0/src/ripplet/retrieval/terms.py +68 -0
  178. ripplet-0.1.0.0/src/ripplet/retrieval/uncertain.py +125 -0
  179. ripplet-0.1.0.0/src/ripplet/retrieval/vectors.py +97 -0
  180. ripplet-0.1.0.0/src/ripplet/security/__init__.py +1 -0
  181. ripplet-0.1.0.0/src/ripplet/security/paths.py +26 -0
  182. ripplet-0.1.0.0/src/ripplet/security/policy.py +12 -0
  183. ripplet-0.1.0.0/src/ripplet/security/sanitization.py +20 -0
  184. ripplet-0.1.0.0/src/ripplet/security/urls.py +21 -0
  185. ripplet-0.1.0.0/src/ripplet/service.py +1836 -0
  186. ripplet-0.1.0.0/src/ripplet/storage/__init__.py +1 -0
  187. ripplet-0.1.0.0/src/ripplet/storage/backends.py +3 -0
  188. ripplet-0.1.0.0/src/ripplet/storage/graph_store.py +2 -0
  189. ripplet-0.1.0.0/src/ripplet/storage/interfaces.py +25 -0
  190. ripplet-0.1.0.0/src/ripplet/storage/lock.py +74 -0
  191. ripplet-0.1.0.0/src/ripplet/storage/sqlite_store.py +495 -0
  192. ripplet-0.1.0.0/src/ripplet/testplan/__init__.py +1 -0
  193. ripplet-0.1.0.0/src/ripplet/testplan/changes.py +213 -0
  194. ripplet-0.1.0.0/src/ripplet/testplan/discovery.py +244 -0
  195. ripplet-0.1.0.0/src/ripplet/testplan/plan.py +276 -0
  196. ripplet-0.1.0.0/src/ripplet/testplan/ranking.py +91 -0
  197. ripplet-0.1.0.0/src/ripplet/testrun/__init__.py +1 -0
  198. ripplet-0.1.0.0/src/ripplet/testrun/adapters.py +163 -0
  199. ripplet-0.1.0.0/src/ripplet/testrun/compare.py +183 -0
  200. ripplet-0.1.0.0/src/ripplet/testrun/models.py +131 -0
  201. ripplet-0.1.0.0/src/ripplet/testrun/process.py +165 -0
  202. ripplet-0.1.0.0/src/ripplet/testrun/service.py +539 -0
  203. ripplet-0.1.0.0/src/ripplet/testrun/store.py +190 -0
  204. ripplet-0.1.0.0/src/ripplet/ui/__init__.py +0 -0
  205. ripplet-0.1.0.0/src/ripplet/ui/server.py +811 -0
  206. ripplet-0.1.0.0/src/ripplet/ui/static/app.css +324 -0
  207. ripplet-0.1.0.0/src/ripplet/ui/static/app.js +1137 -0
  208. ripplet-0.1.0.0/src/ripplet/ui/static/graph.js +472 -0
  209. ripplet-0.1.0.0/src/ripplet/ui/static/index.html +137 -0
  210. ripplet-0.1.0.0/src/ripplet/watch.py +318 -0
  211. ripplet-0.1.0.0/src/ripplet/workspace_scope.py +265 -0
  212. ripplet-0.1.0.0/src/ripplet.egg-info/PKG-INFO +375 -0
  213. ripplet-0.1.0.0/src/ripplet.egg-info/SOURCES.txt +215 -0
  214. ripplet-0.1.0.0/src/ripplet.egg-info/dependency_links.txt +1 -0
  215. ripplet-0.1.0.0/src/ripplet.egg-info/entry_points.txt +2 -0
  216. ripplet-0.1.0.0/src/ripplet.egg-info/requires.txt +29 -0
  217. ripplet-0.1.0.0/src/ripplet.egg-info/top_level.txt +1 -0
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Mehmet Emin Madanoglu
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
@@ -0,0 +1,375 @@
1
+ Metadata-Version: 2.4
2
+ Name: ripplet
3
+ Version: 0.1.0.0
4
+ Summary: A precise, local code graph for coding agents: who calls what, what breaks, which tests to run - over MCP, CLI and a web UI
5
+ Author: Mehmet Emin Madanoglu
6
+ License: FSL-1.1-ALv2
7
+ Keywords: code graph,code intelligence,mcp,coding agents,claude code,static analysis,impact analysis,call graph,refactoring
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Provides-Extra: test
22
+ Requires-Dist: pytest>=8; extra == "test"
23
+ Provides-Extra: mcp
24
+ Provides-Extra: treesitter
25
+ Requires-Dist: tree-sitter>=0.25; extra == "treesitter"
26
+ Requires-Dist: tree-sitter-javascript>=0.25; extra == "treesitter"
27
+ Requires-Dist: tree-sitter-typescript>=0.23; extra == "treesitter"
28
+ Provides-Extra: treesitter-multilang
29
+ Requires-Dist: tree-sitter>=0.25; extra == "treesitter-multilang"
30
+ Requires-Dist: tree-sitter-go>=0.25; extra == "treesitter-multilang"
31
+ Requires-Dist: tree-sitter-rust>=0.24; extra == "treesitter-multilang"
32
+ Requires-Dist: tree-sitter-java>=0.23; extra == "treesitter-multilang"
33
+ Requires-Dist: tree-sitter-c-sharp>=0.23; extra == "treesitter-multilang"
34
+ Requires-Dist: tree-sitter-php>=0.24; extra == "treesitter-multilang"
35
+ Requires-Dist: tree-sitter-swift>=0.7; extra == "treesitter-multilang"
36
+ Requires-Dist: tree-sitter-kotlin>=1.1; extra == "treesitter-multilang"
37
+ Requires-Dist: tree-sitter-lua>=0.5; extra == "treesitter-multilang"
38
+ Requires-Dist: tree-sitter-cpp>=0.23; extra == "treesitter-multilang"
39
+ Requires-Dist: tree-sitter-c>=0.24; extra == "treesitter-multilang"
40
+ Requires-Dist: tree-sitter-dart>=0.1; extra == "treesitter-multilang"
41
+ Requires-Dist: tree-sitter-gdscript>=6.1; extra == "treesitter-multilang"
42
+ Requires-Dist: tree-sitter-ruby>=0.23; extra == "treesitter-multilang"
43
+ Provides-Extra: watch
44
+ Requires-Dist: watchfiles>=1.0; extra == "watch"
45
+ Dynamic: license-file
46
+
47
+ <p align="center">
48
+ <img src="docs/logo.png" alt="Ripplet" width="180">
49
+ </p>
50
+
51
+ <h1 align="center">Ripplet</h1>
52
+
53
+ <p align="center">
54
+ <b>See the ripple before you make the change.</b><br>
55
+ A precise, local code graph for coding agents.
56
+ </p>
57
+
58
+ <p align="center">
59
+ <a href="https://pypi.org/project/ripplet/"><img src="https://img.shields.io/pypi/v/ripplet" alt="PyPI"></a>
60
+ <img src="https://img.shields.io/pypi/pyversions/ripplet" alt="Python">
61
+ <img src="https://img.shields.io/badge/license-FSL--1.1--ALv2-blue" alt="License">
62
+ <img src="https://img.shields.io/badge/MCP-server-8A2BE2" alt="MCP">
63
+ </p>
64
+
65
+ <p align="center">
66
+ <a href="#how-it-compares">Benchmarks</a> ·
67
+ <a href="#languages">Languages</a> ·
68
+ <a href="#using-it-with-agents">Agents</a> ·
69
+ <a href="#change-safety-from-the-command-line">Change safety</a> ·
70
+ <a href="#the-ui">UI</a> ·
71
+ <a href="#license">License</a>
72
+ </p>
73
+
74
+ ---
75
+
76
+ **A precise, local code graph for coding agents.** Ripplet indexes a repository
77
+ into a call / type / data graph and answers the questions agents otherwise
78
+ answer with grep: *who calls this, what breaks if it changes, which lines a
79
+ rename touches, which tests to run.* Every answer comes with `file:line`, and
80
+ a link the graph cannot prove is labelled as such instead of being guessed.
81
+
82
+ - **Precise.** Checked call by call against compiler-grade indexes (SCIP):
83
+ zero wrong edges across 12 repositories, 0.92 call-site recall.
84
+ - **Built for agents.** MCP server, always-on rules for Claude Code, Codex,
85
+ Gemini CLI, Cursor, Copilot, OpenCode and more, a Claude Code skill, and
86
+ hooks that steer an agent to the graph before it greps.
87
+ - **Change safety.** Impact of an edit, a dry-run rename, broken callers after
88
+ an edit, the exact tests that reach a change, PR review, architecture rules.
89
+ - **Local.** One SQLite file, no LLM, no cloud, no vector database. Python 3.12+.
90
+
91
+ ```bash
92
+ pip install "ripplet[treesitter-multilang]"
93
+ ripplet setup . # index + MCP config + agent rules/skill/hooks, in one step
94
+ ripplet ui . # browse the graph
95
+ ```
96
+
97
+ ### At a glance
98
+
99
+ | | Ripplet | Graphify |
100
+ |---|---:|---:|
101
+ | Callers found (site recall, 258 functions) | **~93%** | ~23% |
102
+ | Right file first for a task (hit@1, 389 tasks) | **62.5%** | 44.5% |
103
+ | Broken change caught by selected tests | **68-92%** | 10-20% |
104
+ | Wrong call edges vs a compiler (12 repos) | **0** | not measured |
105
+
106
+ Details and per-repository numbers below.
107
+
108
+ ---
109
+
110
+ ## How it compares
111
+
112
+ Measured on real open-source repositories with harnesses that score every
113
+ tool the same way (ground truth: textual call sites, the files real commits
114
+ changed, or mutants a test suite kills). Graphify 0.9.92 was run with its
115
+ defaults (`graphify extract --code-only`, `graphify query`).
116
+
117
+ ### Finding every caller of a function
118
+
119
+ Site recall = share of the real call sites (`file:line`) the tool reports.
120
+
121
+ | Set | Functions | Ripplet | Graphify |
122
+ |---|---:|---:|---:|
123
+ | fresh (13 repos: TS, Java, C#, Go, PHP, Python, Rust, Lua) | 150 | **93%** | 23% |
124
+ | dev (7 repos: Java, Lua, Python, TS, C#) | 67 | **96%** | 29% |
125
+ | extra (9 repos: Lua, Ruby, Rust) | 41 | **89%** | 16% |
126
+
127
+ Per language, all three sets: Java 99% vs 66%, TypeScript 91% vs 14%, Python 96% vs 29%,
128
+ Go 98% vs 48%, C# 93% vs 11%, Lua 94% vs 6%, Rust 90% vs 56%, Ruby 86% vs 25%, PHP 100% vs 79%.
129
+
130
+ ### Finding where a task should be done
131
+
132
+ The commit subject of a real later commit is the task; the files that commit
133
+ changed are the answer. `task_context` vs `graphify query`.
134
+
135
+ hit@1 = the first file named is one the commit changed; hit@5 = one of the first five.
136
+ 389 tasks on 13 repositories (Python, Java, Go, TypeScript, PHP); the last 9 were added later as
137
+ hold-out sets, to catch tuning that only fits the first four.
138
+
139
+ | Repository | Tasks | hit@1 Ripplet | hit@1 Graphify | hit@5 Ripplet | hit@5 Graphify |
140
+ |---|---:|---:|---:|---:|---:|
141
+ | httpx (Python) | 38 | **53%** | 34% | **87%** | 76% |
142
+ | marshmallow (Python) | 29 | **69%** | 41% | **90%** | 83% |
143
+ | jsoup (Java) | 40 | **60%** | 30% | **78%** | 55% |
144
+ | chi (Go) | 40 | **62%** | 50% | 80% | 80% |
145
+ | attrs (Python) | 15 | **80%** | 33% | **87%** | 53% |
146
+ | zustand (TypeScript) | 11 | 91% | 91% | 91% | **100%** |
147
+ | gson (Java) | 39 | **46%** | 36% | **79%** | 49% |
148
+ | cobra (Go) | 40 | **82%** | 52% | **100%** | 88% |
149
+ | monolog (PHP) | 40 | **68%** | 55% | **78%** | 70% |
150
+ | javapoet (Java) | 37 | 70% | 70% | **95%** | 84% |
151
+ | commons-text (Java) | 18 | **78%** | 72% | **94%** | 83% |
152
+ | commons-csv (Java) | 7 | **71%** | 14% | 86% | 86% |
153
+ | JsonPath (Java) | 35 | **26%** | 11% | **60%** | 34% |
154
+ | **all** | **389** | **62.5%** | 44.5% | **83.8%** | 69.9% |
155
+
156
+ Average answer size: about 1,500 tokens.
157
+
158
+ ### Picking the tests to run after a change
159
+
160
+ Mutation test selection: a mutant is caught when one of the selected tests
161
+ fails on it.
162
+
163
+ | Repository | Mutants | Ripplet | Graphify | grep |
164
+ |---|---:|---:|---:|---:|
165
+ | click (Python, 578 tests) | 40 | **68%** caught | 10% | 30% |
166
+ | conduit (C#, 38 tests) | 25 | **92%** caught | 20% | 52% |
167
+
168
+ Ripplet selects the tests that reach the changed symbol through calls,
169
+ instantiation and inheritance, so a broken change is far more likely to fail
170
+ a selected test; it also selects more tests (43% of click's suite, 16% of conduit's).
171
+
172
+ ### Precision against a compiler
173
+
174
+ Ripplet's call edges compared with SCIP indexes (scip-typescript, scip-python,
175
+ rust-analyzer, scip-go, scip-dotnet, scip-java) — every call site the
176
+ compiler resolves, and every edge Ripplet claims:
177
+
178
+ | Repository | Language | Recall | Wrong edges |
179
+ |---|---|---:|---:|
180
+ | hono | TypeScript | 0.955 | 0 |
181
+ | h3 | TypeScript | 0.978 | 0 |
182
+ | axios | JavaScript | 1.000 | 0 |
183
+ | starlette | Python | 0.954 | 0 |
184
+ | requests | Python | 0.974 | 0 |
185
+ | ripgrep | Rust | 0.938 | 0 |
186
+ | axum | Rust | 0.839 | 0 |
187
+ | eShopOnWeb | C# | 0.920 | 0 |
188
+ | gin | Go | 0.959 | 0 |
189
+ | echo | Go | 0.940 | 0 |
190
+ | spring-petclinic | Java | 0.962 | 0 |
191
+ | commons-lang | Java | 0.905 | 0 |
192
+ | **all 12** | | **0.923** of 77,408 call sites | **0** |
193
+
194
+ A call Ripplet cannot prove (an untyped receiver whose method name exists in
195
+ the project) is not turned into an edge. Agents see it in an `UNVERIFIED`
196
+ section: *possible caller, check the line*.
197
+
198
+ ### With a coding agent
199
+
200
+ Claude Haiku 4.5, headless, 13 repositories in 13 languages; the same tasks
201
+ with and without Ripplet (without = no MCP server, no rules, no hooks).
202
+
203
+ | Task | With Ripplet | Without |
204
+ |---|---|---|
205
+ | Rename a function everywhere (complete, compiles) | **13 / 13** | 12 / 13 |
206
+ | … cost / turns for all 13 | **$0.81 / 85** | $1.82 / 420 |
207
+ | List every caller (recall) | 0.985 | 0.995 |
208
+ | Files read or grepped (both tasks, all repos) | **14** | 229 |
209
+
210
+ Renames are as reliable at less than half the cost and a fifth of the turns.
211
+ Caller lists are about as complete; where the graph has a gap, the agent is
212
+ told so (UNVERIFIED) rather than given a confident wrong answer.
213
+
214
+ ---
215
+
216
+ ## Languages
217
+
218
+ Deep analysis (symbols, imports, calls with receiver types, inheritance,
219
+ overrides) for:
220
+
221
+ | Language | Notes |
222
+ |---|---|
223
+ | Python | AST; imports, `__all__`, properties, `__call__`, typed attributes |
224
+ | TypeScript / JavaScript | tree-sitter; namespaces, re-export barrels, workspaces, callbacks |
225
+ | Java, Kotlin | packages, nested/anonymous classes, overloads, extension functions |
226
+ | C# | usings, generics, extension methods, local functions, `await Task<T>` |
227
+ | Go | packages, interfaces, embedding, build tags |
228
+ | Rust | modules, re-exports, workspaces, traits, macros |
229
+ | PHP | namespaces, Laravel container/facades, Blade views, docblock types |
230
+ | Ruby | modules, mixins, Rails conventions |
231
+ | C / C++ | includes, namespaces, templates, `#if` branches, macro bodies |
232
+ | Swift | modules, extensions, closures typed by their callee |
233
+ | Dart, Lua, GDScript | imports / requires, classes and modules |
234
+
235
+ Also indexed: SQL schemas and code migrations (Laravel, Rails, Django, Alembic,
236
+ EF Core, Prisma) as tables and columns, HTTP routes and the client calls that
237
+ hit them across languages, Docker Compose, Kubernetes, CI workflows, Terraform,
238
+ Markdown docs, config files.
239
+
240
+ ---
241
+
242
+ ## Using it with agents
243
+
244
+ ```bash
245
+ ripplet setup . # init, index, .mcp.json / opencode.json, rules, skill, hooks, guard
246
+ ripplet rules on . --target all # rules for every agent below
247
+ ripplet rules on . --strict # block the first raw read/grep until a Ripplet tool is used
248
+ ```
249
+
250
+ | Agent | Always-on guidance | Enforcement |
251
+ |---|---|---|
252
+ | Claude Code | `CLAUDE.md` + skill `.claude/skills/ripplet/SKILL.md` | PreToolUse / PostToolUse hooks |
253
+ | Codebuddy | Claude-style | same hooks |
254
+ | OpenCode | `AGENTS.md` | plugin `.opencode/plugins/ripplet.js` |
255
+ | Gemini CLI | `GEMINI.md` | BeforeTool hook |
256
+ | Codex, Hermes, Amp, Devin, Jules | `AGENTS.md` | |
257
+ | Cursor | `.cursor/rules/ripplet.mdc` | |
258
+ | GitHub Copilot | `.github/copilot-instructions.md` | |
259
+ | Kiro, Windsurf, Antigravity, Cline | their rules folders | |
260
+
261
+ This repository ships the same guidance as files you can copy:
262
+ [`CLAUDE.md`](CLAUDE.md), [`AGENTS.md`](AGENTS.md), [`GEMINI.md`](GEMINI.md) and the
263
+ Claude Code skill [`skills/ripplet/SKILL.md`](skills/ripplet/SKILL.md).
264
+
265
+ ### MCP tools
266
+
267
+ `ripplet mcp` serves these over stdio (`ripplet tool <name> key=value` runs any
268
+ of them from the shell):
269
+
270
+ | Tool | Use it for |
271
+ |---|---|
272
+ | `task_context` | the start of a task: the code it is about, callers, routes / tables, files to edit, tests |
273
+ | `repo_map` | an unfamiliar repository: entry points, most-used files and symbols |
274
+ | `explain_symbol` | a known name: source, every caller and callee with the call's code |
275
+ | `get_neighbors`, `analyze_change_impact` | who calls it / what breaks, with every call line |
276
+ | `change_plan`, `rename_symbol` | renames and signature changes: every line to edit, same-named code to leave alone |
277
+ | `investigate_error` | a stack trace or log line mapped to functions, code and callers |
278
+ | `check_change` | after editing: broken callers, leftovers, the exact tests to run |
279
+ | `list_routes` | routes, their handlers and the permission checks they make |
280
+ | `feature_slice` | building something like an existing feature: all its touch points |
281
+ | `find_related_tests`, `find_path`, `search_symbols`, `query_graph` | the rest |
282
+
283
+ Answers fit a token budget and say how to get more; read tools re-index
284
+ changed files first, so line numbers follow the agent's edits.
285
+
286
+ ---
287
+
288
+ ## Change safety from the command line
289
+
290
+ ```bash
291
+ ripplet impact --symbol Store.save # what depends on it
292
+ ripplet tool change_plan symbol=Store.save change=rename new_name=persist
293
+ ripplet check . --run-tests # broken callers + the tests that reach the change
294
+ ripplet review . --base origin/main # PR review (Markdown or --format sarif)
295
+ ripplet arch # architecture rules in ripplet.arch.yaml
296
+ ripplet test-plan --working-tree # tests to run, with the evidence for each
297
+ ```
298
+
299
+ Architecture rules are checked on the graph, not on text:
300
+
301
+ ```yaml
302
+ rules:
303
+ - id: writes-need-permission
304
+ must_call: [requireRole, requireNotViewer]
305
+ for: {path: "app/Controllers/*.php", type: [method], public: true, name: "^(store|update|delete)"}
306
+ depth: 3
307
+ - id: ui-not-db
308
+ forbid: {from: "src/ui/**", to: "src/db/**"}
309
+ ```
310
+
311
+ ---
312
+
313
+ ## The UI
314
+
315
+ `ripplet ui .` opens a local, read-only explorer:
316
+
317
+ - **Map** of module dependencies, **Explore** a symbol's neighbourhood (graph or
318
+ list, large neighbourhoods grouped by file), **Impact** ring by ring with the
319
+ tests that reach it, **Changes** of your working tree, **Path** between two symbols.
320
+ - **Routes** with their handlers, **Data**: tables, columns and the queries on
321
+ them (SELECT / INSERT / UPDATE / DELETE), **Index health**: coverage per
322
+ language, stale files, agent setup.
323
+ - Every caller with the call's code, proven vs inferred links, possible
324
+ (unverified) callers, and a dry-run **rename preview**.
325
+
326
+ ---
327
+
328
+ ## Install
329
+
330
+ ```bash
331
+ pip install ripplet # Python, Markdown, config, SQL
332
+ pip install "ripplet[treesitter-multilang]" # + every language above
333
+ pip install "ripplet[watch]" # ripplet watch: re-index on save
334
+ ```
335
+
336
+ ```bash
337
+ ripplet index . # build / update the graph (incremental)
338
+ ripplet search Store # find symbols
339
+ ripplet explain Store.save # source, callers, callees
340
+ ripplet status # what is indexed
341
+ ```
342
+
343
+ Optional local semantic search with Ollama (`ripplet embed --model
344
+ qwen3-embedding:0.6b`, then `ripplet query ... --mode hybrid_full`); everything
345
+ else works without a model.
346
+
347
+ ## Limitations
348
+
349
+ - Static analysis: calls made through reflection, string-built names or
350
+ dependency injection containers configured at runtime are not followed
351
+ (Laravel's `app(X::class)` is).
352
+ - Dynamic languages (Ruby, Lua, PHP without types) have more UNVERIFIED sites
353
+ than typed ones; Ripplet reports them instead of guessing.
354
+ - Generated code that only exists after a build is not indexed.
355
+ - Single SQLite file per workspace.
356
+
357
+ ## License
358
+
359
+ Ripplet is **source-available** under the
360
+ [Functional Source License 1.1, Apache 2.0 future license](LICENSE) (FSL-1.1-ALv2).
361
+
362
+ - **Free to use** for anything except a competing product: personal projects,
363
+ work, commercial companies, internal tools, CI, education, research.
364
+ - **Free to change**, and to share your changes, as long as the license and
365
+ copyright notices stay.
366
+ - **Not allowed:** offering Ripplet, or a copy or fork of it, as a commercial
367
+ product or service that competes with it.
368
+ - **Becomes Apache 2.0** two years after each release.
369
+ - The name "Ripplet" and its logo are trademarks and are not licensed.
370
+
371
+ For a commercial or team license, contact the author.
372
+
373
+ ## Author
374
+
375
+ Mehmet Emin Madanoglu