semdex 1.5.6__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 (531) hide show
  1. semdex-1.5.6/.claude/skills/bench-rerun/SKILL.md +81 -0
  2. semdex-1.5.6/.devcontainer/devcontainer.json +22 -0
  3. semdex-1.5.6/.devcontainer/settings.json +6 -0
  4. semdex-1.5.6/.env.example +468 -0
  5. semdex-1.5.6/.github/actions/extract-metadata/action.yml +108 -0
  6. semdex-1.5.6/.github/dependabot.yml +22 -0
  7. semdex-1.5.6/.github/workflows/codeql.yml +39 -0
  8. semdex-1.5.6/.github/workflows/default_cicd_public.yml +472 -0
  9. semdex-1.5.6/.github/workflows/default_release_public.yml +95 -0
  10. semdex-1.5.6/.github/workflows/integration.yml +190 -0
  11. semdex-1.5.6/.gitignore +222 -0
  12. semdex-1.5.6/.qlty/qlty.toml +2 -0
  13. semdex-1.5.6/.snyk +5 -0
  14. semdex-1.5.6/CHANGELOG.md +522 -0
  15. semdex-1.5.6/CONFIG.md +590 -0
  16. semdex-1.5.6/CONTRIBUTING.md +48 -0
  17. semdex-1.5.6/DEVELOPMENT.md +151 -0
  18. semdex-1.5.6/INSTALL.md +142 -0
  19. semdex-1.5.6/LICENSE +22 -0
  20. semdex-1.5.6/Makefile +487 -0
  21. semdex-1.5.6/PKG-INFO +549 -0
  22. semdex-1.5.6/README.md +420 -0
  23. semdex-1.5.6/SECURITY.md +37 -0
  24. semdex-1.5.6/ai-stance.md +90 -0
  25. semdex-1.5.6/ai-transparency.md +117 -0
  26. semdex-1.5.6/codecov.yml +27 -0
  27. semdex-1.5.6/docs/BENCHMARKS.md +7 -0
  28. semdex-1.5.6/docs/COMPONENT_SETUP.md +336 -0
  29. semdex-1.5.6/docs/adr/0001-memory-adapters-in-src.md +29 -0
  30. semdex-1.5.6/docs/adr/0002-mcp-server-adapter.md +63 -0
  31. semdex-1.5.6/docs/bench_chunk_params.md +7 -0
  32. semdex-1.5.6/docs/bench_chunker.md +7 -0
  33. semdex-1.5.6/docs/bench_database.md +7 -0
  34. semdex-1.5.6/docs/bench_embedding.md +7 -0
  35. semdex-1.5.6/docs/bench_extractor.md +7 -0
  36. semdex-1.5.6/docs/bench_pre_computed_vectors.md +7 -0
  37. semdex-1.5.6/docs/benchmarks/01-method.md +360 -0
  38. semdex-1.5.6/docs/benchmarks/02-extraction.md +288 -0
  39. semdex-1.5.6/docs/benchmarks/03-chunking.md +2970 -0
  40. semdex-1.5.6/docs/benchmarks/04-embedding.md +301 -0
  41. semdex-1.5.6/docs/benchmarks/05-vector-store.md +411 -0
  42. semdex-1.5.6/docs/benchmarks/06-retrieval-method.md +230 -0
  43. semdex-1.5.6/docs/benchmarks/07-selection.md +242 -0
  44. semdex-1.5.6/docs/benchmarks/08-gaps.md +535 -0
  45. semdex-1.5.6/docs/benchmarks/README.md +70 -0
  46. semdex-1.5.6/docs/benchmarks/explorer.html +271 -0
  47. semdex-1.5.6/docs/benchmarks/generated-tables.manifest.json +57 -0
  48. semdex-1.5.6/docs/benchmarks/img/ann_frontier-dark.png +0 -0
  49. semdex-1.5.6/docs/benchmarks/img/ann_frontier.png +0 -0
  50. semdex-1.5.6/docs/benchmarks/img/charts.manifest.json +19 -0
  51. semdex-1.5.6/docs/benchmarks/img/chunk_knob_breakpoint_model-dark.png +0 -0
  52. semdex-1.5.6/docs/benchmarks/img/chunk_knob_breakpoint_model.png +0 -0
  53. semdex-1.5.6/docs/benchmarks/img/chunk_knob_embedding-dark.png +0 -0
  54. semdex-1.5.6/docs/benchmarks/img/chunk_knob_embedding.png +0 -0
  55. semdex-1.5.6/docs/benchmarks/img/chunk_knob_max_tokens-dark.png +0 -0
  56. semdex-1.5.6/docs/benchmarks/img/chunk_knob_max_tokens.png +0 -0
  57. semdex-1.5.6/docs/benchmarks/img/chunk_knob_method-dark.png +0 -0
  58. semdex-1.5.6/docs/benchmarks/img/chunk_knob_method.png +0 -0
  59. semdex-1.5.6/docs/benchmarks/img/chunk_knob_overlap_tokens-dark.png +0 -0
  60. semdex-1.5.6/docs/benchmarks/img/chunk_knob_overlap_tokens.png +0 -0
  61. semdex-1.5.6/docs/benchmarks/img/chunk_knob_strategy-dark.png +0 -0
  62. semdex-1.5.6/docs/benchmarks/img/chunk_knob_strategy.png +0 -0
  63. semdex-1.5.6/docs/benchmarks/img/chunk_markdown_structure-dark.png +0 -0
  64. semdex-1.5.6/docs/benchmarks/img/chunk_markdown_structure.png +0 -0
  65. semdex-1.5.6/docs/benchmarks/img/chunker_quality-dark.png +0 -0
  66. semdex-1.5.6/docs/benchmarks/img/chunker_quality.png +0 -0
  67. semdex-1.5.6/docs/benchmarks/img/chunker_throughput-dark.png +0 -0
  68. semdex-1.5.6/docs/benchmarks/img/chunker_throughput.png +0 -0
  69. semdex-1.5.6/docs/benchmarks/img/embedding_german_ranking-dark.png +0 -0
  70. semdex-1.5.6/docs/benchmarks/img/embedding_german_ranking.png +0 -0
  71. semdex-1.5.6/docs/benchmarks/img/embedding_model_ranking-dark.png +0 -0
  72. semdex-1.5.6/docs/benchmarks/img/embedding_model_ranking.png +0 -0
  73. semdex-1.5.6/docs/benchmarks/img/end_to_end_quality-dark.png +0 -0
  74. semdex-1.5.6/docs/benchmarks/img/end_to_end_quality.png +0 -0
  75. semdex-1.5.6/docs/benchmarks/img/extraction_real-dark.png +0 -0
  76. semdex-1.5.6/docs/benchmarks/img/extraction_real.png +0 -0
  77. semdex-1.5.6/docs/benchmarks/img/extractor_latency-dark.png +0 -0
  78. semdex-1.5.6/docs/benchmarks/img/extractor_latency.png +0 -0
  79. semdex-1.5.6/docs/benchmarks/img/ocr_badscans-dark.png +0 -0
  80. semdex-1.5.6/docs/benchmarks/img/ocr_badscans.png +0 -0
  81. semdex-1.5.6/docs/benchmarks/img/span_integrity-dark.png +0 -0
  82. semdex-1.5.6/docs/benchmarks/img/span_integrity.png +0 -0
  83. semdex-1.5.6/docs/benchmarks/img/store_dim_crossover-dark.png +0 -0
  84. semdex-1.5.6/docs/benchmarks/img/store_dim_crossover.png +0 -0
  85. semdex-1.5.6/docs/benchmarks/img/store_dim_real-dark.png +0 -0
  86. semdex-1.5.6/docs/benchmarks/img/store_dim_real.png +0 -0
  87. semdex-1.5.6/docs/benchmarks/img/store_memory-dark.png +0 -0
  88. semdex-1.5.6/docs/benchmarks/img/store_memory.png +0 -0
  89. semdex-1.5.6/docs/benchmarks/img/store_scale_trends-dark.png +0 -0
  90. semdex-1.5.6/docs/benchmarks/img/store_scale_trends.png +0 -0
  91. semdex-1.5.6/docs/plans/2026-07-09-mcp-server-step4.md +414 -0
  92. semdex-1.5.6/docs/plans/2026-07-09-mcp-server-step5.md +571 -0
  93. semdex-1.5.6/docs/plans/2026-07-09-mcp-server-step6.md +470 -0
  94. semdex-1.5.6/docs/plans/2026-07-14-ann-tuning-and-embed-batch-config-design.md +158 -0
  95. semdex-1.5.6/docs/plans/2026-07-22-chunk-sanitize-design.md +114 -0
  96. semdex-1.5.6/docs/plans/2026-09-27-effect-floors-design.md +80 -0
  97. semdex-1.5.6/docs/plans/2026-09-27-effect-floors-plan.md +949 -0
  98. semdex-1.5.6/docs/plans/2026-09-27-markdown-structure-design.md +131 -0
  99. semdex-1.5.6/docs/plans/2026-09-27-markdown-structure-plan.md +1478 -0
  100. semdex-1.5.6/docs/plans/2026-09-27-product-k-design.md +113 -0
  101. semdex-1.5.6/docs/plans/2026-09-27-product-k-plan.md +1482 -0
  102. semdex-1.5.6/docs/plans/2026-09-28-fastmcp4-audit-fixes-plan.md +153 -0
  103. semdex-1.5.6/docs/plans/2026-10-02-industry-overlap-arm-plan.md +279 -0
  104. semdex-1.5.6/docs/semdex-shortlist.md +76 -0
  105. semdex-1.5.6/docs/systemdesign/mcp-multi-dataset-design.md +172 -0
  106. semdex-1.5.6/docs/systemdesign/module_reference.md +498 -0
  107. semdex-1.5.6/notebooks/Quickstart.ipynb +136 -0
  108. semdex-1.5.6/pyproject.toml +513 -0
  109. semdex-1.5.6/scripts/_bench_breakpoint_embeddings.py +166 -0
  110. semdex-1.5.6/scripts/_bench_energy.py +187 -0
  111. semdex-1.5.6/scripts/_bench_memory.py +176 -0
  112. semdex-1.5.6/scripts/_bench_timing.py +140 -0
  113. semdex-1.5.6/scripts/_fusion.py +58 -0
  114. semdex-1.5.6/scripts/_metric_agreement.py +132 -0
  115. semdex-1.5.6/scripts/_optional_ml.py +68 -0
  116. semdex-1.5.6/scripts/_perquery.py +86 -0
  117. semdex-1.5.6/scripts/_provenance.py +110 -0
  118. semdex-1.5.6/scripts/_query_power.py +91 -0
  119. semdex-1.5.6/scripts/_score_kernel.py +132 -0
  120. semdex-1.5.6/scripts/_score_stats.py +158 -0
  121. semdex-1.5.6/scripts/audit_chunk_dimensions.py +575 -0
  122. semdex-1.5.6/scripts/audit_embedder_truncation.py +409 -0
  123. semdex-1.5.6/scripts/bench_chunker_throughput.py +194 -0
  124. semdex-1.5.6/scripts/bench_dim_crossover.py +378 -0
  125. semdex-1.5.6/scripts/bench_embed_stack_ab.py +207 -0
  126. semdex-1.5.6/scripts/bench_embed_throughput.py +141 -0
  127. semdex-1.5.6/scripts/bench_energy.py +232 -0
  128. semdex-1.5.6/scripts/bench_energy_gpu.py +255 -0
  129. semdex-1.5.6/scripts/bench_german_miracl.py +213 -0
  130. semdex-1.5.6/scripts/bench_memory.py +270 -0
  131. semdex-1.5.6/scripts/bench_msmarco_scale.py +525 -0
  132. semdex-1.5.6/scripts/benchmark_compare.py +279 -0
  133. semdex-1.5.6/scripts/bp_sweep_healthcheck.py +277 -0
  134. semdex-1.5.6/scripts/bp_sweep_watchdog.py +98 -0
  135. semdex-1.5.6/scripts/build_gerdalir_slice.py +206 -0
  136. semdex-1.5.6/scripts/build_miracl_slices.py +170 -0
  137. semdex-1.5.6/scripts/build_mldr_markdown_slice.py +171 -0
  138. semdex-1.5.6/scripts/build_mldr_slices.py +211 -0
  139. semdex-1.5.6/scripts/check_bench_claims.py +698 -0
  140. semdex-1.5.6/scripts/export_bench_raw.py +794 -0
  141. semdex-1.5.6/scripts/gen_bench_charts.py +1320 -0
  142. semdex-1.5.6/scripts/gen_bench_explorer.py +403 -0
  143. semdex-1.5.6/scripts/gen_bench_tables.py +2266 -0
  144. semdex-1.5.6/scripts/preembed_vectors.py +756 -0
  145. semdex-1.5.6/scripts/repair_oversized_chunks.py +329 -0
  146. semdex-1.5.6/scripts/restart-hooks/ollama-docker.sh +25 -0
  147. semdex-1.5.6/scripts/restart-hooks/ollama-systemd.sh +34 -0
  148. semdex-1.5.6/scripts/score_ann_frontier.py +377 -0
  149. semdex-1.5.6/scripts/score_chunk_sweep.py +460 -0
  150. semdex-1.5.6/scripts/score_extraction_omnidocbench.py +445 -0
  151. semdex-1.5.6/scripts/score_hybrid_sweep.py +301 -0
  152. semdex-1.5.6/scripts/score_markdown_structure_effect.py +244 -0
  153. semdex-1.5.6/scripts/score_metric_redundancy.py +182 -0
  154. semdex-1.5.6/scripts/score_product_k.py +299 -0
  155. semdex-1.5.6/scripts/score_query_length_effect.py +320 -0
  156. semdex-1.5.6/scripts/score_query_power.py +87 -0
  157. semdex-1.5.6/scripts/score_qwen3_instruction.py +244 -0
  158. semdex-1.5.6/scripts/score_rerank_sweep.py +287 -0
  159. semdex-1.5.6/scripts/score_span_integrity.py +655 -0
  160. semdex-1.5.6/scripts/score_through_store.py +340 -0
  161. semdex-1.5.6/scripts/sweep_breakpoint_models.py +186 -0
  162. semdex-1.5.6/scripts/sweep_chunk_profiles.py +86 -0
  163. semdex-1.5.6/scripts/validate_query_power.py +186 -0
  164. semdex-1.5.6/src/semdex/__init__.py +20 -0
  165. semdex-1.5.6/src/semdex/__init__conf__.py +90 -0
  166. semdex-1.5.6/src/semdex/__main__.py +14 -0
  167. semdex-1.5.6/src/semdex/adapters/__init__.py +15 -0
  168. semdex-1.5.6/src/semdex/adapters/_http_retry.py +97 -0
  169. semdex-1.5.6/src/semdex/adapters/chunker/__init__.py +20 -0
  170. semdex-1.5.6/src/semdex/adapters/chunker/_base.py +117 -0
  171. semdex-1.5.6/src/semdex/adapters/chunker/chonkie.py +209 -0
  172. semdex-1.5.6/src/semdex/adapters/chunker/semantic_text_splitter.py +67 -0
  173. semdex-1.5.6/src/semdex/adapters/chunker/whitespace.py +37 -0
  174. semdex-1.5.6/src/semdex/adapters/cli/__init__.py +64 -0
  175. semdex-1.5.6/src/semdex/adapters/cli/commands/__init__.py +34 -0
  176. semdex-1.5.6/src/semdex/adapters/cli/commands/config.py +511 -0
  177. semdex-1.5.6/src/semdex/adapters/cli/commands/email/__init__.py +17 -0
  178. semdex-1.5.6/src/semdex/adapters/cli/commands/email/_common.py +374 -0
  179. semdex-1.5.6/src/semdex/adapters/cli/commands/email/send_email.py +148 -0
  180. semdex-1.5.6/src/semdex/adapters/cli/commands/email/send_notification.py +100 -0
  181. semdex-1.5.6/src/semdex/adapters/cli/commands/index_search.py +260 -0
  182. semdex-1.5.6/src/semdex/adapters/cli/commands/info.py +60 -0
  183. semdex-1.5.6/src/semdex/adapters/cli/commands/logging.py +34 -0
  184. semdex-1.5.6/src/semdex/adapters/cli/commands/serve.py +253 -0
  185. semdex-1.5.6/src/semdex/adapters/cli/config_load.py +205 -0
  186. semdex-1.5.6/src/semdex/adapters/cli/constants.py +28 -0
  187. semdex-1.5.6/src/semdex/adapters/cli/context.py +192 -0
  188. semdex-1.5.6/src/semdex/adapters/cli/exit_codes.py +57 -0
  189. semdex-1.5.6/src/semdex/adapters/cli/main.py +123 -0
  190. semdex-1.5.6/src/semdex/adapters/cli/py.typed +0 -0
  191. semdex-1.5.6/src/semdex/adapters/cli/root.py +162 -0
  192. semdex-1.5.6/src/semdex/adapters/cli/safe_console.py +297 -0
  193. semdex-1.5.6/src/semdex/adapters/cli/typed_click.py +76 -0
  194. semdex-1.5.6/src/semdex/adapters/config/__init__.py +25 -0
  195. semdex-1.5.6/src/semdex/adapters/config/_section.py +21 -0
  196. semdex-1.5.6/src/semdex/adapters/config/chunker.py +77 -0
  197. semdex-1.5.6/src/semdex/adapters/config/dataset.py +189 -0
  198. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/10-index.toml +126 -0
  199. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/15-vectorstore.toml +163 -0
  200. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/16-datasets.toml +193 -0
  201. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/17-mcp.toml +210 -0
  202. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/20-extractor.toml +97 -0
  203. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/25-chunker.toml +130 -0
  204. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/28-sanitize.toml +59 -0
  205. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/30-embedding.toml +227 -0
  206. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/31-summary.toml +131 -0
  207. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/32-health.toml +105 -0
  208. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/35-watch.toml +54 -0
  209. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/40-layered-config.toml +78 -0
  210. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/50-mail.toml +244 -0
  211. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.d/90-logging.toml +445 -0
  212. semdex-1.5.6/src/semdex/adapters/config/defaultconfig.toml +56 -0
  213. semdex-1.5.6/src/semdex/adapters/config/deploy.py +135 -0
  214. semdex-1.5.6/src/semdex/adapters/config/display.py +60 -0
  215. semdex-1.5.6/src/semdex/adapters/config/embedding.py +95 -0
  216. semdex-1.5.6/src/semdex/adapters/config/extractor.py +72 -0
  217. semdex-1.5.6/src/semdex/adapters/config/health.py +104 -0
  218. semdex-1.5.6/src/semdex/adapters/config/index.py +72 -0
  219. semdex-1.5.6/src/semdex/adapters/config/loader.py +198 -0
  220. semdex-1.5.6/src/semdex/adapters/config/mcp.py +69 -0
  221. semdex-1.5.6/src/semdex/adapters/config/overrides.py +302 -0
  222. semdex-1.5.6/src/semdex/adapters/config/py.typed +0 -0
  223. semdex-1.5.6/src/semdex/adapters/config/sanitize.py +65 -0
  224. semdex-1.5.6/src/semdex/adapters/config/summary.py +87 -0
  225. semdex-1.5.6/src/semdex/adapters/config/vectorstore.py +119 -0
  226. semdex-1.5.6/src/semdex/adapters/config/watch.py +54 -0
  227. semdex-1.5.6/src/semdex/adapters/discovery/__init__.py +15 -0
  228. semdex-1.5.6/src/semdex/adapters/discovery/filesystem.py +108 -0
  229. semdex-1.5.6/src/semdex/adapters/discovery/location.py +62 -0
  230. semdex-1.5.6/src/semdex/adapters/email/__init__.py +28 -0
  231. semdex-1.5.6/src/semdex/adapters/email/config.py +381 -0
  232. semdex-1.5.6/src/semdex/adapters/email/py.typed +0 -0
  233. semdex-1.5.6/src/semdex/adapters/email/sender.py +26 -0
  234. semdex-1.5.6/src/semdex/adapters/email/transport.py +233 -0
  235. semdex-1.5.6/src/semdex/adapters/email/validation.py +65 -0
  236. semdex-1.5.6/src/semdex/adapters/embedding/__init__.py +38 -0
  237. semdex-1.5.6/src/semdex/adapters/embedding/_base.py +150 -0
  238. semdex-1.5.6/src/semdex/adapters/embedding/cohere.py +127 -0
  239. semdex-1.5.6/src/semdex/adapters/embedding/fastembed.py +87 -0
  240. semdex-1.5.6/src/semdex/adapters/embedding/gemini.py +153 -0
  241. semdex-1.5.6/src/semdex/adapters/embedding/model2vec.py +51 -0
  242. semdex-1.5.6/src/semdex/adapters/embedding/ollama.py +130 -0
  243. semdex-1.5.6/src/semdex/adapters/embedding/openai.py +118 -0
  244. semdex-1.5.6/src/semdex/adapters/embedding/sentence_transformers.py +117 -0
  245. semdex-1.5.6/src/semdex/adapters/extractor/__init__.py +37 -0
  246. semdex-1.5.6/src/semdex/adapters/extractor/_http.py +129 -0
  247. semdex-1.5.6/src/semdex/adapters/extractor/docling.py +85 -0
  248. semdex-1.5.6/src/semdex/adapters/extractor/markitdown.py +135 -0
  249. semdex-1.5.6/src/semdex/adapters/extractor/mineru.py +95 -0
  250. semdex-1.5.6/src/semdex/adapters/extractor/router.py +192 -0
  251. semdex-1.5.6/src/semdex/adapters/extractor/text.py +58 -0
  252. semdex-1.5.6/src/semdex/adapters/extractor/vision_ocr.py +186 -0
  253. semdex-1.5.6/src/semdex/adapters/extractor/xberg.py +109 -0
  254. semdex-1.5.6/src/semdex/adapters/health/__init__.py +61 -0
  255. semdex-1.5.6/src/semdex/adapters/health/_loop.py +111 -0
  256. semdex-1.5.6/src/semdex/adapters/health/_probe.py +63 -0
  257. semdex-1.5.6/src/semdex/adapters/health/_restart.py +105 -0
  258. semdex-1.5.6/src/semdex/adapters/health/_warmup.py +55 -0
  259. semdex-1.5.6/src/semdex/adapters/logging/__init__.py +13 -0
  260. semdex-1.5.6/src/semdex/adapters/logging/py.typed +0 -0
  261. semdex-1.5.6/src/semdex/adapters/logging/setup.py +345 -0
  262. semdex-1.5.6/src/semdex/adapters/mcp/__init__.py +1 -0
  263. semdex-1.5.6/src/semdex/adapters/mcp/auth.py +128 -0
  264. semdex-1.5.6/src/semdex/adapters/mcp/schemas.py +146 -0
  265. semdex-1.5.6/src/semdex/adapters/mcp/server.py +275 -0
  266. semdex-1.5.6/src/semdex/adapters/memory/__init__.py +60 -0
  267. semdex-1.5.6/src/semdex/adapters/memory/config.py +66 -0
  268. semdex-1.5.6/src/semdex/adapters/memory/email.py +173 -0
  269. semdex-1.5.6/src/semdex/adapters/memory/index.py +230 -0
  270. semdex-1.5.6/src/semdex/adapters/memory/logging.py +80 -0
  271. semdex-1.5.6/src/semdex/adapters/py.typed +0 -0
  272. semdex-1.5.6/src/semdex/adapters/sanitize/__init__.py +14 -0
  273. semdex-1.5.6/src/semdex/adapters/sanitize/detectors.py +71 -0
  274. semdex-1.5.6/src/semdex/adapters/sanitize/extractor.py +79 -0
  275. semdex-1.5.6/src/semdex/adapters/summarizer/__init__.py +22 -0
  276. semdex-1.5.6/src/semdex/adapters/summarizer/_base.py +116 -0
  277. semdex-1.5.6/src/semdex/adapters/summarizer/ollama.py +122 -0
  278. semdex-1.5.6/src/semdex/adapters/summarizer/openai.py +128 -0
  279. semdex-1.5.6/src/semdex/adapters/vectorstore/__init__.py +22 -0
  280. semdex-1.5.6/src/semdex/adapters/vectorstore/jsonstore.py +141 -0
  281. semdex-1.5.6/src/semdex/adapters/vectorstore/lance.py +273 -0
  282. semdex-1.5.6/src/semdex/adapters/vectorstore/mariadb.py +234 -0
  283. semdex-1.5.6/src/semdex/adapters/vectorstore/pgvector.py +227 -0
  284. semdex-1.5.6/src/semdex/adapters/vectorstore/sqlitevec.py +219 -0
  285. semdex-1.5.6/src/semdex/adapters/watch/__init__.py +13 -0
  286. semdex-1.5.6/src/semdex/adapters/watch/watchfiles_watcher.py +115 -0
  287. semdex-1.5.6/src/semdex/application/__init__.py +51 -0
  288. semdex-1.5.6/src/semdex/application/batching.py +51 -0
  289. semdex-1.5.6/src/semdex/application/ports.py +331 -0
  290. semdex-1.5.6/src/semdex/application/py.typed +0 -0
  291. semdex-1.5.6/src/semdex/application/resilience.py +160 -0
  292. semdex-1.5.6/src/semdex/application/use_cases/__init__.py +31 -0
  293. semdex-1.5.6/src/semdex/application/use_cases/indexing.py +101 -0
  294. semdex-1.5.6/src/semdex/application/use_cases/reconciling.py +77 -0
  295. semdex-1.5.6/src/semdex/application/use_cases/searching.py +121 -0
  296. semdex-1.5.6/src/semdex/application/use_cases/writing.py +67 -0
  297. semdex-1.5.6/src/semdex/composition/__init__.py +1148 -0
  298. semdex-1.5.6/src/semdex/composition/py.typed +0 -0
  299. semdex-1.5.6/src/semdex/domain/__init__.py +50 -0
  300. semdex-1.5.6/src/semdex/domain/ann_tuning.py +102 -0
  301. semdex-1.5.6/src/semdex/domain/enums.py +280 -0
  302. semdex-1.5.6/src/semdex/domain/errors.py +143 -0
  303. semdex-1.5.6/src/semdex/domain/models.py +180 -0
  304. semdex-1.5.6/src/semdex/domain/py.typed +0 -0
  305. semdex-1.5.6/src/semdex/entry.py +35 -0
  306. semdex-1.5.6/src/semdex/py.typed +0 -0
  307. semdex-1.5.6/tests/_bench_corpus.py +91 -0
  308. semdex-1.5.6/tests/_benchmark_report.py +176 -0
  309. semdex-1.5.6/tests/benchmarks/baseline.json +3591 -0
  310. semdex-1.5.6/tests/benchmarks/claims/01-method.toml +377 -0
  311. semdex-1.5.6/tests/benchmarks/claims/02-extraction.toml +318 -0
  312. semdex-1.5.6/tests/benchmarks/claims/03-chunking.toml +4191 -0
  313. semdex-1.5.6/tests/benchmarks/claims/04-embedding.toml +256 -0
  314. semdex-1.5.6/tests/benchmarks/claims/05-vector-store.toml +772 -0
  315. semdex-1.5.6/tests/benchmarks/claims/06-retrieval-method.toml +187 -0
  316. semdex-1.5.6/tests/benchmarks/claims/07-selection.toml +582 -0
  317. semdex-1.5.6/tests/benchmarks/claims/08-gaps.toml +1427 -0
  318. semdex-1.5.6/tests/benchmarks/claims/README.md +107 -0
  319. semdex-1.5.6/tests/benchmarks/raw/README.md +85 -0
  320. semdex-1.5.6/tests/benchmarks/raw/ann-1m.json +50 -0
  321. semdex-1.5.6/tests/benchmarks/raw/ann-frontier.json +795 -0
  322. semdex-1.5.6/tests/benchmarks/raw/ann-scale-50k-250k.json +92 -0
  323. semdex-1.5.6/tests/benchmarks/raw/chunk-dimension-audit.json +9500 -0
  324. semdex-1.5.6/tests/benchmarks/raw/chunk-knob-effects.json +85335 -0
  325. semdex-1.5.6/tests/benchmarks/raw/chunk-sweep-beir.json +3720 -0
  326. semdex-1.5.6/tests/benchmarks/raw/chunk-sweep-gerdalir.json +6169 -0
  327. semdex-1.5.6/tests/benchmarks/raw/chunk-sweep-miracl.json +2070 -0
  328. semdex-1.5.6/tests/benchmarks/raw/chunk-sweep-mldr.json +13985 -0
  329. semdex-1.5.6/tests/benchmarks/raw/chunker-throughput.json +487 -0
  330. semdex-1.5.6/tests/benchmarks/raw/cloud-prices.json +48 -0
  331. semdex-1.5.6/tests/benchmarks/raw/dim-crossover-real.json +689 -0
  332. semdex-1.5.6/tests/benchmarks/raw/dim-crossover.json +309 -0
  333. semdex-1.5.6/tests/benchmarks/raw/embedder-truncation-audit.json +9349 -0
  334. semdex-1.5.6/tests/benchmarks/raw/embedding-german-miracl.json +108 -0
  335. semdex-1.5.6/tests/benchmarks/raw/embedding-multilingual-mldr.json +2770 -0
  336. semdex-1.5.6/tests/benchmarks/raw/embedding-qwen3-gpu.json +30 -0
  337. semdex-1.5.6/tests/benchmarks/raw/energy-gpu.json +67 -0
  338. semdex-1.5.6/tests/benchmarks/raw/energy.json +90 -0
  339. semdex-1.5.6/tests/benchmarks/raw/extraction-omnidocbench.json +704 -0
  340. semdex-1.5.6/tests/benchmarks/raw/hybrid-dense-bm25.json +1094 -0
  341. semdex-1.5.6/tests/benchmarks/raw/markdown-structure-effect.json +1730 -0
  342. semdex-1.5.6/tests/benchmarks/raw/memory.json +235 -0
  343. semdex-1.5.6/tests/benchmarks/raw/metric-redundancy.json +493 -0
  344. semdex-1.5.6/tests/benchmarks/raw/msmarco-scale.json +183 -0
  345. semdex-1.5.6/tests/benchmarks/raw/ocr-badscans.json +14 -0
  346. semdex-1.5.6/tests/benchmarks/raw/query-length-effect.json +4421 -0
  347. semdex-1.5.6/tests/benchmarks/raw/query-power-validation.json +100 -0
  348. semdex-1.5.6/tests/benchmarks/raw/query-power.json +129 -0
  349. semdex-1.5.6/tests/benchmarks/raw/qwen3-instruction-8b.json +4961 -0
  350. semdex-1.5.6/tests/benchmarks/raw/qwen3-instruction.json +4961 -0
  351. semdex-1.5.6/tests/benchmarks/raw/rerank-cross-encoder.json +923 -0
  352. semdex-1.5.6/tests/benchmarks/raw/span-integrity.json +15074 -0
  353. semdex-1.5.6/tests/benchmarks/raw/store-quality.json +390 -0
  354. semdex-1.5.6/tests/conftest.py +823 -0
  355. semdex-1.5.6/tests/fixtures/extract/README.md +40 -0
  356. semdex-1.5.6/tests/fixtures/extract/_generate.py +178 -0
  357. semdex-1.5.6/tests/fixtures/extract/expected.toml +23 -0
  358. semdex-1.5.6/tests/fixtures/extract/sample.docx +0 -0
  359. semdex-1.5.6/tests/fixtures/extract/sample.html +7 -0
  360. semdex-1.5.6/tests/fixtures/extract/sample.md +11 -0
  361. semdex-1.5.6/tests/fixtures/extract/sample.pdf +74 -0
  362. semdex-1.5.6/tests/fixtures/extract/sample.pptx +0 -0
  363. semdex-1.5.6/tests/fixtures/extract/sample.txt +3 -0
  364. semdex-1.5.6/tests/fixtures/extract/sample.xlsx +0 -0
  365. semdex-1.5.6/tests/fixtures/extract/scan.png +0 -0
  366. semdex-1.5.6/tests/test_ann_frontier.py +229 -0
  367. semdex-1.5.6/tests/test_ann_tuning.py +81 -0
  368. semdex-1.5.6/tests/test_batching_embedding.py +60 -0
  369. semdex-1.5.6/tests/test_bench_breakpoint_timeout.py +121 -0
  370. semdex-1.5.6/tests/test_bench_charts_current.py +232 -0
  371. semdex-1.5.6/tests/test_bench_chunk_dimensions_integrity.py +150 -0
  372. semdex-1.5.6/tests/test_bench_chunker_throughput.py +139 -0
  373. semdex-1.5.6/tests/test_bench_claims_current.py +447 -0
  374. semdex-1.5.6/tests/test_bench_corpus.py +62 -0
  375. semdex-1.5.6/tests/test_bench_embed_stack_ab.py +115 -0
  376. semdex-1.5.6/tests/test_bench_embedder_truncation.py +468 -0
  377. semdex-1.5.6/tests/test_bench_energy.py +238 -0
  378. semdex-1.5.6/tests/test_bench_export_axes.py +171 -0
  379. semdex-1.5.6/tests/test_bench_export_corpus_guard.py +199 -0
  380. semdex-1.5.6/tests/test_bench_export_material.py +134 -0
  381. semdex-1.5.6/tests/test_bench_export_product_k.py +129 -0
  382. semdex-1.5.6/tests/test_bench_export_provenance.py +239 -0
  383. semdex-1.5.6/tests/test_bench_export_unscored_guard.py +147 -0
  384. semdex-1.5.6/tests/test_bench_export_void.py +151 -0
  385. semdex-1.5.6/tests/test_bench_markdown_structure_effect.py +216 -0
  386. semdex-1.5.6/tests/test_bench_measurement_provenance.py +85 -0
  387. semdex-1.5.6/tests/test_bench_memory.py +263 -0
  388. semdex-1.5.6/tests/test_bench_query_length_effect.py +183 -0
  389. semdex-1.5.6/tests/test_bench_scale_knobs.py +80 -0
  390. semdex-1.5.6/tests/test_bench_score_out_guard.py +85 -0
  391. semdex-1.5.6/tests/test_bench_score_query_variant.py +72 -0
  392. semdex-1.5.6/tests/test_bench_scorers_stamp_provenance.py +131 -0
  393. semdex-1.5.6/tests/test_bench_source_sha.py +69 -0
  394. semdex-1.5.6/tests/test_bench_tables_current.py +448 -0
  395. semdex-1.5.6/tests/test_bench_tables_effect_floors.py +195 -0
  396. semdex-1.5.6/tests/test_bench_tables_markdown_structure.py +109 -0
  397. semdex-1.5.6/tests/test_bench_tables_overlap_percent.py +81 -0
  398. semdex-1.5.6/tests/test_bench_tables_product_k.py +219 -0
  399. semdex-1.5.6/tests/test_bench_tables_query_length.py +121 -0
  400. semdex-1.5.6/tests/test_bench_timing.py +201 -0
  401. semdex-1.5.6/tests/test_benchmark_regression.py +467 -0
  402. semdex-1.5.6/tests/test_build_mldr_markdown_slice.py +144 -0
  403. semdex-1.5.6/tests/test_cache_effectiveness.py +155 -0
  404. semdex-1.5.6/tests/test_chunk_size_guard.py +220 -0
  405. semdex-1.5.6/tests/test_chunker.py +165 -0
  406. semdex-1.5.6/tests/test_chunker_factory.py +58 -0
  407. semdex-1.5.6/tests/test_chunker_local.py +61 -0
  408. semdex-1.5.6/tests/test_cli_attachment_refused.py +191 -0
  409. semdex-1.5.6/tests/test_cli_config.py +836 -0
  410. semdex-1.5.6/tests/test_cli_config_errors.py +501 -0
  411. semdex-1.5.6/tests/test_cli_core.py +213 -0
  412. semdex-1.5.6/tests/test_cli_email.py +827 -0
  413. semdex-1.5.6/tests/test_cli_email_config_errors.py +136 -0
  414. semdex-1.5.6/tests/test_cli_embedding_knobs_reach_factory.py +79 -0
  415. semdex-1.5.6/tests/test_cli_env_file.py +181 -0
  416. semdex-1.5.6/tests/test_cli_exit_codes.py +161 -0
  417. semdex-1.5.6/tests/test_cli_index_search.py +110 -0
  418. semdex-1.5.6/tests/test_cli_main_exit.py +182 -0
  419. semdex-1.5.6/tests/test_cli_overrides.py +167 -0
  420. semdex-1.5.6/tests/test_cli_serve.py +124 -0
  421. semdex-1.5.6/tests/test_cli_validation.py +132 -0
  422. semdex-1.5.6/tests/test_config_ann.py +78 -0
  423. semdex-1.5.6/tests/test_config_chunker.py +69 -0
  424. semdex-1.5.6/tests/test_config_dataset.py +102 -0
  425. semdex-1.5.6/tests/test_config_embedding.py +79 -0
  426. semdex-1.5.6/tests/test_config_extractor.py +59 -0
  427. semdex-1.5.6/tests/test_config_health.py +63 -0
  428. semdex-1.5.6/tests/test_config_index.py +106 -0
  429. semdex-1.5.6/tests/test_config_mcp.py +65 -0
  430. semdex-1.5.6/tests/test_config_overrides.py +389 -0
  431. semdex-1.5.6/tests/test_config_summary.py +100 -0
  432. semdex-1.5.6/tests/test_config_vectorstore.py +79 -0
  433. semdex-1.5.6/tests/test_dataset_services.py +31 -0
  434. semdex-1.5.6/tests/test_declared_dependencies.py +158 -0
  435. semdex-1.5.6/tests/test_deploy_mode_safety.py +191 -0
  436. semdex-1.5.6/tests/test_deploy_permissions.py +380 -0
  437. semdex-1.5.6/tests/test_discovery.py +104 -0
  438. semdex-1.5.6/tests/test_display.py +124 -0
  439. semdex-1.5.6/tests/test_domain_models.py +200 -0
  440. semdex-1.5.6/tests/test_e2e_extractor_matrix.py +503 -0
  441. semdex-1.5.6/tests/test_e2e_matrix.py +564 -0
  442. semdex-1.5.6/tests/test_e2e_mcp_knowledge_matrix.py +1137 -0
  443. semdex-1.5.6/tests/test_e2e_watch.py +100 -0
  444. semdex-1.5.6/tests/test_email_attachment_lists.py +226 -0
  445. semdex-1.5.6/tests/test_email_config_translation.py +326 -0
  446. semdex-1.5.6/tests/test_email_password_secrecy.py +293 -0
  447. semdex-1.5.6/tests/test_email_shipped_defaults.py +123 -0
  448. semdex-1.5.6/tests/test_embedding_base.py +36 -0
  449. semdex-1.5.6/tests/test_embedding_cohere.py +169 -0
  450. semdex-1.5.6/tests/test_embedding_factory.py +149 -0
  451. semdex-1.5.6/tests/test_embedding_fastembed_cache.py +36 -0
  452. semdex-1.5.6/tests/test_embedding_gemini.py +168 -0
  453. semdex-1.5.6/tests/test_embedding_instruction_prefix.py +192 -0
  454. semdex-1.5.6/tests/test_embedding_local.py +46 -0
  455. semdex-1.5.6/tests/test_embedding_ollama.py +171 -0
  456. semdex-1.5.6/tests/test_embedding_openai.py +156 -0
  457. semdex-1.5.6/tests/test_embedding_sentence_transformers.py +109 -0
  458. semdex-1.5.6/tests/test_enums.py +78 -0
  459. semdex-1.5.6/tests/test_errors.py +39 -0
  460. semdex-1.5.6/tests/test_extract_fixtures_match_expectations.py +71 -0
  461. semdex-1.5.6/tests/test_extraction_omnidocbench.py +242 -0
  462. semdex-1.5.6/tests/test_extractor_docker.py +110 -0
  463. semdex-1.5.6/tests/test_extractor_factory.py +94 -0
  464. semdex-1.5.6/tests/test_extractor_http.py +140 -0
  465. semdex-1.5.6/tests/test_extractor_markitdown.py +129 -0
  466. semdex-1.5.6/tests/test_extractor_mineru_docker.py +73 -0
  467. semdex-1.5.6/tests/test_extractor_router.py +262 -0
  468. semdex-1.5.6/tests/test_extractor_text.py +54 -0
  469. semdex-1.5.6/tests/test_extractor_vision_ocr.py +139 -0
  470. semdex-1.5.6/tests/test_fusion.py +149 -0
  471. semdex-1.5.6/tests/test_health_composition.py +110 -0
  472. semdex-1.5.6/tests/test_health_loop.py +84 -0
  473. semdex-1.5.6/tests/test_health_probe.py +65 -0
  474. semdex-1.5.6/tests/test_health_restart.py +92 -0
  475. semdex-1.5.6/tests/test_health_warmup.py +93 -0
  476. semdex-1.5.6/tests/test_http_retry.py +398 -0
  477. semdex-1.5.6/tests/test_index_composition.py +68 -0
  478. semdex-1.5.6/tests/test_index_ports.py +296 -0
  479. semdex-1.5.6/tests/test_location.py +95 -0
  480. semdex-1.5.6/tests/test_logging.py +31 -0
  481. semdex-1.5.6/tests/test_logging_dotenv_isolation.py +461 -0
  482. semdex-1.5.6/tests/test_mail.py +1570 -0
  483. semdex-1.5.6/tests/test_mcp_auth.py +111 -0
  484. semdex-1.5.6/tests/test_mcp_server.py +270 -0
  485. semdex-1.5.6/tests/test_memory_index_adapters.py +200 -0
  486. semdex-1.5.6/tests/test_memory_logging.py +121 -0
  487. semdex-1.5.6/tests/test_metadata.py +84 -0
  488. semdex-1.5.6/tests/test_metadata_sync.py +80 -0
  489. semdex-1.5.6/tests/test_metric_agreement.py +185 -0
  490. semdex-1.5.6/tests/test_module_entry.py +218 -0
  491. semdex-1.5.6/tests/test_module_reference_sync.py +51 -0
  492. semdex-1.5.6/tests/test_os_paths.py +60 -0
  493. semdex-1.5.6/tests/test_perf_plugins.py +166 -0
  494. semdex-1.5.6/tests/test_perf_tunables.py +125 -0
  495. semdex-1.5.6/tests/test_permission_defaults.py +592 -0
  496. semdex-1.5.6/tests/test_perquery_writer.py +110 -0
  497. semdex-1.5.6/tests/test_ports.py +202 -0
  498. semdex-1.5.6/tests/test_preembed_num_batch.py +49 -0
  499. semdex-1.5.6/tests/test_property_email.py +282 -0
  500. semdex-1.5.6/tests/test_property_overrides.py +165 -0
  501. semdex-1.5.6/tests/test_query_power.py +153 -0
  502. semdex-1.5.6/tests/test_reconcile.py +114 -0
  503. semdex-1.5.6/tests/test_repair_plan.py +193 -0
  504. semdex-1.5.6/tests/test_rerank_candidates.py +88 -0
  505. semdex-1.5.6/tests/test_resilience.py +184 -0
  506. semdex-1.5.6/tests/test_safe_console.py +282 -0
  507. semdex-1.5.6/tests/test_sanitize_detectors.py +68 -0
  508. semdex-1.5.6/tests/test_sanitize_extractor.py +72 -0
  509. semdex-1.5.6/tests/test_score_kernel.py +191 -0
  510. semdex-1.5.6/tests/test_score_product_k.py +200 -0
  511. semdex-1.5.6/tests/test_score_stats.py +131 -0
  512. semdex-1.5.6/tests/test_search_across_datasets.py +85 -0
  513. semdex-1.5.6/tests/test_serve_health.py +80 -0
  514. semdex-1.5.6/tests/test_serve_watch.py +137 -0
  515. semdex-1.5.6/tests/test_settings_dotenv_numbers.py +138 -0
  516. semdex-1.5.6/tests/test_span_integrity.py +408 -0
  517. semdex-1.5.6/tests/test_store_quality_harness.py +89 -0
  518. semdex-1.5.6/tests/test_summarizer_factory.py +36 -0
  519. semdex-1.5.6/tests/test_summarizer_ollama.py +116 -0
  520. semdex-1.5.6/tests/test_summarizer_openai.py +144 -0
  521. semdex-1.5.6/tests/test_use_cases.py +168 -0
  522. semdex-1.5.6/tests/test_vectorstore_ann_build_params.py +174 -0
  523. semdex-1.5.6/tests/test_vectorstore_factory.py +50 -0
  524. semdex-1.5.6/tests/test_vectorstore_json.py +123 -0
  525. semdex-1.5.6/tests/test_vectorstore_lance.py +238 -0
  526. semdex-1.5.6/tests/test_vectorstore_mariadb.py +139 -0
  527. semdex-1.5.6/tests/test_vectorstore_pgvector.py +96 -0
  528. semdex-1.5.6/tests/test_vectorstore_sqlite.py +164 -0
  529. semdex-1.5.6/tests/test_watcher.py +144 -0
  530. semdex-1.5.6/tests/test_writing.py +70 -0
  531. semdex-1.5.6/uv.lock +7097 -0
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: bench-rerun
3
+ description: Use when semdex components were updated (extractor/store container images, fastembed or other embedding models, chunker libraries, ollama models) or on a periodic re-test, and the benchmarks must be re-run, compared against the committed baseline, and the bench_*.md rankings refreshed.
4
+ ---
5
+
6
+ # Re-run the semdex benchmarks after component updates
7
+
8
+ Everything runs against the **fixed slice** the baseline was seeded with - a different slice
9
+ makes the comparison apples-to-oranges. One-off scale references (the MSMARCO tables in
10
+ `bench_database.md`) are NOT part of this loop; re-measure those deliberately.
11
+
12
+ ## 1. Update what actually changed
13
+
14
+ ```bash
15
+ # Containers: docker run reuses the cached tag - a stale image silently tests nothing new.
16
+ docker pull <image> # then record: docker inspect --format '{{index .RepoDigests 0}}' <image>
17
+ # Python deps: upgrade IN THE BENCHMARK VENV (the one with all extras, see
18
+ # COMPONENT_SETUP.md "Benchmark prerequisites"), not some other venv.
19
+ uv pip install -U <package>
20
+ # ollama models: ollama pull <model> on your server (endpoint via SEMDEX_BENCH_OLLAMA_URL
21
+ # from .env - never hardcode a host anywhere in the repo).
22
+ ```
23
+
24
+ ## 2. Re-run at the fixed slice - ONE pytest session
25
+
26
+ Result cells accumulate into one `benchmark-results.json` per pytest **process**; a second
27
+ invocation overwrites it. Run all needed files in a single session:
28
+
29
+ ```bash
30
+ SEMDEX_BENCH_CORPORA=nfcorpus SEMDEX_BENCH_MAX_DOCS=150 SEMDEX_BENCH_MAX_QUERIES=20 \
31
+ pytest -p no:cacheprovider -o addopts="" -s \
32
+ tests/test_e2e_matrix.py tests/test_e2e_extractor_matrix.py::test_extractor_fixture_matrix
33
+ ```
34
+
35
+ Scope a partial re-check to the changed axis with the env filters
36
+ (`SEMDEX_BENCH_CHUNKERS/_EMBEDDINGS/_STORES/_EXTRACTORS/_EMBED_MODELS`); untouched cells show
37
+ as non-gating "not_run". Cells whose container/server is down record `skip` - the comparator
38
+ flags `ok -> skip`, so fix the service rather than accepting it.
39
+
40
+ ## 3. Compare - and root-cause before touching the baseline
41
+
42
+ ```bash
43
+ python scripts/benchmark_compare.py benchmark-results.json
44
+ ```
45
+
46
+ On a regression, **never `--update` to make red green.** Attribute it first: status flip ->
47
+ diff the recorded image digest vs the baseline's; quality drop -> what changed in the model
48
+ (re-run once to confirm - fastembed is deterministic); adapter error -> upstream API change,
49
+ fix the adapter + its tests. A semdex-side fix ends with the slice green; an upstream
50
+ regression ends with a pin + upstream issue; a genuine accepted change moves on to step 4.
51
+
52
+ ## 4. Adopt and re-rank
53
+
54
+ ```bash
55
+ python scripts/benchmark_compare.py benchmark-results.json --update
56
+ ```
57
+
58
+ Then regenerate every published number in that same commit, never by hand. Run
59
+ `python scripts/export_bench_raw.py`, then `python scripts/gen_bench_tables.py` and
60
+ `python scripts/gen_bench_charts.py`: every published table and chart under `docs/benchmarks/`
61
+ is generated from `tests/benchmarks/raw/`, and
62
+ `pytest tests/test_bench_tables_current.py tests/test_bench_charts_current.py` fails if a
63
+ published number no longer matches its data.
64
+
65
+ What a human still writes, in the same commit: the PROSE around a table, if a verdict changed;
66
+ the new component versions/digests, named in the commit message; a `CHANGELOG.md` entry; a
67
+ `pyproject.toml` constraint if a floor or pin changed. The quality-table numbers come from the
68
+ 4-corpus run (`SEMDEX_BENCH_CORPORA=nfcorpus,cqadupstack,scifact,fiqa`) - re-run that before
69
+ re-ranking chunker/embedding tables.
70
+
71
+ ## 5. Gate before pushing
72
+
73
+ ```bash
74
+ grep -rnE "192\.168\.|[0-9]{1,3}(\.[0-9]{1,3}){3}|\.local\." docs/ tests/benchmarks/ .claude/skills/ || echo leak-clean
75
+ make test
76
+ ```
77
+
78
+ Done when: every flagged cell has a written root cause, `make test` is green, the baseline
79
+ refresh and the docs regenerated from it are one reviewable commit of their own (no semdex code
80
+ fix from step 3 in it) naming the component versions/digests that justify it, and the doc tables
81
+ cite the new numbers.
@@ -0,0 +1,22 @@
1
+ {
2
+ "image": "mcr.microsoft.com/devcontainers/python:3.13",
3
+
4
+ "postCreateCommand": "bash -lc '\nPY=/usr/local/bin/python;\n$PY -m pip install -U pip && \\\n$PY -m pip install ipykernel && \\\n$PY -m pip install -e . && \\\n# register kernel using this exact interpreter\n$PY -m ipykernel install --name=python3 --display-name=\"Python 3 (3.13)\" --user && \\\n# patch the notebook to point to the python3 kernelspec (VS Code will bind to /usr/local/bin/python)\n$PY - <<\"PY\"\nimport json, pathlib\np = pathlib.Path(\"notebooks/Quickstart.ipynb\")\nif p.exists():\n nb = json.loads(p.read_text(encoding=\"utf-8\"))\n md = nb.setdefault(\"metadata\", {})\n md[\"kernelspec\"] = {\n \"name\": \"python3\",\n \"display_name\": \"Python 3 (3.13)\",\n \"language\": \"python\"\n }\n md[\"language_info\"] = {\"name\": \"python\"}\n p.write_text(json.dumps(nb, ensure_ascii=False, indent=1), encoding=\"utf-8\")\n print(\"Pinned kernelspec to python3 in\", p)\nelse:\n print(\"Notebook not found:\", p)\nPY'\n",
5
+
6
+ "customizations": {
7
+ "vscode": {
8
+ "extensions": ["ms-toolsai.jupyter", "ms-python.python"],
9
+ "settings": {
10
+ "workbench.startupEditor": "none",
11
+ "jupyter.alwaysTrustNotebooks": true,
12
+ "jupyter.kernelPickerType": "OnlyRecommended",
13
+ "python.defaultInterpreterPath": "/usr/local/bin/python"
14
+ }
15
+ },
16
+ "codespaces": {
17
+ "openFiles": ["README.md"]
18
+ }
19
+ },
20
+
21
+ "postAttachCommand": "bash -lc 'if [ -f notebooks/Quickstart.ipynb ]; then code -r notebooks/Quickstart.ipynb; fi'"
22
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "python.defaultInterpreterPath": "/usr/local/bin/python3.13",
3
+ "jupyter.alwaysTrustNotebooks": true,
4
+ "jupyter.kernelPickerType": "OnlyRecommended",
5
+ "jupyter.askForKernelRestart": false
6
+ }
@@ -0,0 +1,468 @@
1
+ # Copy to .env and fill values as needed.
2
+
3
+ # Codecov upload token (required for private repos; optional for public repos)
4
+ CODECOV_TOKEN=
5
+
6
+ # PyPI API token for the release workflow (.github/workflows/default_release_public.yml).
7
+ # Leave it empty when PyPI has a Trusted Publisher for this repo: the workflow then
8
+ # publishes via OIDC instead of the token.
9
+ # Format: pypi-AgENdGVzdC5weXBpLm9yZwIk...
10
+ PYPI_API_TOKEN=
11
+
12
+ # Optional: GitHub token for API-limited tasks
13
+ GITHUB_TOKEN=
14
+
15
+
16
+ # ==============================================================================
17
+ # Email Configuration (SMTP)
18
+ # ==============================================================================
19
+ #
20
+ # Naming Convention
21
+ # -----------------
22
+ # Format: <SECTION>__<KEY>=value (double underscore separates section from key)
23
+ # An unquoted value is converted (in .env and in the environment alike): true/false become
24
+ # booleans, null/none become None (except for secret keys such as passwords, which keep the
25
+ # text), a JSON array or object is parsed, and a number becomes a number only when it converts
26
+ # back to the same text (007 and 1.50 stay text). Quote a .env value to keep it as text; the
27
+ # quotes are removed. A list is a JSON array, written UNQUOTED: EMAIL__RECIPIENTS=["a@example.com","b@example.com"].
28
+ # Or give one key per entry: EMAIL__RECIPIENTS__0=a@example.com, EMAIL__RECIPIENTS__1=b@example.com.
29
+ # A comma-separated value is NOT a list: it arrives as ONE string.
30
+ #
31
+ # Full environment variable (outside .env):
32
+ # SEMDEX___EMAIL__<KEY>=value
33
+ # (triple underscore separates the application slug from the section)
34
+ # The environment converts values the same way; an environment variable has no quoting
35
+ # of its own (quotes stay part of the value), so the single quotes below are only for the
36
+ # shell: SEMDEX___EMAIL__RECIPIENTS='["a@example.com","b@example.com"]'
37
+
38
+ # Purpose: SMTP servers for email delivery, tried in order (host:port)
39
+ # Type: list of strings in "host[:port]" format; a single string is one host
40
+ # Default: (empty, must be configured to send email)
41
+ # Environment Variable: SEMDEX___EMAIL__SMTP_HOSTS='["smtp.example.com:587","smtp-backup.example.com:587"]'
42
+ # .env: EMAIL__SMTP_HOSTS=["smtp.example.com:587","smtp-backup.example.com:587"]
43
+ # .env, one key per host: EMAIL__SMTP_HOSTS__0=smtp.example.com:587 and EMAIL__SMTP_HOSTS__1=smtp-backup.example.com:587
44
+ # EMAIL__SMTP_HOSTS=["smtp.example.com:587"]
45
+
46
+ # Purpose: Default sender address for outgoing emails
47
+ # Type: string (valid email address)
48
+ # Default: (empty, must be configured or passed via --from)
49
+ # Environment Variable: SEMDEX___EMAIL__FROM_ADDRESS=noreply@example.com
50
+ # .env: EMAIL__FROM_ADDRESS=noreply@example.com
51
+ # EMAIL__FROM_ADDRESS=noreply@example.com
52
+
53
+ # Purpose: Default recipient addresses
54
+ # Type: list of strings (valid email addresses); a single string is one address
55
+ # Default: (empty, must be configured or passed via --to)
56
+ # Environment Variable: SEMDEX___EMAIL__RECIPIENTS='["admin@example.com","ops@example.com"]'
57
+ # .env: EMAIL__RECIPIENTS=["admin@example.com","ops@example.com"]
58
+ # .env, one key per address: EMAIL__RECIPIENTS__0=admin@example.com and EMAIL__RECIPIENTS__1=ops@example.com
59
+ # EMAIL__RECIPIENTS=["admin@example.com","ops@example.com"]
60
+
61
+ # Purpose: SMTP authentication username
62
+ # Type: string
63
+ # Default: (empty, no authentication)
64
+ # Environment Variable: SEMDEX___EMAIL__SMTP_USERNAME=noreply@example.com
65
+ # .env: EMAIL__SMTP_USERNAME=noreply@example.com
66
+ # EMAIL__SMTP_USERNAME=noreply@example.com
67
+
68
+ # Purpose: SMTP authentication password
69
+ # Type: string
70
+ # Default: (empty, no authentication)
71
+ # Environment Variable: SEMDEX___EMAIL__SMTP_PASSWORD=your-app-password
72
+ # .env: EMAIL__SMTP_PASSWORD=your-app-password
73
+ # EMAIL__SMTP_PASSWORD=your-app-password
74
+
75
+ # Purpose: Enable STARTTLS negotiation before authentication
76
+ # Type: boolean (true/false)
77
+ # Default: true
78
+ # Environment Variable: SEMDEX___EMAIL__USE_STARTTLS=true
79
+ # .env: EMAIL__USE_STARTTLS=true
80
+ # EMAIL__USE_STARTTLS=true
81
+
82
+ # Purpose: Socket timeout in seconds for SMTP operations
83
+ # Type: float
84
+ # Default: 30.0
85
+ # Environment Variable: SEMDEX___EMAIL__TIMEOUT=30.0
86
+ # .env: EMAIL__TIMEOUT=30.0
87
+ # EMAIL__TIMEOUT=30.0
88
+
89
+ # Purpose: Verify the SMTP server's TLS certificate after STARTTLS
90
+ # Type: boolean (true/false)
91
+ # Default: true
92
+ # Note: false accepts ANY certificate; use it only for a known internal relay
93
+ # Environment Variable: SEMDEX___EMAIL__STARTTLS_VERIFY=true
94
+ # .env: EMAIL__STARTTLS_VERIFY=true
95
+ # EMAIL__STARTTLS_VERIFY=true
96
+
97
+ # Purpose: Host name announced in the SMTP greeting (EHLO); set it where reverse DNS is slow
98
+ # Type: string
99
+ # Default: unset (looked up once per process)
100
+ # Environment Variable: SEMDEX___EMAIL__LOCAL_HOSTNAME=mail.example.com
101
+ # .env: EMAIL__LOCAL_HOSTNAME=mail.example.com
102
+ # EMAIL__LOCAL_HOSTNAME=mail.example.com
103
+
104
+ # Purpose: Upper bound in seconds for one SMTP session (connect to QUIT); 0 for none
105
+ # Type: float
106
+ # Default: 0 (none)
107
+ # Environment Variable: SEMDEX___EMAIL__DELIVERY_DEADLINE=300
108
+ # .env: EMAIL__DELIVERY_DEADLINE=300
109
+ # EMAIL__DELIVERY_DEADLINE=300
110
+
111
+ # Purpose: Most recipients one send accepts; 0 for no limit
112
+ # Type: integer
113
+ # Default: 1000
114
+ # Environment Variable: SEMDEX___EMAIL__RECIPIENT_MAX_COUNT=1000
115
+ # .env: EMAIL__RECIPIENT_MAX_COUNT=1000
116
+ # EMAIL__RECIPIENT_MAX_COUNT=1000
117
+
118
+ # Purpose: Raise FileNotFoundError when attachment files are missing
119
+ # Type: boolean (true/false)
120
+ # Default: true
121
+ # Environment Variable: SEMDEX___EMAIL__RAISE_ON_MISSING_ATTACHMENTS=true
122
+ # .env: EMAIL__RAISE_ON_MISSING_ATTACHMENTS=true
123
+ # EMAIL__RAISE_ON_MISSING_ATTACHMENTS=true
124
+
125
+ # Purpose: Raise ValueError when recipient addresses are invalid
126
+ # Type: boolean (true/false)
127
+ # Default: true
128
+ # Environment Variable: SEMDEX___EMAIL__RAISE_ON_INVALID_RECIPIENT=true
129
+ # .env: EMAIL__RAISE_ON_INVALID_RECIPIENT=true
130
+ # EMAIL__RAISE_ON_INVALID_RECIPIENT=true
131
+
132
+
133
+ # ==============================================================================
134
+ # Logging Configuration (lib_log_rich)
135
+ # ==============================================================================
136
+ #
137
+ # Naming Convention
138
+ # -----------------
139
+ # Format: <SECTION>__<KEY>=value (double underscore separates section from key)
140
+ # Strings need no quotes. An unquoted value is converted: true/false become booleans,
141
+ # null/none become None, a JSON array or object is parsed, and a number becomes a number only
142
+ # when it converts back to the same text; quote a value to keep it as text. A table is a JSON object, written unquoted
143
+ # (LIB_LOG_RICH__CONSOLE_STYLES={"ERROR":"bold red"}), or one key per entry
144
+ # (LIB_LOG_RICH__SCRUB_PATTERNS__API_KEY=.+). Comma-separated pairs are NOT a table: they
145
+ # arrive as ONE string and are refused.
146
+ #
147
+ # Full environment variable (outside .env):
148
+ # SEMDEX___LIB_LOG_RICH__<KEY>=value
149
+ #
150
+ # For nested subsections (e.g. payload_limits):
151
+ # SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__<KEY>=value
152
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__<KEY>=value
153
+
154
+ # --- Core Identity ---
155
+
156
+ # Purpose: Logical service name recorded in each log event
157
+ # Type: string (non-empty)
158
+ # Default: "semdex"
159
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__SERVICE=my-application
160
+ # .env: LIB_LOG_RICH__SERVICE=my-application
161
+ # LIB_LOG_RICH__SERVICE=my-application
162
+
163
+ # Purpose: Deployment environment label
164
+ # Type: string (non-empty)
165
+ # Default: "prod"
166
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__ENVIRONMENT=dev
167
+ # .env: LIB_LOG_RICH__ENVIRONMENT=dev
168
+ # LIB_LOG_RICH__ENVIRONMENT=dev
169
+
170
+ # --- Console Output ---
171
+
172
+ # Purpose: Minimum severity level emitted to Rich console
173
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
174
+ # Default: "INFO"
175
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
176
+ # .env: LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
177
+ # LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
178
+
179
+ # Purpose: Where to send console output
180
+ # Type: string: "stdout", "stderr", "both", "custom", "none"
181
+ # Default: "stderr"
182
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_STREAM=stderr
183
+ # .env: LIB_LOG_RICH__CONSOLE_STREAM=stderr
184
+ # LIB_LOG_RICH__CONSOLE_STREAM=stderr
185
+
186
+ # Purpose: Console line layout preset
187
+ # Type: string (case-insensitive): "full", "short", "full_loc", "short_loc"
188
+ # Default: "short_loc"
189
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
190
+ # .env: LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
191
+ # LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
192
+
193
+ # Purpose: Custom console output template (overrides preset)
194
+ # Type: string (Python str.format template); empty = uses preset
195
+ # Default: (empty, uses preset)
196
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
197
+ # .env: LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
198
+ # LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
199
+
200
+ # Purpose: Rich color palette for console output
201
+ # Type: string: "classic", "dark", "neon", "pastel"
202
+ # Default: "dark"
203
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_THEME=dark
204
+ # .env: LIB_LOG_RICH__CONSOLE_THEME=dark
205
+ # LIB_LOG_RICH__CONSOLE_THEME=dark
206
+
207
+ # Purpose: Override Rich styles per severity level
208
+ # Type: table of LEVEL = style (a JSON object keeps the level names upper case)
209
+ # Default: (empty, uses theme defaults)
210
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__CONSOLE_STYLES='{"DEBUG":"dim","ERROR":"bold red"}'
211
+ # .env: LIB_LOG_RICH__CONSOLE_STYLES={"DEBUG":"dim","ERROR":"bold red"}
212
+ # LIB_LOG_RICH__CONSOLE_STYLES={"DEBUG":"dim","ERROR":"bold red"}
213
+
214
+ # Purpose: Force ANSI color output even when stderr is not a TTY
215
+ # Type: boolean (true/false)
216
+ # Default: false
217
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__FORCE_COLOR=true
218
+ # .env: LIB_LOG_RICH__FORCE_COLOR=true
219
+ # LIB_LOG_RICH__FORCE_COLOR=true
220
+
221
+ # Purpose: Disable color output entirely (overrides force_color)
222
+ # Type: boolean (true/false)
223
+ # Default: false
224
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__NO_COLOR=false
225
+ # .env: LIB_LOG_RICH__NO_COLOR=false
226
+ # LIB_LOG_RICH__NO_COLOR=false
227
+
228
+ # --- Backend Adapters ---
229
+
230
+ # Purpose: Minimum severity threshold for journald and Windows Event Log
231
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
232
+ # Default: "WARNING"
233
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__BACKEND_LEVEL=WARNING
234
+ # .env: LIB_LOG_RICH__BACKEND_LEVEL=WARNING
235
+ # LIB_LOG_RICH__BACKEND_LEVEL=WARNING
236
+
237
+ # Purpose: Enable systemd journald adapter (Linux only; requires python3-systemd)
238
+ # Type: boolean (true/false)
239
+ # Default: false
240
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__ENABLE_JOURNALD=true
241
+ # .env: LIB_LOG_RICH__ENABLE_JOURNALD=true
242
+ # LIB_LOG_RICH__ENABLE_JOURNALD=true
243
+
244
+ # Purpose: Enable Windows Event Log adapter (Windows only)
245
+ # Type: boolean (true/false)
246
+ # Default: false
247
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__ENABLE_EVENTLOG=false
248
+ # .env: LIB_LOG_RICH__ENABLE_EVENTLOG=false
249
+ # LIB_LOG_RICH__ENABLE_EVENTLOG=false
250
+
251
+ # --- Graylog / GELF ---
252
+
253
+ # Purpose: Enable Graylog adapter for centralized logging
254
+ # Type: boolean (true/false)
255
+ # Default: false
256
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__ENABLE_GRAYLOG=true
257
+ # .env: LIB_LOG_RICH__ENABLE_GRAYLOG=true
258
+ # LIB_LOG_RICH__ENABLE_GRAYLOG=true
259
+
260
+ # Purpose: Graylog server address
261
+ # Type: JSON array [host, port]; a "host:port" string is refused (config, index, search,
262
+ # serve, send-email and send-notification exit 78; only the native LOG_GRAYLOG_ENDPOINT
263
+ # variable takes host:port)
264
+ # Default: (none, must be configured to enable Graylog)
265
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__GRAYLOG_ENDPOINT='["graylog.example.com",12201]'
266
+ # .env: LIB_LOG_RICH__GRAYLOG_ENDPOINT=["graylog.example.com",12201]
267
+ # LIB_LOG_RICH__GRAYLOG_ENDPOINT=["graylog.example.com",12201]
268
+
269
+ # Purpose: Transport protocol for Graylog (tcp, udp); TLS only supported with tcp
270
+ # Type: string: "tcp", "udp"
271
+ # Default: "tcp"
272
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
273
+ # .env: LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
274
+ # LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
275
+
276
+ # Purpose: Wrap Graylog TCP connection in TLS
277
+ # Type: boolean (true/false)
278
+ # Default: false
279
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__GRAYLOG_TLS=true
280
+ # .env: LIB_LOG_RICH__GRAYLOG_TLS=true
281
+ # LIB_LOG_RICH__GRAYLOG_TLS=true
282
+
283
+ # Purpose: Minimum severity level sent to Graylog
284
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
285
+ # Default: "WARNING"
286
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
287
+ # .env: LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
288
+ # LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
289
+
290
+ # --- Queue Settings ---
291
+
292
+ # Purpose: Route log events through background queue worker (false = synchronous, blocks on I/O)
293
+ # Type: boolean (true/false)
294
+ # Default: true
295
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__QUEUE_ENABLED=true
296
+ # .env: LIB_LOG_RICH__QUEUE_ENABLED=true
297
+ # LIB_LOG_RICH__QUEUE_ENABLED=true
298
+
299
+ # Purpose: Maximum pending events before queue full policy applies
300
+ # Type: integer (> 0)
301
+ # Default: 2048
302
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__QUEUE_MAXSIZE=2048
303
+ # .env: LIB_LOG_RICH__QUEUE_MAXSIZE=2048
304
+ # LIB_LOG_RICH__QUEUE_MAXSIZE=2048
305
+
306
+ # Purpose: Behavior when queue is full
307
+ # Type: string: "block" (wait for space), "drop" (discard events)
308
+ # Default: "block"
309
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__QUEUE_FULL_POLICY=block
310
+ # .env: LIB_LOG_RICH__QUEUE_FULL_POLICY=block
311
+ # LIB_LOG_RICH__QUEUE_FULL_POLICY=block
312
+
313
+ # Purpose: Timeout in seconds for blocking queue puts (0 = infinite wait)
314
+ # Type: float (>= 0)
315
+ # Default: 1.0
316
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
317
+ # .env: LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
318
+ # LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
319
+
320
+ # Purpose: Maximum wait in seconds for queue drain during shutdown
321
+ # Type: float (> 0)
322
+ # Default: 5.0
323
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
324
+ # .env: LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
325
+ # LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
326
+
327
+ # --- Ring Buffer ---
328
+
329
+ # Purpose: Enable in-memory circular buffer for log history (enables log.dump())
330
+ # Type: boolean (true/false)
331
+ # Default: true
332
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__ENABLE_RING_BUFFER=true
333
+ # .env: LIB_LOG_RICH__ENABLE_RING_BUFFER=true
334
+ # LIB_LOG_RICH__ENABLE_RING_BUFFER=true
335
+
336
+ # Purpose: Maximum events retained in ring buffer
337
+ # Type: integer (> 0)
338
+ # Default: 25000
339
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__RING_BUFFER_SIZE=25000
340
+ # .env: LIB_LOG_RICH__RING_BUFFER_SIZE=25000
341
+ # LIB_LOG_RICH__RING_BUFFER_SIZE=25000
342
+
343
+ # --- Dump Format ---
344
+
345
+ # Purpose: Default layout for text dumps
346
+ # Type: string (case-insensitive): "full", "short", "full_loc", "short_loc"
347
+ # Default: "full"
348
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
349
+ # .env: LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
350
+ # LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
351
+
352
+ # Purpose: Custom template for text dumps (overrides preset)
353
+ # Type: string (Python str.format template); empty = uses preset
354
+ # Default: (empty, uses preset)
355
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
356
+ # .env: LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
357
+ # LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
358
+
359
+ # --- Security & Payload ---
360
+
361
+ # Purpose: Regex patterns to redact sensitive data (field = regex)
362
+ # Type: table of field = regex; merged with the defaults
363
+ # Default: password = .+, secret = .+, token = .+
364
+ # Environment Variable, one key per field: SEMDEX___LIB_LOG_RICH__SCRUB_PATTERNS__API_KEY=.+
365
+ # .env, one key per field: LIB_LOG_RICH__SCRUB_PATTERNS__API_KEY=.+
366
+ # LIB_LOG_RICH__SCRUB_PATTERNS__API_KEY=.+
367
+
368
+ # Purpose: Throttle log emissions (max_events per window_seconds)
369
+ # Type: JSON array [max_events, window_seconds]; a "100:60" string is refused (config, index,
370
+ # search, serve, send-email and send-notification exit 78; only the native LOG_RATE_LIMIT
371
+ # variable takes MAX:WINDOW_SECONDS)
372
+ # Default: (none, no rate limiting)
373
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__RATE_LIMIT='[100,60]'
374
+ # .env: LIB_LOG_RICH__RATE_LIMIT=[100,60]
375
+ # LIB_LOG_RICH__RATE_LIMIT=[100,60]
376
+
377
+ # --- Payload Limits ---
378
+
379
+ # Purpose: Truncate vs reject oversized messages
380
+ # Type: boolean (true/false)
381
+ # Default: true
382
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
383
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
384
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
385
+
386
+ # Purpose: Maximum characters in primary log message
387
+ # Type: integer
388
+ # Default: 4096
389
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
390
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
391
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
392
+
393
+ # Purpose: Maximum keys in extra metadata dict
394
+ # Type: integer
395
+ # Default: 25
396
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
397
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
398
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
399
+
400
+ # Purpose: Maximum characters per extra value (after stringify)
401
+ # Type: integer
402
+ # Default: 512
403
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
404
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
405
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
406
+
407
+ # Purpose: Maximum nesting depth for extra structures
408
+ # Type: integer
409
+ # Default: 3
410
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
411
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
412
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
413
+
414
+ # Purpose: Total UTF-8 byte limit for sanitized extra payload
415
+ # Type: integer
416
+ # Default: 8192
417
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
418
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
419
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
420
+
421
+ # Purpose: Maximum keys in LogContext.extra
422
+ # Type: integer
423
+ # Default: 20
424
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
425
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
426
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
427
+
428
+ # Purpose: Maximum characters per context value
429
+ # Type: integer
430
+ # Default: 256
431
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
432
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
433
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
434
+
435
+ # Purpose: Number of frames preserved in exception tracebacks
436
+ # Type: integer
437
+ # Default: 10
438
+ # Environment Variable: SEMDEX___LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
439
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
440
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
441
+
442
+
443
+ # ==============================================================================
444
+ # Cloud-embedder live E2E keys (test-only)
445
+ # ==============================================================================
446
+ #
447
+ # Real-API keys for the gemini / cohere embedding end-to-end cells in
448
+ # tests/test_e2e_mcp_knowledge_matrix.py (marked local_only, excluded from CI).
449
+ #
450
+ # These are PLAIN environment variables, NOT the layered SEMDEX___ form: the
451
+ # tests read them directly via os.environ (conftest loads .env into the process
452
+ # environment), so the name is the SAME full literal in the shell and in .env.
453
+ # They are deliberately DISTINCT from the production SEMDEX___EMBEDDING__API_KEY
454
+ # so running the suite never touches a deployed key.
455
+ #
456
+ # A cell SKIPS when its key is unset, and also skips on a vendor 429 (free-tier
457
+ # quota), so an unused key is fine. Leave it COMMENTED OUT: a bare name with no
458
+ # "=" breaks the strict .env parser (LayerLoadError: Malformed line).
459
+
460
+ # Google Gemini (gemini-embedding-001). Key from Google AI Studio.
461
+ # SEMDEX_TEST_GEMINI_API_KEY=
462
+ # Optional model override (default: gemini-embedding-001)
463
+ # SEMDEX_TEST_GEMINI_MODEL=gemini-embedding-001
464
+
465
+ # Cohere (embed-v4.0). Key from the Cohere dashboard.
466
+ # SEMDEX_TEST_COHERE_API_KEY=
467
+ # Optional model override (default: embed-v4.0)
468
+ # SEMDEX_TEST_COHERE_MODEL=embed-v4.0