dynvo 1.33.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 (418) hide show
  1. dynvo-1.33.0/.github/workflows/ci.yml +121 -0
  2. dynvo-1.33.0/.github/workflows/release.yml +276 -0
  3. dynvo-1.33.0/.github/workflows/secrets-scan.yml +21 -0
  4. dynvo-1.33.0/.gitignore +66 -0
  5. dynvo-1.33.0/.gitleaks.toml +30 -0
  6. dynvo-1.33.0/.pre-commit-config.yaml +40 -0
  7. dynvo-1.33.0/.secrets.baseline +186 -0
  8. dynvo-1.33.0/CHANGELOG.md +141 -0
  9. dynvo-1.33.0/LICENSE +183 -0
  10. dynvo-1.33.0/PKG-INFO +239 -0
  11. dynvo-1.33.0/README.md +196 -0
  12. dynvo-1.33.0/assets/faultlines-banner.png +0 -0
  13. dynvo-1.33.0/eval/STRUCTURAL-AUDIT.md +80 -0
  14. dynvo-1.33.0/eval/STRUCTURAL-BASELINE.json +261 -0
  15. dynvo-1.33.0/eval/_replay_post_process.py +137 -0
  16. dynvo-1.33.0/eval/dependency-anchors.yaml +400 -0
  17. dynvo-1.33.0/eval/membership/BASELINE.md +103 -0
  18. dynvo-1.33.0/eval/membership/NAMES-BASELINE.md +120 -0
  19. dynvo-1.33.0/eval/membership/documenso/ground-truth.yaml +820 -0
  20. dynvo-1.33.0/eval/membership/inbox-zero/ground-truth.yaml +465 -0
  21. dynvo-1.33.0/eval/membership/infisical/ground-truth.yaml +4411 -0
  22. dynvo-1.33.0/eval/membership/score_membership.py +289 -0
  23. dynvo-1.33.0/eval/membership/score_names.py +371 -0
  24. dynvo-1.33.0/eval/run_structural_corpus.sh +55 -0
  25. dynvo-1.33.0/eval/stacks/config-manifests.yaml +65 -0
  26. dynvo-1.33.0/eval/stacks/django.yaml +124 -0
  27. dynvo-1.33.0/eval/stacks/express.yaml +87 -0
  28. dynvo-1.33.0/eval/stacks/fastapi.yaml +55 -0
  29. dynvo-1.33.0/eval/stacks/filesystem-routing.yaml +86 -0
  30. dynvo-1.33.0/eval/stacks/go-http-router.yaml +53 -0
  31. dynvo-1.33.0/eval/stacks/js-library.yaml +90 -0
  32. dynvo-1.33.0/eval/stacks/mvc-controllers.yaml +27 -0
  33. dynvo-1.33.0/eval/stacks/python-library.yaml +60 -0
  34. dynvo-1.33.0/eval/stacks/rails-app.yaml +79 -0
  35. dynvo-1.33.0/eval/stacks/rust-workspace.yaml +37 -0
  36. dynvo-1.33.0/eval/stacks/schema-domains.yaml +52 -0
  37. dynvo-1.33.0/eval/structural_audit.py +368 -0
  38. dynvo-1.33.0/faultline/__init__.py +1 -0
  39. dynvo-1.33.0/faultline/analyzer/__init__.py +0 -0
  40. dynvo-1.33.0/faultline/analyzer/ast_extractor.py +1108 -0
  41. dynvo-1.33.0/faultline/analyzer/auto_alias_discoverer.py +189 -0
  42. dynvo-1.33.0/faultline/analyzer/evolve.py +666 -0
  43. dynvo-1.33.0/faultline/analyzer/features.py +1519 -0
  44. dynvo-1.33.0/faultline/analyzer/git.py +490 -0
  45. dynvo-1.33.0/faultline/analyzer/import_graph.py +1022 -0
  46. dynvo-1.33.0/faultline/analyzer/incremental.py +201 -0
  47. dynvo-1.33.0/faultline/analyzer/marketing_fetcher.py +926 -0
  48. dynvo-1.33.0/faultline/analyzer/post_process.py +795 -0
  49. dynvo-1.33.0/faultline/analyzer/repo_config.py +447 -0
  50. dynvo-1.33.0/faultline/analyzer/reverse_imports.py +712 -0
  51. dynvo-1.33.0/faultline/analyzer/symbol_graph.py +884 -0
  52. dynvo-1.33.0/faultline/analyzer/test_mapper.py +333 -0
  53. dynvo-1.33.0/faultline/analyzer/tsconfig_paths.py +613 -0
  54. dynvo-1.33.0/faultline/analyzer/url_route_resolver.py +485 -0
  55. dynvo-1.33.0/faultline/analyzer/validation.py +232 -0
  56. dynvo-1.33.0/faultline/analyzer/workspace.py +483 -0
  57. dynvo-1.33.0/faultline/benchmark/__init__.py +52 -0
  58. dynvo-1.33.0/faultline/benchmark/loader.py +197 -0
  59. dynvo-1.33.0/faultline/benchmark/metrics.py +300 -0
  60. dynvo-1.33.0/faultline/benchmark/report.py +107 -0
  61. dynvo-1.33.0/faultline/cache/__init__.py +110 -0
  62. dynvo-1.33.0/faultline/cache/backend.py +260 -0
  63. dynvo-1.33.0/faultline/cache/discovery.py +497 -0
  64. dynvo-1.33.0/faultline/cache/freshness.py +145 -0
  65. dynvo-1.33.0/faultline/cache/hashing.py +73 -0
  66. dynvo-1.33.0/faultline/cache/paths.py +43 -0
  67. dynvo-1.33.0/faultline/cache/refresh.py +154 -0
  68. dynvo-1.33.0/faultline/cache/symbols.py +296 -0
  69. dynvo-1.33.0/faultline/cli.py +1057 -0
  70. dynvo-1.33.0/faultline/cloud/__init__.py +13 -0
  71. dynvo-1.33.0/faultline/cloud/sync.py +155 -0
  72. dynvo-1.33.0/faultline/digest/__init__.py +2 -0
  73. dynvo-1.33.0/faultline/digest/__main__.py +4 -0
  74. dynvo-1.33.0/faultline/digest/cli.py +81 -0
  75. dynvo-1.33.0/faultline/digest/git_reader.py +160 -0
  76. dynvo-1.33.0/faultline/digest/summarizer.py +192 -0
  77. dynvo-1.33.0/faultline/framework_linkers/__init__.py +25 -0
  78. dynvo-1.33.0/faultline/framework_linkers/_discovery.py +110 -0
  79. dynvo-1.33.0/faultline/framework_linkers/base.py +124 -0
  80. dynvo-1.33.0/faultline/framework_linkers/nextjs_http_route.py +705 -0
  81. dynvo-1.33.0/faultline/framework_linkers/nextjs_server_actions.py +598 -0
  82. dynvo-1.33.0/faultline/framework_linkers/store_mutation.py +1058 -0
  83. dynvo-1.33.0/faultline/framework_linkers/trpc_procedure.py +756 -0
  84. dynvo-1.33.0/faultline/llm/__init__.py +0 -0
  85. dynvo-1.33.0/faultline/llm/cost.py +307 -0
  86. dynvo-1.33.0/faultline/llm/model_gateway.py +129 -0
  87. dynvo-1.33.0/faultline/models/__init__.py +0 -0
  88. dynvo-1.33.0/faultline/models/types.py +1055 -0
  89. dynvo-1.33.0/faultline/output/__init__.py +0 -0
  90. dynvo-1.33.0/faultline/output/reporter.py +266 -0
  91. dynvo-1.33.0/faultline/output/writer.py +40 -0
  92. dynvo-1.33.0/faultline/pipeline_v2/__init__.py +110 -0
  93. dynvo-1.33.0/faultline/pipeline_v2/data/__init__.py +74 -0
  94. dynvo-1.33.0/faultline/pipeline_v2/data/dependency-anchors.yaml +400 -0
  95. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/config-manifests.yaml +65 -0
  96. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/django.yaml +124 -0
  97. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/express.yaml +87 -0
  98. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/fastapi.yaml +55 -0
  99. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/filesystem-routing.yaml +86 -0
  100. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/go-http-router.yaml +53 -0
  101. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/js-library.yaml +90 -0
  102. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/mvc-controllers.yaml +27 -0
  103. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/python-library.yaml +60 -0
  104. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/rails-app.yaml +79 -0
  105. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/rust-workspace.yaml +37 -0
  106. dynvo-1.33.0/faultline/pipeline_v2/data/stacks/schema-domains.yaml +52 -0
  107. dynvo-1.33.0/faultline/pipeline_v2/domain_noun.py +272 -0
  108. dynvo-1.33.0/faultline/pipeline_v2/extractors/__init__.py +25 -0
  109. dynvo-1.33.0/faultline/pipeline_v2/extractors/_pattern_base.py +121 -0
  110. dynvo-1.33.0/faultline/pipeline_v2/extractors/_rails.py +206 -0
  111. dynvo-1.33.0/faultline/pipeline_v2/extractors/_util.py +143 -0
  112. dynvo-1.33.0/faultline/pipeline_v2/extractors/base.py +87 -0
  113. dynvo-1.33.0/faultline/pipeline_v2/extractors/config.py +377 -0
  114. dynvo-1.33.0/faultline/pipeline_v2/extractors/django.py +500 -0
  115. dynvo-1.33.0/faultline/pipeline_v2/extractors/express.py +364 -0
  116. dynvo-1.33.0/faultline/pipeline_v2/extractors/fastapi.py +324 -0
  117. dynvo-1.33.0/faultline/pipeline_v2/extractors/fastify.py +273 -0
  118. dynvo-1.33.0/faultline/pipeline_v2/extractors/go_packages.py +231 -0
  119. dynvo-1.33.0/faultline/pipeline_v2/extractors/go_router.py +256 -0
  120. dynvo-1.33.0/faultline/pipeline_v2/extractors/js_library.py +788 -0
  121. dynvo-1.33.0/faultline/pipeline_v2/extractors/mvc.py +117 -0
  122. dynvo-1.33.0/faultline/pipeline_v2/extractors/package.py +362 -0
  123. dynvo-1.33.0/faultline/pipeline_v2/extractors/python_library.py +386 -0
  124. dynvo-1.33.0/faultline/pipeline_v2/extractors/rails_jobs.py +127 -0
  125. dynvo-1.33.0/faultline/pipeline_v2/extractors/rails_models.py +165 -0
  126. dynvo-1.33.0/faultline/pipeline_v2/extractors/rails_routes.py +137 -0
  127. dynvo-1.33.0/faultline/pipeline_v2/extractors/rails_stimulus.py +143 -0
  128. dynvo-1.33.0/faultline/pipeline_v2/extractors/rails_views.py +125 -0
  129. dynvo-1.33.0/faultline/pipeline_v2/extractors/route.py +407 -0
  130. dynvo-1.33.0/faultline/pipeline_v2/extractors/rust_packages.py +382 -0
  131. dynvo-1.33.0/faultline/pipeline_v2/extractors/rust_workspace.py +255 -0
  132. dynvo-1.33.0/faultline/pipeline_v2/extractors/schema.py +249 -0
  133. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/__init__.py +29 -0
  134. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/adapters/__init__.py +17 -0
  135. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/adapters/express.py +17 -0
  136. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/adapters/fastapi.py +18 -0
  137. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/adapters/nextjs.py +54 -0
  138. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/adapters/react.py +19 -0
  139. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/call_graph.py +752 -0
  140. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/confidence.py +82 -0
  141. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/cross_stack.py +261 -0
  142. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/expander.py +945 -0
  143. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/fan_in.py +224 -0
  144. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/flow_display_name.py +413 -0
  145. dynvo-1.33.0/faultline/pipeline_v2/flow_expansion/reverse_cross_stack.py +313 -0
  146. dynvo-1.33.0/faultline/pipeline_v2/flow_reach.py +636 -0
  147. dynvo-1.33.0/faultline/pipeline_v2/flow_symbols.py +1098 -0
  148. dynvo-1.33.0/faultline/pipeline_v2/flow_test_mapper.py +296 -0
  149. dynvo-1.33.0/faultline/pipeline_v2/git_snapshot.py +229 -0
  150. dynvo-1.33.0/faultline/pipeline_v2/incremental.py +169 -0
  151. dynvo-1.33.0/faultline/pipeline_v2/incremental_gate.py +467 -0
  152. dynvo-1.33.0/faultline/pipeline_v2/incremental_wiring.py +370 -0
  153. dynvo-1.33.0/faultline/pipeline_v2/indexes.py +336 -0
  154. dynvo-1.33.0/faultline/pipeline_v2/lineage.py +322 -0
  155. dynvo-1.33.0/faultline/pipeline_v2/llm_health.py +244 -0
  156. dynvo-1.33.0/faultline/pipeline_v2/multi.py +161 -0
  157. dynvo-1.33.0/faultline/pipeline_v2/naming_validator.py +290 -0
  158. dynvo-1.33.0/faultline/pipeline_v2/nav_taxonomy.py +457 -0
  159. dynvo-1.33.0/faultline/pipeline_v2/phase_enrich.py +241 -0
  160. dynvo-1.33.0/faultline/pipeline_v2/phase_extract.py +151 -0
  161. dynvo-1.33.0/faultline/pipeline_v2/phase_finalize.py +498 -0
  162. dynvo-1.33.0/faultline/pipeline_v2/phase_intake.py +181 -0
  163. dynvo-1.33.0/faultline/pipeline_v2/phase_layer2.py +451 -0
  164. dynvo-1.33.0/faultline/pipeline_v2/phase_postprocess.py +211 -0
  165. dynvo-1.33.0/faultline/pipeline_v2/product_strings.py +824 -0
  166. dynvo-1.33.0/faultline/pipeline_v2/residual_clusterer.py +430 -0
  167. dynvo-1.33.0/faultline/pipeline_v2/run.py +738 -0
  168. dynvo-1.33.0/faultline/pipeline_v2/run_dir.py +155 -0
  169. dynvo-1.33.0/faultline/pipeline_v2/run_logger.py +173 -0
  170. dynvo-1.33.0/faultline/pipeline_v2/scan_meta.py +486 -0
  171. dynvo-1.33.0/faultline/pipeline_v2/snapshots.py +515 -0
  172. dynvo-1.33.0/faultline/pipeline_v2/stack_auditor.py +1377 -0
  173. dynvo-1.33.0/faultline/pipeline_v2/stage_0_6_shape.py +1589 -0
  174. dynvo-1.33.0/faultline/pipeline_v2/stage_0_intake.py +857 -0
  175. dynvo-1.33.0/faultline/pipeline_v2/stage_1_extractors.py +316 -0
  176. dynvo-1.33.0/faultline/pipeline_v2/stage_1_per_workspace.py +607 -0
  177. dynvo-1.33.0/faultline/pipeline_v2/stage_2_6_membership_closure.py +984 -0
  178. dynvo-1.33.0/faultline/pipeline_v2/stage_2_reconcile.py +874 -0
  179. dynvo-1.33.0/faultline/pipeline_v2/stage_3_flows.py +895 -0
  180. dynvo-1.33.0/faultline/pipeline_v2/stage_4_guards.py +640 -0
  181. dynvo-1.33.0/faultline/pipeline_v2/stage_4_residual.py +793 -0
  182. dynvo-1.33.0/faultline/pipeline_v2/stage_5_3_sibling_collapse.py +706 -0
  183. dynvo-1.33.0/faultline/pipeline_v2/stage_5_5_bipartite.py +377 -0
  184. dynvo-1.33.0/faultline/pipeline_v2/stage_5_postprocess.py +869 -0
  185. dynvo-1.33.0/faultline/pipeline_v2/stage_6_3_import_tree.py +1774 -0
  186. dynvo-1.33.0/faultline/pipeline_v2/stage_6_4_framework_enrich.py +471 -0
  187. dynvo-1.33.0/faultline/pipeline_v2/stage_6_5_product_clusterer.py +1106 -0
  188. dynvo-1.33.0/faultline/pipeline_v2/stage_6_6_branch_slicer.py +1029 -0
  189. dynvo-1.33.0/faultline/pipeline_v2/stage_6_7_user_flows.py +1172 -0
  190. dynvo-1.33.0/faultline/pipeline_v2/stage_6_7b_uf_refiner.py +772 -0
  191. dynvo-1.33.0/faultline/pipeline_v2/stage_6_7c_uf_splitter.py +342 -0
  192. dynvo-1.33.0/faultline/pipeline_v2/stage_6_8_lineage.py +157 -0
  193. dynvo-1.33.0/faultline/pipeline_v2/stage_6_95_history.py +899 -0
  194. dynvo-1.33.0/faultline/pipeline_v2/stage_6_96_impact.py +287 -0
  195. dynvo-1.33.0/faultline/pipeline_v2/stage_6_9_test_strip.py +371 -0
  196. dynvo-1.33.0/faultline/pipeline_v2/stage_6_metrics.py +568 -0
  197. dynvo-1.33.0/faultline/pipeline_v2/stage_7_output.py +259 -0
  198. dynvo-1.33.0/faultline/pipeline_v2/stage_8_5_member_backfill.py +221 -0
  199. dynvo-1.33.0/faultline/pipeline_v2/stage_8_6_5_scaffold_filter.py +163 -0
  200. dynvo-1.33.0/faultline/pipeline_v2/stage_8_6_nonsource_drop.py +276 -0
  201. dynvo-1.33.0/faultline/pipeline_v2/stage_8_7_anchor_desink.py +260 -0
  202. dynvo-1.33.0/faultline/pipeline_v2/stage_8_8_shared_members.py +211 -0
  203. dynvo-1.33.0/faultline/pipeline_v2/stage_8_analyst.py +1403 -0
  204. dynvo-1.33.0/faultline/pipeline_v2/stage_8_marketing_clusterer.py +991 -0
  205. dynvo-1.33.0/faultline/pipeline_v2/stage_8_rollup_strategies.py +967 -0
  206. dynvo-1.33.0/faultline/pipeline_v2/url_linker.py +624 -0
  207. dynvo-1.33.0/faultline/symbols/__init__.py +17 -0
  208. dynvo-1.33.0/faultline/symbols/attribution.py +315 -0
  209. dynvo-1.33.0/faultline/symbols/extractor.py +110 -0
  210. dynvo-1.33.0/faultline/symbols/roles.py +150 -0
  211. dynvo-1.33.0/faultline/watch/__init__.py +16 -0
  212. dynvo-1.33.0/faultline/watch/daemon.py +340 -0
  213. dynvo-1.33.0/faultlines-mcp/.gitignore +2 -0
  214. dynvo-1.33.0/faultlines-mcp/Dockerfile +18 -0
  215. dynvo-1.33.0/faultlines-mcp/README.md +85 -0
  216. dynvo-1.33.0/faultlines-mcp/faultlines_mcp/__init__.py +16 -0
  217. dynvo-1.33.0/faultlines-mcp/faultlines_mcp/core.py +1104 -0
  218. dynvo-1.33.0/faultlines-mcp/faultlines_mcp/http_service.py +132 -0
  219. dynvo-1.33.0/faultlines-mcp/faultlines_mcp/server.py +481 -0
  220. dynvo-1.33.0/faultlines-mcp/fly.toml +33 -0
  221. dynvo-1.33.0/faultlines-mcp/pyproject.toml +56 -0
  222. dynvo-1.33.0/pyproject.toml +207 -0
  223. dynvo-1.33.0/scripts/bump_minor_version.py +41 -0
  224. dynvo-1.33.0/scripts/debug_s15.py +136 -0
  225. dynvo-1.33.0/scripts/debug_s15_v2.py +105 -0
  226. dynvo-1.33.0/scripts/eval_flow_attribution.py +238 -0
  227. dynvo-1.33.0/scripts/landing_codegen.py +324 -0
  228. dynvo-1.33.0/scripts/run_benchmark.py +122 -0
  229. dynvo-1.33.0/scripts/simulate_layer_a.py +128 -0
  230. dynvo-1.33.0/tests/__init__.py +0 -0
  231. dynvo-1.33.0/tests/eval/__init__.py +0 -0
  232. dynvo-1.33.0/tests/eval/_make_fixtures.py +212 -0
  233. dynvo-1.33.0/tests/eval/_runner.py +140 -0
  234. dynvo-1.33.0/tests/eval/conftest.py +54 -0
  235. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/_history.json +27 -0
  236. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/__init__.py +0 -0
  237. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/main.py +13 -0
  238. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/models.py +13 -0
  239. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/routers/__init__.py +0 -0
  240. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/routers/orders.py +18 -0
  241. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/app/routers/users.py +23 -0
  242. dynvo-1.33.0/tests/eval/fixtures/fastapi-svc/requirements.txt +3 -0
  243. dynvo-1.33.0/tests/eval/fixtures/fastify-api/_history.json +32 -0
  244. dynvo-1.33.0/tests/eval/fixtures/fastify-api/package.json +8 -0
  245. dynvo-1.33.0/tests/eval/fixtures/fastify-api/src/models.js +5 -0
  246. dynvo-1.33.0/tests/eval/fixtures/fastify-api/src/plugins/auth.js +7 -0
  247. dynvo-1.33.0/tests/eval/fixtures/fastify-api/src/routes/checkout.js +9 -0
  248. dynvo-1.33.0/tests/eval/fixtures/fastify-api/src/routes/products.js +13 -0
  249. dynvo-1.33.0/tests/eval/fixtures/fastify-api/src/server.js +8 -0
  250. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/_history.json +37 -0
  251. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/app/(marketing)/pricing/page.tsx +8 -0
  252. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/app/(shop)/cart/page.tsx +13 -0
  253. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/app/(shop)/products/page.tsx +12 -0
  254. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/app/api/checkout/route.ts +6 -0
  255. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/lib/db.ts +11 -0
  256. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/next.config.js +4 -0
  257. dynvo-1.33.0/tests/eval/fixtures/nextjs-shop/package.json +10 -0
  258. dynvo-1.33.0/tests/eval/golden/fastapi-svc.json +27 -0
  259. dynvo-1.33.0/tests/eval/golden/fastify-api.json +24 -0
  260. dynvo-1.33.0/tests/eval/golden/nextjs-shop.json +37 -0
  261. dynvo-1.33.0/tests/eval/test_accuracy_floor.py +74 -0
  262. dynvo-1.33.0/tests/eval/test_determinism.py +30 -0
  263. dynvo-1.33.0/tests/eval/test_golden_snapshots.py +63 -0
  264. dynvo-1.33.0/tests/eval/test_membership_harness.py +172 -0
  265. dynvo-1.33.0/tests/eval/test_name_scorer.py +188 -0
  266. dynvo-1.33.0/tests/eval/truth/fastapi-svc.yaml +20 -0
  267. dynvo-1.33.0/tests/eval/truth/fastify-api.yaml +20 -0
  268. dynvo-1.33.0/tests/eval/truth/nextjs-shop.yaml +29 -0
  269. dynvo-1.33.0/tests/pipeline_v2/__init__.py +0 -0
  270. dynvo-1.33.0/tests/pipeline_v2/test_cross_cut_events.py +510 -0
  271. dynvo-1.33.0/tests/pipeline_v2/test_fastapi_route_extractor.py +308 -0
  272. dynvo-1.33.0/tests/pipeline_v2/test_flow_display_name.py +284 -0
  273. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_adapters.py +59 -0
  274. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_call_graph.py +687 -0
  275. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_confidence.py +60 -0
  276. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_cross_stack.py +149 -0
  277. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_integration.py +242 -0
  278. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_python_callees.py +280 -0
  279. dynvo-1.33.0/tests/pipeline_v2/test_flow_expansion_wrapper_entry.py +268 -0
  280. dynvo-1.33.0/tests/pipeline_v2/test_flow_loc_parity.py +336 -0
  281. dynvo-1.33.0/tests/pipeline_v2/test_incremental.py +148 -0
  282. dynvo-1.33.0/tests/pipeline_v2/test_incremental_gate.py +252 -0
  283. dynvo-1.33.0/tests/pipeline_v2/test_incremental_gate_layer2.py +356 -0
  284. dynvo-1.33.0/tests/pipeline_v2/test_indexes.py +172 -0
  285. dynvo-1.33.0/tests/pipeline_v2/test_lineage.py +144 -0
  286. dynvo-1.33.0/tests/pipeline_v2/test_naming_validator.py +170 -0
  287. dynvo-1.33.0/tests/pipeline_v2/test_naming_validator_wiring.py +379 -0
  288. dynvo-1.33.0/tests/pipeline_v2/test_nav_taxonomy.py +459 -0
  289. dynvo-1.33.0/tests/pipeline_v2/test_product_strings.py +238 -0
  290. dynvo-1.33.0/tests/pipeline_v2/test_snapshots.py +440 -0
  291. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_7_user_flows.py +822 -0
  292. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_8_lineage.py +88 -0
  293. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_95_history.py +583 -0
  294. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_95_history_integration.py +282 -0
  295. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_96_impact.py +453 -0
  296. dynvo-1.33.0/tests/pipeline_v2/test_stage_6_9_test_strip.py +386 -0
  297. dynvo-1.33.0/tests/test_ast_extractor.py +259 -0
  298. dynvo-1.33.0/tests/test_auto_alias_discoverer.py +171 -0
  299. dynvo-1.33.0/tests/test_benchmark.py +356 -0
  300. dynvo-1.33.0/tests/test_cache.py +161 -0
  301. dynvo-1.33.0/tests/test_cache_backend.py +197 -0
  302. dynvo-1.33.0/tests/test_cache_backend_integration.py +132 -0
  303. dynvo-1.33.0/tests/test_cache_symbols.py +300 -0
  304. dynvo-1.33.0/tests/test_cli_scan_v2.py +381 -0
  305. dynvo-1.33.0/tests/test_cloud.py +80 -0
  306. dynvo-1.33.0/tests/test_cost.py +240 -0
  307. dynvo-1.33.0/tests/test_discovery.py +254 -0
  308. dynvo-1.33.0/tests/test_domain_noun.py +188 -0
  309. dynvo-1.33.0/tests/test_extractor_django.py +290 -0
  310. dynvo-1.33.0/tests/test_extractor_express.py +360 -0
  311. dynvo-1.33.0/tests/test_extractor_fastify.py +219 -0
  312. dynvo-1.33.0/tests/test_extractor_go_packages.py +145 -0
  313. dynvo-1.33.0/tests/test_extractor_go_router.py +250 -0
  314. dynvo-1.33.0/tests/test_extractor_js_library.py +419 -0
  315. dynvo-1.33.0/tests/test_extractor_js_library_source_modules.py +176 -0
  316. dynvo-1.33.0/tests/test_extractor_python_library.py +175 -0
  317. dynvo-1.33.0/tests/test_extractor_rails_helpers.py +151 -0
  318. dynvo-1.33.0/tests/test_extractor_rails_jobs.py +126 -0
  319. dynvo-1.33.0/tests/test_extractor_rails_models.py +151 -0
  320. dynvo-1.33.0/tests/test_extractor_rails_routes.py +131 -0
  321. dynvo-1.33.0/tests/test_extractor_rails_stimulus.py +105 -0
  322. dynvo-1.33.0/tests/test_extractor_rails_views.py +105 -0
  323. dynvo-1.33.0/tests/test_extractor_route_workspace_roots.py +270 -0
  324. dynvo-1.33.0/tests/test_extractor_rust_packages.py +289 -0
  325. dynvo-1.33.0/tests/test_extractor_rust_workspace.py +174 -0
  326. dynvo-1.33.0/tests/test_features.py +735 -0
  327. dynvo-1.33.0/tests/test_flow_expansion_fanin.py +281 -0
  328. dynvo-1.33.0/tests/test_flow_reach.py +386 -0
  329. dynvo-1.33.0/tests/test_flow_symbols_v2.py +366 -0
  330. dynvo-1.33.0/tests/test_flow_test_mapper.py +295 -0
  331. dynvo-1.33.0/tests/test_framework_linkers/__init__.py +0 -0
  332. dynvo-1.33.0/tests/test_framework_linkers/test_nextjs_http_route.py +244 -0
  333. dynvo-1.33.0/tests/test_framework_linkers/test_nextjs_server_actions.py +231 -0
  334. dynvo-1.33.0/tests/test_framework_linkers/test_store_mutation.py +352 -0
  335. dynvo-1.33.0/tests/test_framework_linkers/test_trpc_procedure.py +287 -0
  336. dynvo-1.33.0/tests/test_get_symbol_range.py +127 -0
  337. dynvo-1.33.0/tests/test_git.py +659 -0
  338. dynvo-1.33.0/tests/test_git_snapshot_partition.py +212 -0
  339. dynvo-1.33.0/tests/test_git_subpath_scoping.py +123 -0
  340. dynvo-1.33.0/tests/test_go_imports.py +194 -0
  341. dynvo-1.33.0/tests/test_go_rust_extraction.py +119 -0
  342. dynvo-1.33.0/tests/test_import_graph.py +689 -0
  343. dynvo-1.33.0/tests/test_incremental_gate_run.py +259 -0
  344. dynvo-1.33.0/tests/test_llm_health.py +622 -0
  345. dynvo-1.33.0/tests/test_marketing_fetcher.py +505 -0
  346. dynvo-1.33.0/tests/test_mcp_server.py +372 -0
  347. dynvo-1.33.0/tests/test_method_level_resolution.py +195 -0
  348. dynvo-1.33.0/tests/test_model_gateway.py +151 -0
  349. dynvo-1.33.0/tests/test_pipeline_decomposition.py +400 -0
  350. dynvo-1.33.0/tests/test_pipeline_v2_data_hermetic.py +315 -0
  351. dynvo-1.33.0/tests/test_pipeline_v2_isolation.py +270 -0
  352. dynvo-1.33.0/tests/test_post_process.py +233 -0
  353. dynvo-1.33.0/tests/test_post_process_naming_fixes.py +204 -0
  354. dynvo-1.33.0/tests/test_python_imports.py +160 -0
  355. dynvo-1.33.0/tests/test_repo_config.py +250 -0
  356. dynvo-1.33.0/tests/test_residual_clusterer.py +280 -0
  357. dynvo-1.33.0/tests/test_reverse_cross_stack.py +224 -0
  358. dynvo-1.33.0/tests/test_reverse_imports.py +95 -0
  359. dynvo-1.33.0/tests/test_roles.py +127 -0
  360. dynvo-1.33.0/tests/test_run_dir.py +140 -0
  361. dynvo-1.33.0/tests/test_run_logger.py +101 -0
  362. dynvo-1.33.0/tests/test_run_pipeline_multi.py +364 -0
  363. dynvo-1.33.0/tests/test_run_pipeline_v2.py +247 -0
  364. dynvo-1.33.0/tests/test_rust_imports.py +154 -0
  365. dynvo-1.33.0/tests/test_schema_layer1.py +216 -0
  366. dynvo-1.33.0/tests/test_stack_auditor.py +778 -0
  367. dynvo-1.33.0/tests/test_stage_0_6_shape.py +1280 -0
  368. dynvo-1.33.0/tests/test_stage_0_intake.py +335 -0
  369. dynvo-1.33.0/tests/test_stage_0_lib_stack_detection.py +135 -0
  370. dynvo-1.33.0/tests/test_stage_0_subpath_scoping.py +165 -0
  371. dynvo-1.33.0/tests/test_stage_1_extractor_wirings.py +424 -0
  372. dynvo-1.33.0/tests/test_stage_1_extractors.py +245 -0
  373. dynvo-1.33.0/tests/test_stage_1_per_workspace.py +429 -0
  374. dynvo-1.33.0/tests/test_stage_2_6_membership_closure.py +567 -0
  375. dynvo-1.33.0/tests/test_stage_2_rails_merger.py +165 -0
  376. dynvo-1.33.0/tests/test_stage_2_reconcile.py +577 -0
  377. dynvo-1.33.0/tests/test_stage_3_flows.py +519 -0
  378. dynvo-1.33.0/tests/test_stage_4_guards.py +500 -0
  379. dynvo-1.33.0/tests/test_stage_4_residual.py +524 -0
  380. dynvo-1.33.0/tests/test_stage_4_residual_cache.py +206 -0
  381. dynvo-1.33.0/tests/test_stage_5_3_sibling_collapse.py +460 -0
  382. dynvo-1.33.0/tests/test_stage_5_5_bipartite.py +349 -0
  383. dynvo-1.33.0/tests/test_stage_5_a1_validation.py +278 -0
  384. dynvo-1.33.0/tests/test_stage_5_postprocess.py +563 -0
  385. dynvo-1.33.0/tests/test_stage_6_3_import_tree.py +548 -0
  386. dynvo-1.33.0/tests/test_stage_6_3_import_tree_parallel.py +272 -0
  387. dynvo-1.33.0/tests/test_stage_6_4_framework_enrich.py +245 -0
  388. dynvo-1.33.0/tests/test_stage_6_4_framework_enrich_parallel.py +209 -0
  389. dynvo-1.33.0/tests/test_stage_6_5_h3_alias_guard.py +109 -0
  390. dynvo-1.33.0/tests/test_stage_6_5_product_clusterer.py +633 -0
  391. dynvo-1.33.0/tests/test_stage_6_6_branch_slicer.py +609 -0
  392. dynvo-1.33.0/tests/test_stage_6_6_branch_slicer_parallel.py +176 -0
  393. dynvo-1.33.0/tests/test_stage_6_7b_uf_refiner.py +293 -0
  394. dynvo-1.33.0/tests/test_stage_6_7c_uf_splitter.py +146 -0
  395. dynvo-1.33.0/tests/test_stage_6_metrics.py +389 -0
  396. dynvo-1.33.0/tests/test_stage_7_output.py +191 -0
  397. dynvo-1.33.0/tests/test_stage_8_5_member_backfill.py +187 -0
  398. dynvo-1.33.0/tests/test_stage_8_6_5_scaffold_filter.py +102 -0
  399. dynvo-1.33.0/tests/test_stage_8_6_nonsource_drop.py +204 -0
  400. dynvo-1.33.0/tests/test_stage_8_7_anchor_desink.py +226 -0
  401. dynvo-1.33.0/tests/test_stage_8_8_shared_members.py +113 -0
  402. dynvo-1.33.0/tests/test_stage_8_analyst.py +535 -0
  403. dynvo-1.33.0/tests/test_stage_8_marketing_clusterer.py +699 -0
  404. dynvo-1.33.0/tests/test_stage_8_rollup_strategies.py +780 -0
  405. dynvo-1.33.0/tests/test_structural_audit.py +165 -0
  406. dynvo-1.33.0/tests/test_symbol_graph.py +351 -0
  407. dynvo-1.33.0/tests/test_symbols.py +264 -0
  408. dynvo-1.33.0/tests/test_test_attribution.py +171 -0
  409. dynvo-1.33.0/tests/test_test_mapper.py +218 -0
  410. dynvo-1.33.0/tests/test_tsconfig_paths.py +205 -0
  411. dynvo-1.33.0/tests/test_url_linker.py +607 -0
  412. dynvo-1.33.0/tests/test_url_route_resolver.py +307 -0
  413. dynvo-1.33.0/tests/test_validation.py +246 -0
  414. dynvo-1.33.0/tests/test_watch.py +199 -0
  415. dynvo-1.33.0/tests/test_wheel_hermetic.py +130 -0
  416. dynvo-1.33.0/tests/test_workspace_package_detection.py +391 -0
  417. dynvo-1.33.0/tests/test_writer.py +57 -0
  418. dynvo-1.33.0/uv.lock +1255 -0
@@ -0,0 +1,121 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ name: Tests (Python ${{ matrix.python-version }})
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: ["3.11", "3.12"]
21
+
22
+ steps:
23
+ - name: Checkout
24
+ uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0 # full history so git-log-based tests work
27
+
28
+ - name: Set up Python ${{ matrix.python-version }}
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+ cache: pip
33
+
34
+ - name: Install dependencies
35
+ run: |
36
+ python -m pip install --upgrade pip
37
+ # `mcp` extra removed (MCP is now the standalone faultlines-mcp package);
38
+ # keep `watch` which the engine tests still use.
39
+ pip install -e '.[watch]'
40
+ # The standalone MCP package — tests/test_mcp_server.py imports it.
41
+ pip install -e ./faultlines-mcp
42
+ pip install pytest pytest-cov
43
+
44
+ - name: Run tests
45
+ run: |
46
+ pytest tests/ \
47
+ -k "not test_reads_api_key_from_env_var" \
48
+ --cov=faultline \
49
+ --cov-report=xml \
50
+ --cov-report=term-missing:skip-covered
51
+
52
+ - name: Upload coverage
53
+ if: matrix.python-version == '3.11'
54
+ uses: actions/upload-artifact@v4
55
+ with:
56
+ name: coverage-report
57
+ path: coverage.xml
58
+ retention-days: 7
59
+
60
+ lint:
61
+ name: Lint
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+
66
+ - uses: actions/setup-python@v5
67
+ with:
68
+ python-version: "3.11"
69
+ cache: pip
70
+
71
+ - name: Install ruff
72
+ run: pip install ruff
73
+
74
+ - name: Run ruff
75
+ run: |
76
+ ruff check faultline/ tests/ || true
77
+ ruff format --check faultline/ tests/ || true
78
+
79
+ typecheck:
80
+ name: Type check (mypy, pipeline_v2)
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+
85
+ - uses: actions/setup-python@v5
86
+ with:
87
+ python-version: "3.11"
88
+ cache: pip
89
+
90
+ - name: Install dependencies
91
+ run: |
92
+ python -m pip install --upgrade pip
93
+ pip install -e '.[watch]'
94
+ pip install mypy types-PyYAML
95
+
96
+ # Blocking — pipeline_v2 must stay mypy-clean (lenient config in
97
+ # pyproject.toml [tool.mypy]).
98
+ - name: Run mypy
99
+ run: mypy faultline/pipeline_v2
100
+
101
+ build:
102
+ name: Build wheel
103
+ runs-on: ubuntu-latest
104
+ steps:
105
+ - uses: actions/checkout@v4
106
+
107
+ - uses: actions/setup-python@v5
108
+ with:
109
+ python-version: "3.11"
110
+
111
+ - name: Install build
112
+ run: pip install build
113
+
114
+ - name: Build
115
+ run: python -m build
116
+
117
+ - name: Check artifacts
118
+ run: |
119
+ ls -la dist/
120
+ pip install twine
121
+ twine check dist/*
@@ -0,0 +1,276 @@
1
+ name: Release
2
+
3
+ # Auto-publish to PyPI on merge to main. Each package is released
4
+ # independently based on which paths changed. Every release minor-bumps the
5
+ # package version.
6
+ #
7
+ # Flow: detect → test → stage → release
8
+ # 0. `test` — run the suite. Gates everything: if tests fail, nothing
9
+ # is built or published.
10
+ # 1. `stage` — bump + build + upload to TestPyPI. Runs automatically
11
+ # (the `testpypi` Environment has no required reviewers).
12
+ # 2. `release` — publish the SAME artifacts to the real PyPI, then commit
13
+ # the bump + tag back to main. Gated behind the `pypi`
14
+ # Environment, so prod publishing waits for your Approve.
15
+ # Prod only runs if TestPyPI staging succeeded (`needs: stage`).
16
+ on:
17
+ push:
18
+ branches: [main]
19
+
20
+ # Serialize releases so two quick merges can't race on the version bump /
21
+ # push-back to main.
22
+ concurrency:
23
+ group: release-main
24
+ cancel-in-progress: false
25
+
26
+ permissions:
27
+ contents: read
28
+
29
+ jobs:
30
+ detect:
31
+ name: Detect changed packages
32
+ runs-on: ubuntu-latest
33
+ # Skip the release commit this workflow pushes back (belt-and-braces with
34
+ # the `[skip ci]` marker in that commit message).
35
+ if: ${{ !contains(github.event.head_commit.message, 'chore(release)') }}
36
+ outputs:
37
+ engine: ${{ steps.filter.outputs.engine }}
38
+ mcp: ${{ steps.filter.outputs.mcp }}
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+
42
+ - uses: dorny/paths-filter@v3
43
+ id: filter
44
+ with:
45
+ filters: |
46
+ engine:
47
+ - 'faultline/**'
48
+ - 'pyproject.toml'
49
+ - 'README.md' # shipped as the engine's long_description
50
+ mcp:
51
+ - 'faultlines-mcp/**'
52
+
53
+ test:
54
+ name: Tests
55
+ needs: detect
56
+ # Only run when there's actually something to release — no point gating
57
+ # on tests for a merge that touches neither package.
58
+ if: ${{ needs.detect.outputs.engine == 'true' || needs.detect.outputs.mcp == 'true' }}
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - name: Checkout
62
+ uses: actions/checkout@v4
63
+ with:
64
+ fetch-depth: 0 # full history so git-log-based tests work
65
+
66
+ - name: Set up Python
67
+ uses: actions/setup-python@v5
68
+ with:
69
+ python-version: "3.11"
70
+ cache: pip
71
+
72
+ - name: Install dependencies
73
+ run: |
74
+ python -m pip install --upgrade pip
75
+ pip install -e '.[watch]'
76
+ pip install -e ./faultlines-mcp
77
+ pip install pytest pytest-cov
78
+
79
+ - name: Run tests
80
+ run: |
81
+ pytest tests/ \
82
+ -k "not test_reads_api_key_from_env_var" \
83
+ --cov=faultline \
84
+ --cov-report=term-missing:skip-covered
85
+
86
+ stage:
87
+ name: Bump, build, stage on TestPyPI
88
+ # Gate the whole release on the test suite: if tests fail, `test` fails,
89
+ # `stage` is skipped, and nothing is published to TestPyPI or PyPI.
90
+ needs: [detect, test]
91
+ if: ${{ needs.detect.outputs.engine == 'true' || needs.detect.outputs.mcp == 'true' }}
92
+ runs-on: ubuntu-latest
93
+ # `testpypi` Environment: configure it WITHOUT required reviewers so
94
+ # staging runs automatically. TestPyPI trusted publishers must use
95
+ # environment name `testpypi` to match this job's OIDC claim.
96
+ environment:
97
+ name: testpypi
98
+ url: https://test.pypi.org/project/dynvo/
99
+ permissions:
100
+ id-token: write # OIDC token for TestPyPI Trusted Publishing
101
+ outputs:
102
+ engine_version: ${{ steps.engine.outputs.version }}
103
+ mcp_version: ${{ steps.mcp.outputs.version }}
104
+
105
+ steps:
106
+ - name: Checkout
107
+ uses: actions/checkout@v4
108
+
109
+ - name: Set up Python
110
+ uses: actions/setup-python@v5
111
+ with:
112
+ python-version: "3.11"
113
+
114
+ - name: Install build tooling
115
+ run: python -m pip install --upgrade build
116
+
117
+ # --- Version bump (working tree only; committed in the prod job) ---
118
+ - name: Bump engine (dynvo) minor version
119
+ id: engine
120
+ if: ${{ needs.detect.outputs.engine == 'true' }}
121
+ run: echo "version=$(python scripts/bump_minor_version.py pyproject.toml)" >> "$GITHUB_OUTPUT"
122
+
123
+ - name: Bump mcp (faultlines-mcp) minor version
124
+ id: mcp
125
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
126
+ run: echo "version=$(python scripts/bump_minor_version.py faultlines-mcp/pyproject.toml)" >> "$GITHUB_OUTPUT"
127
+
128
+ # --- Build ---
129
+ - name: Build engine
130
+ if: ${{ needs.detect.outputs.engine == 'true' }}
131
+ run: python -m build --outdir dist .
132
+
133
+ - name: Build mcp
134
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
135
+ run: python -m build --outdir faultlines-mcp/dist faultlines-mcp
136
+
137
+ # --- Stage on TestPyPI (skip-existing → idempotent re-runs) ---
138
+ # attestations: false — staging is validation only, and any
139
+ # .publish.attestation files generated here would ride along in the
140
+ # uploaded artifact and make the prod publish fail ("distributions
141
+ # already have publish attestations"). Prod generates fresh ones.
142
+ - name: Stage engine on TestPyPI
143
+ if: ${{ needs.detect.outputs.engine == 'true' }}
144
+ uses: pypa/gh-action-pypi-publish@release/v1
145
+ with:
146
+ repository-url: https://test.pypi.org/legacy/
147
+ packages-dir: dist/
148
+ skip-existing: true
149
+ attestations: false
150
+
151
+ - name: Stage mcp on TestPyPI
152
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
153
+ uses: pypa/gh-action-pypi-publish@release/v1
154
+ with:
155
+ repository-url: https://test.pypi.org/legacy/
156
+ packages-dir: faultlines-mcp/dist/
157
+ skip-existing: true
158
+ attestations: false
159
+
160
+ # --- Hand the exact built artifacts to the prod job ---
161
+ - name: Upload engine artifact
162
+ if: ${{ needs.detect.outputs.engine == 'true' }}
163
+ uses: actions/upload-artifact@v4
164
+ with:
165
+ name: dist-engine
166
+ path: dist/
167
+
168
+ - name: Upload mcp artifact
169
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
170
+ uses: actions/upload-artifact@v4
171
+ with:
172
+ name: dist-mcp
173
+ path: faultlines-mcp/dist/
174
+
175
+ release:
176
+ name: Publish to PyPI (approved)
177
+ needs: [detect, stage]
178
+ if: ${{ needs.detect.outputs.engine == 'true' || needs.detect.outputs.mcp == 'true' }}
179
+ runs-on: ubuntu-latest
180
+ # `pypi` Environment: configure it WITH required reviewers so this job
181
+ # pauses for your Approve before anything reaches the real PyPI. PyPI
182
+ # trusted publishers must use environment name `pypi`.
183
+ environment:
184
+ name: pypi
185
+ url: https://pypi.org/project/dynvo/
186
+ permissions:
187
+ contents: write # push the version-bump commit + tags back to main
188
+ id-token: write # OIDC token for PyPI Trusted Publishing
189
+
190
+ steps:
191
+ - name: Checkout
192
+ uses: actions/checkout@v4
193
+ with:
194
+ fetch-depth: 0
195
+
196
+ - name: Set up Python
197
+ uses: actions/setup-python@v5
198
+ with:
199
+ python-version: "3.11"
200
+
201
+ # --- Pull the exact artifacts validated on TestPyPI ---
202
+ - name: Download engine artifact
203
+ if: ${{ needs.detect.outputs.engine == 'true' }}
204
+ uses: actions/download-artifact@v4
205
+ with:
206
+ name: dist-engine
207
+ path: dist/
208
+
209
+ - name: Download mcp artifact
210
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
211
+ uses: actions/download-artifact@v4
212
+ with:
213
+ name: dist-mcp
214
+ path: faultlines-mcp/dist/
215
+
216
+ # --- Publish to the real PyPI (default repository-url) ---
217
+ - name: Publish engine to PyPI
218
+ if: ${{ needs.detect.outputs.engine == 'true' }}
219
+ uses: pypa/gh-action-pypi-publish@release/v1
220
+ with:
221
+ packages-dir: dist/
222
+
223
+ - name: Publish mcp to PyPI
224
+ if: ${{ needs.detect.outputs.mcp == 'true' }}
225
+ uses: pypa/gh-action-pypi-publish@release/v1
226
+ with:
227
+ packages-dir: faultlines-mcp/dist/
228
+
229
+ # --- Notify faultlines-app to redeploy the worker on the new engine ---
230
+ - name: Ping faultlines-app (engine published)
231
+ if: ${{ needs.detect.outputs.engine == 'true' }}
232
+ continue-on-error: true
233
+ env:
234
+ DISPATCH_TOKEN: ${{ secrets.FAULTLINES_APP_DISPATCH_TOKEN }}
235
+ run: |
236
+ if [ -z "$DISPATCH_TOKEN" ]; then
237
+ echo "FAULTLINES_APP_DISPATCH_TOKEN not set — skipping worker ping (the 6h PyPI poll picks up this release)."
238
+ exit 0
239
+ fi
240
+ curl -fsSL -X POST \
241
+ -H "Authorization: Bearer $DISPATCH_TOKEN" \
242
+ -H "Accept: application/vnd.github+json" \
243
+ https://api.github.com/repos/PashaSchool/faultlines-app/dispatches \
244
+ -d '{"event_type":"engine-published","client_payload":{"version":"${{ needs.stage.outputs.engine_version }}"}}'
245
+
246
+ # --- Persist the bump back to main only after prod publish succeeds ---
247
+ # Re-run the deterministic bump on a fresh main checkout so pyproject
248
+ # reflects the just-published version. The numbers come from the stage
249
+ # job's outputs (the same versions baked into the published artifacts).
250
+ - name: Commit version bumps and tag
251
+ run: |
252
+ git config user.name "github-actions[bot]"
253
+ git config user.email "github-actions[bot]@users.noreply.github.com"
254
+
255
+ summary=""
256
+ if [ "${{ needs.detect.outputs.engine }}" = "true" ]; then
257
+ python scripts/bump_minor_version.py pyproject.toml >/dev/null
258
+ summary="dynvo v${{ needs.stage.outputs.engine_version }}"
259
+ fi
260
+ if [ "${{ needs.detect.outputs.mcp }}" = "true" ]; then
261
+ python scripts/bump_minor_version.py faultlines-mcp/pyproject.toml >/dev/null
262
+ [ -n "$summary" ] && summary="$summary, "
263
+ summary="${summary}faultlines-mcp v${{ needs.stage.outputs.mcp_version }}"
264
+ fi
265
+
266
+ git add pyproject.toml faultlines-mcp/pyproject.toml
267
+ git commit -m "chore(release): $summary [skip ci]"
268
+
269
+ if [ "${{ needs.detect.outputs.engine }}" = "true" ]; then
270
+ git tag -a "dynvo-v${{ needs.stage.outputs.engine_version }}" -m "dynvo v${{ needs.stage.outputs.engine_version }}"
271
+ fi
272
+ if [ "${{ needs.detect.outputs.mcp }}" = "true" ]; then
273
+ git tag -a "faultlines-mcp-v${{ needs.stage.outputs.mcp_version }}" -m "faultlines-mcp v${{ needs.stage.outputs.mcp_version }}"
274
+ fi
275
+
276
+ git push origin HEAD:main --follow-tags
@@ -0,0 +1,21 @@
1
+ name: Secrets scan
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ gitleaks:
11
+ name: Gitleaks
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with:
16
+ fetch-depth: 0 # full history for PR scans
17
+
18
+ - name: Run gitleaks
19
+ uses: gitleaks/gitleaks-action@v2
20
+ env:
21
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,66 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ *.so
7
+ *.egg
8
+ *.egg-info/
9
+ dist/
10
+ build/
11
+ .eggs/
12
+ wheels/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+ ENV/
19
+
20
+ # Testing
21
+ .pytest_cache/
22
+ .coverage
23
+ coverage.xml
24
+ htmlcov/
25
+ .tox/
26
+
27
+ # Type checking
28
+ .mypy_cache/
29
+ .pyright/
30
+
31
+ # featuremap output
32
+ .featuremap/
33
+ .faultline
34
+
35
+ # IDE
36
+ .vscode/
37
+ .idea/
38
+ *.swp
39
+ *.swo
40
+ .DS_Store
41
+
42
+ # Secrets
43
+ .env
44
+ .env.local
45
+ .env.*
46
+ *.key
47
+
48
+ # Hatch
49
+ .hatch/
50
+
51
+ # Internal mission docs (not for public)
52
+ memory/
53
+
54
+ # Landing page screenshots
55
+ *.png
56
+ *.webp
57
+ # …but keep committed brand/README assets
58
+ !assets/
59
+ !assets/**
60
+
61
+ # Waitlist data
62
+ waitlist.json
63
+
64
+ .pypirc
65
+ docs/
66
+ .pypirc
@@ -0,0 +1,30 @@
1
+ # Gitleaks config for faultlines
2
+ # See https://github.com/gitleaks/gitleaks/blob/master/README.md
3
+ #
4
+ # We inherit the default ruleset and just allow-list the placeholder
5
+ # strings that appear in docstrings and error messages. Never put real
6
+ # secrets here — this file is public.
7
+
8
+ title = "faultlines gitleaks config"
9
+
10
+ [extend]
11
+ useDefault = true
12
+
13
+ [allowlist]
14
+ description = "Ignore placeholders and docstring examples"
15
+ regexes = [
16
+ # "sk-ant-..." is a doc placeholder, not a real key
17
+ '''sk-ant-\.\.\.''',
18
+ # CLI validation pattern, not a key
19
+ '''startswith\(['"]sk-ant-['"]''',
20
+ # Help text and docstrings referencing the key format
21
+ '''ANTHROPIC_API_KEY''',
22
+ ]
23
+ paths = [
24
+ # These files contain only docs, examples, and regex validators
25
+ '''^faultline/llm/detector\.py$''',
26
+ '''^faultline/cli\.py$''',
27
+ '''^tests/''',
28
+ '''^README\.md$''',
29
+ '''^CHANGELOG\.md$''',
30
+ ]
@@ -0,0 +1,40 @@
1
+ # Pre-commit hooks for faultlines.
2
+ # Install: pip install pre-commit && pre-commit install
3
+ # Run manually: pre-commit run --all-files
4
+
5
+ repos:
6
+ # Basic hygiene
7
+ - repo: https://github.com/pre-commit/pre-commit-hooks
8
+ rev: v5.0.0
9
+ hooks:
10
+ - id: trailing-whitespace
11
+ - id: end-of-file-fixer
12
+ - id: check-yaml
13
+ - id: check-toml
14
+ - id: check-added-large-files
15
+ args: ["--maxkb=500"]
16
+ - id: check-merge-conflict
17
+ - id: detect-private-key
18
+ - id: mixed-line-ending
19
+
20
+ # Secret scanning — catches API keys, tokens, credentials
21
+ - repo: https://github.com/gitleaks/gitleaks
22
+ rev: v8.21.2
23
+ hooks:
24
+ - id: gitleaks
25
+
26
+ # Python linting + formatting
27
+ - repo: https://github.com/astral-sh/ruff-pre-commit
28
+ rev: v0.8.6
29
+ hooks:
30
+ - id: ruff
31
+ args: [--fix, --exit-non-zero-on-fix]
32
+ - id: ruff-format
33
+
34
+ # detect-secrets — complementary to gitleaks, uses entropy heuristics
35
+ - repo: https://github.com/Yelp/detect-secrets
36
+ rev: v1.5.0
37
+ hooks:
38
+ - id: detect-secrets
39
+ args: ["--baseline", ".secrets.baseline"]
40
+ exclude: package.lock.json