smartpipe-cli 1.3.0__tar.gz → 1.4.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 (287) hide show
  1. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/.gitignore +4 -0
  2. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/CHANGELOG.md +458 -3
  3. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/CITATION.cff +2 -2
  4. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/CONTRIBUTING.md +24 -5
  5. smartpipe_cli-1.4.0/PKG-INFO +332 -0
  6. smartpipe_cli-1.4.0/README.md +294 -0
  7. smartpipe_cli-1.4.0/demo/video/README.md +23 -0
  8. smartpipe_cli-1.4.0/demo/video/src/Main.tsx +74 -0
  9. smartpipe_cli-1.4.0/demo/video/src/Narration.tsx +94 -0
  10. smartpipe_cli-1.4.0/demo/video/src/Root.tsx +72 -0
  11. smartpipe_cli-1.4.0/demo/video/src/components/Background.tsx +39 -0
  12. smartpipe_cli-1.4.0/demo/video/src/components/Caption.tsx +75 -0
  13. smartpipe_cli-1.4.0/demo/video/src/components/FileGlyph.tsx +109 -0
  14. smartpipe_cli-1.4.0/demo/video/src/components/SceneFrame.tsx +64 -0
  15. smartpipe_cli-1.4.0/demo/video/src/components/Terminal.tsx +332 -0
  16. smartpipe_cli-1.4.0/demo/video/src/components/Wordmark.tsx +80 -0
  17. smartpipe_cli-1.4.0/demo/video/src/config.ts +56 -0
  18. smartpipe_cli-1.4.0/demo/video/src/font.ts +9 -0
  19. smartpipe_cli-1.4.0/demo/video/src/index.ts +4 -0
  20. smartpipe_cli-1.4.0/demo/video/src/narration/durations.json +13 -0
  21. smartpipe_cli-1.4.0/demo/video/src/narration/lines.json +13 -0
  22. smartpipe_cli-1.4.0/demo/video/src/scenes/Close.tsx +81 -0
  23. smartpipe_cli-1.4.0/demo/video/src/scenes/ColdOpen.tsx +60 -0
  24. smartpipe_cli-1.4.0/demo/video/src/scenes/CostHonesty.tsx +188 -0
  25. smartpipe_cli-1.4.0/demo/video/src/scenes/Graph.tsx +236 -0
  26. smartpipe_cli-1.4.0/demo/video/src/scenes/Hook.tsx +47 -0
  27. smartpipe_cli-1.4.0/demo/video/src/scenes/Multimodal.tsx +301 -0
  28. smartpipe_cli-1.4.0/demo/video/src/scenes/ScaleA.tsx +43 -0
  29. smartpipe_cli-1.4.0/demo/video/src/scenes/ScaleB.tsx +42 -0
  30. smartpipe_cli-1.4.0/docs/assets/demo-thumb.jpg +0 -0
  31. smartpipe_cli-1.4.0/docs/assets/graph-hero.png +0 -0
  32. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/comparison.md +11 -15
  33. smartpipe_cli-1.4.0/docs/concepts/feeding-smartpipe.md +140 -0
  34. smartpipe_cli-1.4.0/docs/concepts/granularity.md +109 -0
  35. smartpipe_cli-1.4.0/docs/concepts/models-and-providers.md +286 -0
  36. smartpipe_cli-1.4.0/docs/concepts/output-formats.md +137 -0
  37. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/concepts/pipes-and-items.md +31 -29
  38. smartpipe_cli-1.4.0/docs/concepts/structured-output.md +235 -0
  39. smartpipe_cli-1.4.0/docs/concepts/the-item.md +138 -0
  40. smartpipe_cli-1.4.0/docs/cookbook/README.md +66 -0
  41. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/cookbook/contract-extraction.md +16 -16
  42. smartpipe_cli-1.4.0/docs/cookbook/customer-feedback.md +66 -0
  43. smartpipe_cli-1.4.0/docs/cookbook/invoice-reconciliation.md +47 -0
  44. smartpipe_cli-1.4.0/docs/cookbook/knowledge-graph.md +131 -0
  45. smartpipe_cli-1.4.0/docs/cookbook/live-monitoring.md +104 -0
  46. smartpipe_cli-1.4.0/docs/cookbook/log-triage.md +106 -0
  47. smartpipe_cli-1.4.0/docs/cookbook/meeting-digest.md +42 -0
  48. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/cookbook/ranking-documents.md +15 -15
  49. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/cookbook/stream-enrichment.md +7 -7
  50. smartpipe_cli-1.4.0/docs/cookbook/training-data-prep.md +140 -0
  51. smartpipe_cli-1.4.0/docs/cookbook/video-qa.md +68 -0
  52. smartpipe_cli-1.4.0/docs/cookbook/visualizing-results.md +113 -0
  53. smartpipe_cli-1.4.0/docs/demo/index.html +26 -0
  54. smartpipe_cli-1.4.0/docs/index.md +112 -0
  55. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/inputs/files.md +56 -45
  56. smartpipe_cli-1.4.0/docs/install.md +94 -0
  57. smartpipe_cli-1.4.0/docs/learn/1-first-pipeline.md +140 -0
  58. smartpipe_cli-1.4.0/docs/learn/2-structured-data.md +108 -0
  59. smartpipe_cli-1.4.0/docs/learn/3-files-and-media.md +71 -0
  60. smartpipe_cli-1.4.0/docs/learn/4-free-verbs.md +49 -0
  61. smartpipe_cli-1.4.0/docs/learn/5-scale-and-cost.md +56 -0
  62. smartpipe_cli-1.4.0/docs/learn/6-pipelines-that-last.md +56 -0
  63. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/privacy.md +38 -25
  64. smartpipe_cli-1.4.0/docs/quickstart.md +5 -0
  65. smartpipe_cli-1.4.0/docs/reference/agents.md +18 -0
  66. smartpipe_cli-1.4.0/docs/reference/cli.md +314 -0
  67. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/reference/custom-verbs.md +14 -14
  68. smartpipe_cli-1.4.0/docs/reference/sem-files.md +199 -0
  69. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/troubleshooting.md +78 -45
  70. smartpipe_cli-1.4.0/docs/verbs/cluster.md +37 -0
  71. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/diff.md +8 -9
  72. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/distinct.md +18 -18
  73. smartpipe_cli-1.4.0/docs/verbs/embed.md +112 -0
  74. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/extend.md +15 -14
  75. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/filter.md +31 -20
  76. smartpipe_cli-1.4.0/docs/verbs/getschema.md +24 -0
  77. smartpipe_cli-1.4.0/docs/verbs/graph.md +217 -0
  78. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/join.md +29 -24
  79. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/map.md +70 -46
  80. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/outliers.md +11 -11
  81. smartpipe_cli-1.4.0/docs/verbs/readable.md +53 -0
  82. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/reduce.md +28 -29
  83. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/docs/verbs/sample.md +15 -15
  84. smartpipe_cli-1.4.0/docs/verbs/sort.md +27 -0
  85. smartpipe_cli-1.4.0/docs/verbs/split.md +77 -0
  86. smartpipe_cli-1.4.0/docs/verbs/summarize.md +41 -0
  87. smartpipe_cli-1.4.0/docs/verbs/top-k.md +116 -0
  88. smartpipe_cli-1.4.0/docs/verbs/where.md +50 -0
  89. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/mkdocs.yml +38 -4
  90. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/pyproject.toml +21 -19
  91. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/qa/README.md +53 -6
  92. smartpipe_cli-1.4.0/qa/fixtures/README.md +7 -0
  93. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/__init__.py +1 -1
  94. smartpipe_cli-1.4.0/src/smartpipe/cli/auth_cmd.py +268 -0
  95. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/chart_cmd.py +16 -6
  96. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/cluster_cmd.py +12 -3
  97. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/completions.py +23 -1
  98. smartpipe_cli-1.4.0/src/smartpipe/cli/config_cmd.py +1248 -0
  99. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/distinct_cmd.py +19 -2
  100. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/doctor_cmd.py +15 -12
  101. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/embed_cmd.py +29 -4
  102. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/extend_cmd.py +63 -1
  103. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/filter_cmd.py +38 -3
  104. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/getschema_cmd.py +1 -1
  105. smartpipe_cli-1.4.0/src/smartpipe/cli/graph_cmd.py +185 -0
  106. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/input_options.py +68 -4
  107. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/join_cmd.py +59 -3
  108. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/map_cmd.py +65 -3
  109. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/outliers_cmd.py +12 -3
  110. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/probe_cmd.py +18 -0
  111. smartpipe_cli-1.4.0/src/smartpipe/cli/read_cmd.py +124 -0
  112. smartpipe_cli-1.4.0/src/smartpipe/cli/readable_cmd.py +53 -0
  113. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/reduce_cmd.py +15 -1
  114. smartpipe_cli-1.4.0/src/smartpipe/cli/rescue.py +94 -0
  115. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/root.py +77 -20
  116. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/run_cmd.py +31 -4
  117. smartpipe_cli-1.4.0/src/smartpipe/cli/schema_cmd.py +279 -0
  118. smartpipe_cli-1.4.0/src/smartpipe/cli/schema_workshop.py +318 -0
  119. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/screens.py +83 -13
  120. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/sem_file.py +69 -10
  121. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/sort_cmd.py +3 -3
  122. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/split_cmd.py +14 -5
  123. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/summarize_cmd.py +12 -2
  124. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/top_k_cmd.py +29 -4
  125. smartpipe_cli-1.4.0/src/smartpipe/cli/update_cmd.py +103 -0
  126. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/where_cmd.py +10 -2
  127. smartpipe_cli-1.4.0/src/smartpipe/cli/write_cmd.py +60 -0
  128. smartpipe_cli-1.4.0/src/smartpipe/config/authflow.py +202 -0
  129. smartpipe_cli-1.4.0/src/smartpipe/config/bundles.py +186 -0
  130. smartpipe_cli-1.4.0/src/smartpipe/config/credentials.py +241 -0
  131. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/config/display.py +33 -19
  132. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/config/doctor.py +21 -19
  133. smartpipe_cli-1.4.0/src/smartpipe/config/picker.py +603 -0
  134. smartpipe_cli-1.4.0/src/smartpipe/config/state_cache.py +175 -0
  135. smartpipe_cli-1.4.0/src/smartpipe/config/store.py +241 -0
  136. smartpipe_cli-1.4.0/src/smartpipe/config/verify.py +288 -0
  137. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/container.py +162 -14
  138. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/core/errors.py +8 -0
  139. smartpipe_cli-1.4.0/src/smartpipe/core/install_channel.py +60 -0
  140. smartpipe_cli-1.4.0/src/smartpipe/core/versions.py +87 -0
  141. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/aggregate.py +11 -3
  142. smartpipe_cli-1.4.0/src/smartpipe/engine/chart.py +234 -0
  143. smartpipe_cli-1.4.0/src/smartpipe/engine/chunking.py +348 -0
  144. smartpipe_cli-1.4.0/src/smartpipe/engine/fieldpath.py +167 -0
  145. smartpipe_cli-1.4.0/src/smartpipe/engine/graphkg.py +484 -0
  146. smartpipe_cli-1.4.0/src/smartpipe/engine/graphout.py +513 -0
  147. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/predicate.py +45 -6
  148. smartpipe_cli-1.4.0/src/smartpipe/engine/preview.py +120 -0
  149. smartpipe_cli-1.4.0/src/smartpipe/engine/progressbar.py +68 -0
  150. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/prompts.py +300 -29
  151. smartpipe_cli-1.4.0/src/smartpipe/engine/repair.py +137 -0
  152. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/runner.py +80 -15
  153. smartpipe_cli-1.4.0/src/smartpipe/engine/schema.py +473 -0
  154. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/schema_dsl.py +44 -6
  155. smartpipe_cli-1.4.0/src/smartpipe/engine/schema_repl.py +426 -0
  156. smartpipe_cli-1.4.0/src/smartpipe/engine/temporal.py +166 -0
  157. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/timebin.py +2 -1
  158. smartpipe_cli-1.4.0/src/smartpipe/io/arrow_menu.py +198 -0
  159. smartpipe_cli-1.4.0/src/smartpipe/io/csvrows.py +174 -0
  160. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/inputs.py +3 -1
  161. smartpipe_cli-1.4.0/src/smartpipe/io/items.py +318 -0
  162. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/leaderboard.py +1 -1
  163. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/metering.py +46 -1
  164. smartpipe_cli-1.4.0/src/smartpipe/io/preview.py +296 -0
  165. smartpipe_cli-1.4.0/src/smartpipe/io/progress.py +205 -0
  166. smartpipe_cli-1.4.0/src/smartpipe/io/readers.py +979 -0
  167. smartpipe_cli-1.4.0/src/smartpipe/io/render.py +168 -0
  168. smartpipe_cli-1.4.0/src/smartpipe/io/richui.py +112 -0
  169. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/tty.py +1 -0
  170. smartpipe_cli-1.4.0/src/smartpipe/io/update_check.py +214 -0
  171. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/writers.py +106 -31
  172. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/anthropic_adapter.py +14 -1
  173. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/budget.py +63 -2
  174. smartpipe_cli-1.4.0/src/smartpipe/models/catalogs.py +189 -0
  175. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/gemini_native.py +16 -3
  176. smartpipe_cli-1.4.0/src/smartpipe/models/keycheck.py +108 -0
  177. smartpipe_cli-1.4.0/src/smartpipe/models/local_ner.py +299 -0
  178. smartpipe_cli-1.4.0/src/smartpipe/models/ocr.py +218 -0
  179. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/ollama.py +7 -4
  180. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/openai_codex.py +12 -2
  181. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/openai_compat.py +5 -3
  182. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/resolve.py +1 -2
  183. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/parsing/detect.py +15 -1
  184. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/parsing/extract.py +7 -2
  185. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/chart.py +73 -21
  186. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/cluster.py +17 -1
  187. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/common.py +202 -26
  188. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/convert.py +15 -3
  189. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/diff.py +6 -0
  190. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/distinct.py +66 -7
  191. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/embed.py +66 -13
  192. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/extend.py +92 -22
  193. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/filter.py +97 -23
  194. smartpipe_cli-1.4.0/src/smartpipe/verbs/graph.py +492 -0
  195. smartpipe_cli-1.4.0/src/smartpipe/verbs/graphfull.py +614 -0
  196. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/join.py +298 -25
  197. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/map.py +185 -37
  198. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/outliers.py +1 -1
  199. smartpipe_cli-1.4.0/src/smartpipe/verbs/oversize.py +387 -0
  200. smartpipe_cli-1.4.0/src/smartpipe/verbs/readable.py +64 -0
  201. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/reduce.py +137 -34
  202. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/sortverb.py +27 -5
  203. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/split.py +56 -23
  204. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/summarize.py +23 -0
  205. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/top_k.py +137 -30
  206. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/where.py +21 -1
  207. smartpipe_cli-1.4.0/src/smartpipe/verbs/write.py +209 -0
  208. smartpipe_cli-1.3.0/PKG-INFO +0 -192
  209. smartpipe_cli-1.3.0/README.md +0 -150
  210. smartpipe_cli-1.3.0/docs/concepts/models-and-providers.md +0 -225
  211. smartpipe_cli-1.3.0/docs/concepts/output-formats.md +0 -106
  212. smartpipe_cli-1.3.0/docs/concepts/structured-output.md +0 -148
  213. smartpipe_cli-1.3.0/docs/cookbook/README.md +0 -46
  214. smartpipe_cli-1.3.0/docs/cookbook/live-monitoring.md +0 -85
  215. smartpipe_cli-1.3.0/docs/cookbook/log-triage.md +0 -65
  216. smartpipe_cli-1.3.0/docs/cookbook/training-data-prep.md +0 -70
  217. smartpipe_cli-1.3.0/docs/cookbook/video-qa.md +0 -52
  218. smartpipe_cli-1.3.0/docs/cookbook/visualizing-results.md +0 -113
  219. smartpipe_cli-1.3.0/docs/index.md +0 -70
  220. smartpipe_cli-1.3.0/docs/install.md +0 -92
  221. smartpipe_cli-1.3.0/docs/quickstart.md +0 -119
  222. smartpipe_cli-1.3.0/docs/reference/cli.md +0 -207
  223. smartpipe_cli-1.3.0/docs/reference/sem-files.md +0 -148
  224. smartpipe_cli-1.3.0/docs/verbs/cluster.md +0 -39
  225. smartpipe_cli-1.3.0/docs/verbs/embed.md +0 -92
  226. smartpipe_cli-1.3.0/docs/verbs/getschema.md +0 -26
  227. smartpipe_cli-1.3.0/docs/verbs/sort.md +0 -21
  228. smartpipe_cli-1.3.0/docs/verbs/split.md +0 -76
  229. smartpipe_cli-1.3.0/docs/verbs/summarize.md +0 -35
  230. smartpipe_cli-1.3.0/docs/verbs/top-k.md +0 -108
  231. smartpipe_cli-1.3.0/docs/verbs/where.md +0 -55
  232. smartpipe_cli-1.3.0/src/smartpipe/cli/auth_cmd.py +0 -78
  233. smartpipe_cli-1.3.0/src/smartpipe/cli/config_cmd.py +0 -234
  234. smartpipe_cli-1.3.0/src/smartpipe/cli/schema_cmd.py +0 -75
  235. smartpipe_cli-1.3.0/src/smartpipe/config/credentials.py +0 -118
  236. smartpipe_cli-1.3.0/src/smartpipe/config/store.py +0 -252
  237. smartpipe_cli-1.3.0/src/smartpipe/engine/chart.py +0 -143
  238. smartpipe_cli-1.3.0/src/smartpipe/engine/chunking.py +0 -161
  239. smartpipe_cli-1.3.0/src/smartpipe/engine/schema.py +0 -208
  240. smartpipe_cli-1.3.0/src/smartpipe/io/items.py +0 -149
  241. smartpipe_cli-1.3.0/src/smartpipe/io/progress.py +0 -140
  242. smartpipe_cli-1.3.0/src/smartpipe/io/readers.py +0 -455
  243. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/LICENSE +0 -0
  244. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/NOTICE +0 -0
  245. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/__main__.py +0 -0
  246. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/assets/probe.png +0 -0
  247. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/assets/probe.txt +0 -0
  248. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/assets/probe.wav +0 -0
  249. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/__init__.py +0 -0
  250. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/cache_cmd.py +0 -0
  251. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/cite_cmd.py +0 -0
  252. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/diff_cmd.py +0 -0
  253. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/echo_cmd.py +0 -0
  254. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/interrupts.py +0 -0
  255. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/sample_cmd.py +0 -0
  256. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/cli/usage_cmd.py +0 -0
  257. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/config/__init__.py +0 -0
  258. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/config/paths.py +0 -0
  259. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/core/__init__.py +0 -0
  260. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/core/jsontools.py +0 -0
  261. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/__init__.py +0 -0
  262. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/blocking.py +0 -0
  263. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/clustering.py +0 -0
  264. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/ranking.py +0 -0
  265. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/tally.py +0 -0
  266. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/units.py +0 -0
  267. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/engine/windows.py +0 -0
  268. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/__init__.py +0 -0
  269. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/diagnostics.py +0 -0
  270. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/text.py +0 -0
  271. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/io/usage.py +0 -0
  272. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/__init__.py +0 -0
  273. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/base.py +0 -0
  274. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/cache.py +0 -0
  275. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/http_support.py +0 -0
  276. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/jina.py +0 -0
  277. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/local_embed.py +0 -0
  278. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/openai_oauth.py +0 -0
  279. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/retry.py +0 -0
  280. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/stt.py +0 -0
  281. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/models/windows.py +0 -0
  282. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/parsing/__init__.py +0 -0
  283. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/py.typed +0 -0
  284. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/__init__.py +0 -0
  285. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/getschema.py +0 -0
  286. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/src/smartpipe/verbs/sample.py +0 -0
  287. {smartpipe_cli-1.3.0 → smartpipe_cli-1.4.0}/tests/corpus/README.md +0 -0
@@ -23,3 +23,7 @@ context/
23
23
  /plan/
24
24
  /TODO.md
25
25
  /idea.md
26
+
27
+ # Local-only scratch folder — never tracked, never in the sdist
28
+ /local/
29
+ .claude/
@@ -5,6 +5,457 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · Versioning:
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+
9
+ ## [1.4.0] — 2026-07-10
10
+
11
+ The identity release.
12
+
13
+ ### Knowledge graphs (the highlight)
14
+ - **The showcase**: a full verb page with the modality matrix and a
15
+ live-rendering Mermaid sample, a cookbook chapter written from real
16
+ runs against the downloadable playground corpus, the README highlight
17
+ with a screenshot of the case graph, agent SKILL recipes, and `graph`
18
+ on the welcome screen. Found en route: the playground download in the
19
+ docs pointed at the source tarball (no media inside) - all three
20
+ sites now fetch the actual 26 MB release asset.
21
+
22
+ - **`smartpipe graph --fast` turns a corpus into a knowledge graph for
23
+ exactly $0.** A local zero-shot NER model (GLiNER-small over ONNX -
24
+ no new dependencies, no torch, a one-time ~190 MB download like the
25
+ local embedder) finds YOUR entity types (`--entities "person, vessel,
26
+ account"`), entities co-occurring in a window become weighted edges,
27
+ near-duplicate names fold into one node (disclosed), and every edge
28
+ carries its `sources` - the files, pages, and minutes where it was
29
+ seen. Zero model calls, pinned by test. Free transcripts (local
30
+ whisper) mean audio and video speech join the graph; scans and
31
+ images wait for the paid mode, counted out loud.
32
+ - **Six ways out, all deterministic**: `.graphml` (Gephi), `.dot`
33
+ (Graphviz), `.mmd` (Mermaid), `nodes.csv`+`edges.csv` (Neo4j/Kuzu),
34
+ a self-contained interactive `.html` (search, weight slider, hover
35
+ cards with clickable `file://` evidence links), or a trailing `/`
36
+ for an Obsidian vault of wikilinked entity notes.
37
+ - **A focus prompt buys named relations.** `smartpipe graph "people,
38
+ orgs, and money flows" case/**/*` extracts typed triples per chunk
39
+ through the full multimodal ladders - vision, OCR, native video -
40
+ with `--entities`/`--relations` compiling to enums when you want a
41
+ strict ontology. The cost plan prints BEFORE any spend (`~810
42
+ extraction calls; belt is 500 - the graph will be partial`), a
43
+ terminal decline exits clean at zero calls, and a belted run drains
44
+ to a valid partial graph at exit 1, never a fake success.
45
+ - **The hybrid ladder: `--name-top 200`.** The free pass finds the
46
+ candidates; the model names only the strongest links - one call per
47
+ edge, and if the belt runs out the remainder keeps its honest
48
+ `co-occurs` label, disclosed. Free graph in seconds; name the top
49
+ edges for cents.
50
+ - **Bring your own edges.** Records with `{source, target}` or
51
+ `{subject, relation, object}` on stdin skip extraction entirely -
52
+ canonicalize, fold, serialize. Your own `extend` pipeline is the
53
+ power path.
54
+
55
+ ### The item — one law for everything in a pipe
56
+ - **Nested field paths, everywhere you read.** `where 'user.plan ==
57
+ "pro"'`, `sort --by metrics.score`, `chart items[0].category`,
58
+ `summarize 'avg(metrics.score) by user.plan'`, and `"Is {user.plan}
59
+ worth it?"` in prompts - one grammar (`a.b.c`, `items[0]`,
60
+ `a.b['weird key']`) across all five surfaces. A column literally
61
+ named `user.plan` always wins over the traversal, so CSV headers
62
+ with dots keep working. Extraction names stay flat - paths are for
63
+ reading, and the error says so.
64
+
65
+ - **Dates are a type, and they come back ISO.** `{due date}` and
66
+ `{ts datetime}` join the brace grammar. However the model phrases it
67
+ ("Jan 15, 2026", "15/01/2026"), the field canonicalizes to
68
+ `YYYY-MM-DD` / full ISO-8601 - offsets preserved, never invented;
69
+ genuinely ambiguous slash-dates read month-first and say so on
70
+ stderr. Downstream just works: `where 'due >= "2026-01-01"'`
71
+ compares temporally, `sort --by due` orders by instant, and
72
+ `summarize 'count() by bin(due, 1d)'` buckets date-only values.
73
+ - **The model sees your data framed, not dumped.** Every item payload
74
+ now arrives inside an `<input>` fence - records rendered as clean
75
+ YAML-ish (the `__` plumbing excluded), text as itself. The
76
+ instruction can no longer blur into the data, and the fence is the
77
+ foundation the planned request-batching builds on.
78
+ - **CSV is a first-class row format.** `--as csv` (and `.csv`/`.tsv`
79
+ extension defaults - tab dialect for `.tsv`) reads the header row as
80
+ field names and streams every data row as a record, with per-cell
81
+ int → float → string coercion and multi-line quoted cells handled. A
82
+ ragged row is a loud error naming the file and physical line; rows
83
+ carry `__source {"as": "csv", "line": N}`. Works on stdin too, and
84
+ `.sem` files gain the `as` key.
85
+ - **Malformed model replies repair for free before they cost money.**
86
+ A structured reply that fails to parse now passes through a
87
+ deterministic fixer first - code fences, JSON-island extraction,
88
+ Python-repr literals, trailing commas, quote fixes, all validated by
89
+ an actual parse - and only escalates to the paid model-repair round
90
+ trip when that fails. Disclosed once per run:
91
+ `note: N replies repaired deterministically (fences/commas/quotes)`.
92
+ - **The `__` metadata spine.** Tool metadata lives in a reserved
93
+ double-underscore namespace that rides every record: `__source` (path plus
94
+ HOW the item was cut - file, lines, jsonl, pages, minutes, segment index),
95
+ `__media` (one transport object for bytes crossing a pipe), `__score`
96
+ (top_k and join similarity), `__rank` (top_k), `__snapshot` (top_k
97
+ --stream markers), `__distance` (outliers), `__invalid`/`__error`/`__raw`
98
+ (kept failures). Known fields round-trip through saved files; unknown `__`
99
+ fields warn once and carry. User data owns everything up to one leading
100
+ underscore - which is why the last single-underscore stragglers moved:
101
+ pre-1.4 `top_k`/`outliers` wrote `_score`/`_rank`/`_snapshot`/`_distance`,
102
+ and those spellings stay readable for one release (CSV/TSV still sort them
103
+ into the trailing columns) but are never written again. In the same sweep,
104
+ `cluster --explode` overwriting an existing `cluster` field became a
105
+ disclosed overwrite (one stderr warning) instead of a silent one.
106
+ - **top_k ranks can no longer collide.** Ranking keyed on each item's
107
+ source index, so two page-1 records from different PDFs fought over one
108
+ slot and a result silently vanished. Ranks are now run-scoped ordinals in
109
+ arrival order, in both the embedded and precomputed-vector paths.
110
+ - **Records in, records out.** A plain-prompt `map` over records now returns
111
+ a record (`{"result": …}` plus the spine) instead of bare prose - structure
112
+ and provenance survive transformation. Text lines still leave as text.
113
+ - **The `--as` ingestion dial** (`file` | `lines` | `jsonl`) on every input
114
+ verb. Auto defaults: `.jsonl` means rows (loud per-line errors on
115
+ non-JSON), everything else means whole-document; stdin keeps per-line
116
+ sniffing; `--as file` slurps stdin whole (new). Media files refuse text
117
+ granularities with signposts to `split`.
118
+ - **The binary is the reader.** `smartpipe report.pdf | …` - a first
119
+ argument that exists on disk streams items; verbs always win names,
120
+ `./name` disambiguates. Every input verb also takes positional FILE
121
+ arguments; `--in` survives as a hidden alias.
122
+ - **`write` — the egress mirror.** Items route to files by template
123
+ (`{name}`, `{stem}`, `{index}`, any record field for content fan-out);
124
+ egress mirrors ingress via the spine - whole-file items become files,
125
+ line/row items reassemble into their sources in original order. Emits
126
+ written paths so pipes continue. Text-only records leave as plain text.
127
+ - **`readable` — the human door.** The same YAML-ish renderer as the TTY
128
+ preview, as an explicit pipe stage: nesting indented, lists bulleted,
129
+ multi-line strings as block scalars, spine dimmed, long values truncated
130
+ with counts (`--full` to disable), media summarized (`image/png (48 KB)`)
131
+ - never base64. Piped machine output is untouched JSONL; `--bare` strips
132
+ the spine from it.
133
+ - **Mixed streams are visible.** A kind census notes mixed inputs;
134
+ `where`/`summarize` report rows that had no fields; `--strict-rows` turns
135
+ the notes into errors. Multi-line plain output into a pipe warns that
136
+ line framing is ambiguous (use `--output json`).
137
+ - **`.sem` files are strict about their rows now.** A saved pipeline is a
138
+ program, and a stray plain line in a record stream is a bug, not a
139
+ shrug: `.sem` runs default to `--strict-rows` and fail at ingestion
140
+ naming the exact line, before any spend. Opt out with
141
+ `strict-rows = false` (top-level or per-stage); ad-hoc terminal runs
142
+ keep the permissive census. Eleven verbs that accepted `--strict-rows`
143
+ without actually enforcing it now do, and a text-only `where` predicate
144
+ over a log no longer trips strict mode over "missing fields". A new
145
+ docs page explains the granularity ladder (file → split → lines/rows)
146
+ and when mixing happens.
147
+ - **Synthesized records tell you what they summarize.** join pairs carry
148
+ `__sources` (both parents' refs); reduce windows stamp
149
+ `{"as": "window", "span": [1, 100], "count": 100}`, groups
150
+ `{"as": "group", "group": …, "count": N}`; cluster and diff summary
151
+ rows carry `{"as": "cluster"|"diff", "count": N}`. An audit trail for
152
+ every row that speaks for other rows - and `--bare` strips all of it.
153
+
154
+ ### Judgment you can gate, retry, and keep
155
+ - **`--keep-invalid`** (map/extend): after the repair retry fails, keep the
156
+ failure as one JSON row (`__invalid`/`__error`/`__raw`) instead of a skip
157
+ - dim one-liner at a TTY, full row when piped.
158
+ - **`smartpipe schema`** - the free rungs: compile braces/DSL to JSON Schema,
159
+ `--check FILE` validates rows (exit 0/1), `--example` prints a validating
160
+ instance, bare stdin mode is a REPL. **`--dry-run`** (map/extend) prints
161
+ the composed first request and exits before any model resolution.
162
+ - **`schema --check` stopped failing your own pipelines.** The check is
163
+ open-world now: rows from the documented extend workflow (original
164
+ fields kept, spine aboard) pass instead of tripping "additional
165
+ properties are not allowed" on every row, and `?`-marked fields may be
166
+ absent, not just null. Extras earn one dim hint; `--strict` restores
167
+ the closed world for contract enforcement. The schema sent to models
168
+ at extraction time is unchanged.
169
+ - **Nullability is declared.** `?` on any type (`string?`, `number[]?`, bare
170
+ `field?`) compiles to a null union; bare fields mean scalar-or-scalar-list
171
+ and never admit null (D48, shipped earlier in this cycle).
172
+ - **Circuit breaker + `fallback-model`.** Five consecutive transport
173
+ failures stop the run with a provider-down screen (`SMARTPIPE_BREAKER`
174
+ tunes; 0 disables) - or, with a configured fallback, the run switches
175
+ chat models wholesale, re-runs the failed window on the successor, and
176
+ the receipt splits counts per model. Embedding fallback is refused
177
+ (one vector space per run). One fallback, no chains.
178
+ - **Deterministic rungs.** `join --on 'left.K == right.K'` alone is a free
179
+ key-equality join (all kinds, `--unmatched`); with a prompt it becomes
180
+ blocking - equality narrows pairs, the judge reasons within blocks, the
181
+ receipt reports pairs avoided. `distinct --exact` folds byte/value
182
+ duplicates only (records canonicalized, media hashed by bytes) - zero
183
+ model calls. Verb tables mark the free rungs.
184
+
185
+ ### The terminal behaves
186
+ - **A real progress bar.** When the total is knowable (file lists), the
187
+ status line becomes `[██████░░░░░░░░░] 41% · 205/500 · 12/s · ~25s
188
+ left` - fill and percent truncate so 100% is earned, the ETA appears
189
+ once the first item completes, ASCII terminals get `[=====>....]`,
190
+ and multi-stage runs prefix the stage name. Streams keep the
191
+ count-and-rate line: a `tail -f` has no percent.
192
+ - **Braces extract lists of objects.** `{events {name string, when
193
+ date, severity enum(low, high)}[]}` pulls every event out of an item
194
+ in one call, typed and validated - inner dates still canonicalize to
195
+ ISO, `--explode events` turns the list into one row each. One level
196
+ deep by design; deeper nesting faults free at parse time with the
197
+ two-pass hint.
198
+ - Result writes pause/erase/redraw the status line under an arbiter - the
199
+ spinner can never interleave with output again. Only the final pipe stage
200
+ (stdout a TTY) animates; mid-pipe stages stay line-atomic.
201
+ - Records render at the TTY as YAML-ish blocks. The welcome screen links
202
+ docs, cookbook, and issues. The wizard offers to install shell
203
+ completions (consented, idempotent).
204
+ - **`chart` re-platformed: plotext draws the terminal, matplotlib renders
205
+ `--save`.** TTY bars get color (cyan bars, green time-series); piped or
206
+ `NO_COLOR` output keeps the plain-ASCII contract byte-for-byte. `--save`
207
+ now writes SVG or PNG by extension (identity-styled, deterministic
208
+ output); svgwrite - unmaintained since 2022 - leaves the tree. Both
209
+ libraries ship in core per the no-extras rule; imports stay
210
+ function-local so startup holds. The run receipt now reads
211
+ `run: ↑40 ↓25 tok` (arrows for in/out). The wizard validates model names
212
+ before saving (two strikes, then a typed fault), prints completions
213
+ before the paste-bait "Try it" line, prefers a sensible local default
214
+ over alphabetical luck (cloud tags compete equally), and speaks in the
215
+ same color voice as the other commands with a menu of detected local
216
+ tags and provider-prefixed cloud examples.
217
+ - **Exit 141 is now deliberate, and the -13 flake is dead.** smartpipe used
218
+ to arm the default SIGPIPE handler, so a downstream `| head` killed it by
219
+ raw signal - and, one run in a few hundred, a stray EPIPE on asyncio's
220
+ own self-pipe killed a healthy run mid-teardown, skipping the receipt
221
+ (the CI flake that delayed rc3). SIGPIPE now stays ignored; a closed
222
+ stdout surfaces as BrokenPipeError and exits a silent, deliberate 141
223
+ with every finally honored. (click 8.4's own EPIPE-to-exit-1 trap is
224
+ defused on the way.) One visible delta: `kill -PIPE` no longer
225
+ terminates smartpipe; pipeline behavior is unchanged.
226
+ - **A files-then-stdin wait has a name.** Chaining positional files into a
227
+ stdin read used to end in a silent hang when nothing was piped. All three
228
+ chain paths now say once, on stderr:
229
+ `note: files done - now reading stdin (pipe data or close it; files-only: add < /dev/null)`.
230
+ - **Docs bug, live-caught: `cluster | chart` drew flat bars.** The summary
231
+ rows are one-per-cluster, so charting them counts every theme once. The
232
+ README quick-tour step, the `cluster` help epilog, and the `.sem`
233
+ pipeline example now route `cluster --explode members` into
234
+ `chart cluster --top 8`, which draws real sizes.
235
+
236
+ ### Every example, run for real
237
+ - **`map` and `extend` records finally carry their provenance.** The
238
+ `__source` spine - the law said it rides every record - was being
239
+ dropped by braces extraction: a reader-stamped row went in with
240
+ `{"path", "as", "line"}` and came out with only the extracted fields.
241
+ Every record leaving `map`/`extend` now carries `__source` (incoming
242
+ spines adopted verbatim, fresh ones stamped from the item's
243
+ provenance), which also means the terminal preview now shows the dim
244
+ file-and-line origin under each block. `--bare` still strips it.
245
+ - **Docs truth sweep** (owner-reported): four `echo "... $1250"`
246
+ examples silently shell-expanded to "250" - single-quoted; text files
247
+ are declared one-item-per-line at first use; "everything outside the
248
+ braces is the instruction" stated wherever braces are taught; typed
249
+ braces are the norm across the examples; the playground corpus is
250
+ linked from README, docs home, and the cookbook; the demo video plays
251
+ on the docs front page.
252
+ - **Row cuts keep their rows through `filter` and `top_k`.** The grep-l
253
+ contract (match whole files, get paths back) leaked onto `--as jsonl` /
254
+ `--as lines` rows read from a positional file: every matching ROW came
255
+ out as the filename. Both verbs now key path-back on the whole-file cut;
256
+ rows pass through as records. Found by a zero-context agent driving
257
+ smartpipe purely from SKILL.md; pinned in tests both ways.
258
+ - **The docs were audited by executing them**: all 236 example blocks
259
+ (README, docs, SKILL files, CLI help) inventoried, statically checked,
260
+ and ~105 run verbatim against a generated corpus of real-format files.
261
+ Three code bugs surfaced and are fixed with pinning tests:
262
+ - **Quoted globs reach the reader.** `smartpipe 'logs/*.jsonl'` - a
263
+ documented form - exited 64 ("no verb"); unexpanded glob tokens now
264
+ route to reader mode, and an unmatched glob errs loudly.
265
+ - **Video is refused pre-send on wires that can't watch.** The
266
+ ChatGPT-login (codex) and anthropic adapters silently dropped video
267
+ parts and sent prompt-only requests - the model answered "no video
268
+ provided", no degraded note fired, and video-RAG examples embedded
269
+ that refusal prose as vectors. Both wires now raise before sending,
270
+ so the documented ladder (`degraded: … video → frames+audio`)
271
+ actually engages.
272
+ - 7 broken and 12 misleading example sites corrected against observed
273
+ behavior (SKILL files now run verbatim; the `.sem` key table is
274
+ re-derived from the runtime's own validation errors; `__score`
275
+ spelling; stale "oversized items are refused" claims rewritten for
276
+ auto-chunking).
277
+
278
+ ### The terminal shows your media
279
+ - **Every block at the terminal gets a number.** The human view opens
280
+ each record block with a cyan `#N` - so "look at object 5" is a thing
281
+ you can say. The ordinal is the one handle every output is guaranteed
282
+ to have (provenance can repeat across rows - fifty pages of one PDF
283
+ share a path - or be absent on plain text). Display only: piped
284
+ output is byte-identical.
285
+ - **Media previews at the human view.** At a terminal (and through
286
+ `readable`), the first media part of an item now renders under its
287
+ summary line: images as color thumbnails, video as a three-frame strip
288
+ sampled at 10/50/90% of its duration (never frame zero - intros are
289
+ black), audio as a peak-envelope waveform. Audio and video that still
290
+ live on disk get a clickable `▶ play (0:42, 2.1 MB)` link (OSC 8 -
291
+ opens your system player in iTerm2/kitty/WezTerm/Ghostty/Windows
292
+ Terminal). Piped output, JSONL, NO_COLOR, and `--bare` are
293
+ byte-identical to before - previews exist only where a human is
294
+ looking. `smartpipe config media-previews off` turns them off.
295
+
296
+ ### Documents parse where they enter, vectors stay honest
297
+ - **The `ocr-model` role: a document parser at ingestion.** Set
298
+ `ocr-model = "mistral/mistral-ocr-latest"` in config.toml (the setup
299
+ flow's OCR stage stamps it; `SMARTPIPE_OCR_MODEL` and `--ocr-model`
300
+ override per run) and ingested PDFs and images parse through it - one
301
+ item per page on the `pages` cut, markdown as the text, disclosed per
302
+ row and metered as a paid conversion. Mistral refs ride the dedicated
303
+ `/v1/ocr` wire (live-verified, whole PDFs in one call); any other
304
+ model ref works as chat-vision with extract-the-text framing, so
305
+ `ollama/llava` is a free local OCR. Parse failures fall back to the
306
+ local extraction ladder, disclosed, never fatal. Unset = exactly the
307
+ old behavior.
308
+ - **Reader mode does what you configured.** `smartpipe scan.pdf` used to
309
+ be pinned "zero model calls" even when you had set an ocr-model - the
310
+ reader now honors the role with the same per-row disclosure, local
311
+ fallback, and `--max-calls` belt as the verbs (plus a preflight note
312
+ when more than 20 files will parse). No ocr-model configured = the
313
+ same free path as always, pinned by a zero-HTTP-calls test. Found en
314
+ route: the mistral OCR wire was never counted by `--max-calls`
315
+ anywhere - it is belted now.
316
+ - **The `media-embed-model` role: one joint space for pixels and prose.**
317
+ Text keeps `embed-model`; media routes to the joint-space model
318
+ (jina-clip-v2 and friends). If a run would mix two vector spaces, the
319
+ geometry fence stops it with exit 64 BEFORE any spend, naming both
320
+ models and both fixes. A text query now ranks an image corpus in the
321
+ joint space - that is the point.
322
+ - **Embed rows carry their provenance.** Output rows are now
323
+ `{"text", "vector", "__embedder", "__source"}` - the spine like every
324
+ other verb, plus the model that made the vector. `top_k` refuses a
325
+ corpus whose stamp disagrees with the query's embedder (the
326
+ same-dimensions-different-model trap), and reads old-style rows for
327
+ one release. Two bugs died en route: records piped from the reader
328
+ embedded their serialized JSON instead of their content text, and
329
+ `--max-calls` silently demoted pixels to captions by stripping the
330
+ media-embedding capability.
331
+
332
+ ### Setup that reads the room
333
+ - **Rich now backs `config show` and `doctor`.** It is a deliberate core
334
+ dependency under the no-extras policy, imported only while those human-facing
335
+ screens render so `--help`, pipes, and `NO_COLOR` keep their existing contracts.
336
+ - **The interactive config wizard can go backward.** Model, embedding, OCR, and
337
+ final review screens expose explicit Back rows; returning to a stage restores
338
+ its pre-stage checkpoint, and typed model prompts accept `back`, `b`, `no`, or
339
+ `n` instead of accidentally saving `ollama/n`.
340
+
341
+
342
+ - **Discarding config is terminal and interruption is ordinary.** Choosing
343
+ discard no longer opens the shell-completion prompt after saying "Not saved";
344
+ Ctrl-C or EOF at any Click prompt exits 130 instead of showing the internal-bug
345
+ screen.
346
+
347
+ - **`auth login` now connects every provider, not just ChatGPT.** Pick
348
+ from the full list - OpenAI appears twice because it really is two
349
+ wires (API key vs ChatGPT login, and the login wire has no
350
+ embeddings) - paste your key at a masked prompt after the create-a-key
351
+ URL, and it validates live before storing (with an honest
352
+ "store anyway - the provider may be having a bad minute" escape).
353
+ Keys live at `~/.local/share/smartpipe/auth.json`, owner-only
354
+ permissions from the first byte, masked everywhere they surface, and
355
+ the environment variable always wins. `auth list` shows what's
356
+ connected and which source is live; `auth logout` removes.
357
+ - **Setup walks three questions in order: text model, embeddings,
358
+ document OCR.** Every stage shows every provider - connected ones
359
+ badged, unconnected ones connectable inline without leaving the flow.
360
+ The embedding stage only lists wires that embed; OCR is optional and
361
+ skippable in one keypress. At the end, one consented verification
362
+ pass (~5 tiny requests) probes what your models can actually do -
363
+ and if the basic text check fails, smartpipe reports a setup fault
364
+ instead of pretending your model lacks modalities. Results feed the
365
+ capability chips you see in every picker from then on, alongside a
366
+ public model registry and your own declarations for self-hosted
367
+ models.
368
+
369
+ - **The schema workshop.** `smartpipe schema` with no arguments at a
370
+ terminal opens a small interactive draft loop - your schema pinned up
371
+ top as colored braces, commands scrolling below: `/add name type`,
372
+ `/drop`, `/test data.jsonl` (per-field coverage bars against your real
373
+ rows), `/example` (a synthetic instance), `/save` (writes schema.json
374
+ and prints the paste-ready braces and `--schema` lines). Zero model
375
+ calls by construction - iterate freely, commit when the bars are
376
+ green. Paste any `{braces}` string to replace the draft. Piped and
377
+ argument invocations are unchanged.
378
+ - **`smartpipe config` is now a provider-first picker.** Detect what's
379
+ already connected (API keys in the environment, a ChatGPT login, local
380
+ Ollama), pick a provider, pick from its LIVE model catalog - arrow keys
381
+ on a real terminal, a numbered prompt everywhere else. Undetected
382
+ providers show the exact `export ..._API_KEY=` line (smartpipe never
383
+ prompts for or stores a key). Catalogs cache for a day; a failed fetch
384
+ degrades to typed input with provider-prefixed examples. Picking a
385
+ provider auto-pairs a coherent embedding model (announced, and never
386
+ overwrites one you chose yourself), and one y/N question adds a backup
387
+ `fallback-model` for provider outages. After a `doctor --probe`,
388
+ catalog entries carry capability chips (`sees, hears - probed 2d ago`)
389
+ - probed facts, never claims.
390
+ - **`smartpipe use` - setup is one word now.** `use gemini` (or
391
+ `use claude-opus-4-8`, `use ollama/qwen3:8b`) stamps a coherent bundle
392
+ in one shot: the model, its paired embedder, and the captions posture,
393
+ each line disclosed with a ✓ and a reason. No credential for the named
394
+ provider = a clean refusal that names the exact `auth login` command,
395
+ nothing stamped. Bare `use` opens the interactive flow. `smartpipe
396
+ using` answers "what am I running?" with every setting, its value, and
397
+ WHERE it came from (flag, env, config file, default) in one aligned
398
+ grid. The config.toml you get is signed by its door -
399
+ `# stamped by: smartpipe use (2026-07-10T06:38Z)` - so a mystery
400
+ config explains itself. The old setter subcommands (`config model`,
401
+ `config embed-model`, …) and profiles are gone; an old config with
402
+ profile keys loads with one warning and cleans itself on the next
403
+ save.
404
+ - **The no-model dead end offers a hand.** At a real terminal, the
405
+ no-model error now ends with `run setup now? [Y/n]` - accept, walk the
406
+ same setup flow, and it closes with "saved - rerun your command".
407
+ Scripts and CI see byte-identical output to before (the offer is
408
+ TTY-gated), and the exit code stays honest.
409
+
410
+ ### Getting it and keeping it current
411
+ - **One-line install on every platform.**
412
+ `curl -LsSf https://prabal-rje.github.io/smartpipe/install.sh | sh`
413
+ (macOS/Linux) and the `install.ps1` analog for Windows PowerShell, both
414
+ published at the docs-site root. The script uses Homebrew when present,
415
+ otherwise bootstraps uv and runs `uv tool install smartpipe-cli`;
416
+ `SMARTPIPE_VERSION` pins a version; it ends with a loud
417
+ `smartpipe --version` verify. brew/uv/pipx/pip remain as explicit
418
+ alternatives.
419
+ - **The installers survive the real world.** Rerunning the one-liner
420
+ upgrades in place instead of erroring (brew-, uv-, and
421
+ otherwise-managed installs each get the right move); the uv bootstrap
422
+ falls back to `wget` when `curl` is missing; Alpine/musl systems get
423
+ a wheels warning before anything installs; Rosetta-translated macOS
424
+ shells get an arch hint; GitHub Actions runners get `~/.local/bin`
425
+ appended to `GITHUB_PATH`. Footguns adopted from studying opencode's
426
+ installer. `install.sh` stays readable POSIX sh at 96 lines.
427
+ - **`smartpipe update`.** Detects how smartpipe was installed (homebrew,
428
+ uv tool, pipx, or pip - fingerprinted from the executable path), shows
429
+ the exact upgrade command, asks consent (`--yes` skips), runs it, and
430
+ reports honestly. Unrecognized installs get the per-channel commands
431
+ instead of a guess.
432
+ - **A calm update notice.** At most once a day smartpipe checks PyPI in a
433
+ background thread (2 s cap, silent on any failure) and - on a later
434
+ run, at a terminal, never in CI, never on stdout - prints one dim line:
435
+ `note: smartpipe X.Y.Z is available (you have A.B.C) - run: smartpipe
436
+ update`. Rc users aren't nagged about older stables. Off switches:
437
+ `SMARTPIPE_NO_UPDATE_CHECK=1` or `smartpipe config update-check off`.
438
+ The welcome screen's utility list now includes `update`.
439
+
440
+ ### Docs: a shape, not a pile
441
+ - New Learn track (`docs/learn/1…6`), `concepts/the-item.md` (the five
442
+ laws), `concepts/feeding-smartpipe.md` (the ingestion chapter), nav
443
+ regrouped Learn/Verbs/Concepts/Cookbook/Reference, index as mode-router,
444
+ every example reconciled to the new syntax with outputs from tests, qa/
445
+ flows extended (a live walk of which caught and fixed a real write
446
+ round-trip bug).
447
+
448
+ ## [1.3.1] — 2026-07-08
449
+
450
+ ### Fixed
451
+ - **PyPI no longer advertises phantom extras.** 1.3.0 kept the old extra
452
+ names (`[files]`, `[video]`, …) as empty compat aliases - but nothing was
453
+ ever published under the old name, so they protected nobody while the
454
+ PyPI sidebar listed six extras that contradict the everything-in-the-box
455
+ install story. The optional-dependencies table is gone entirely; pip
456
+ warns on an unknown extra and installs the complete package regardless.
457
+ Keywords now carry the multimodal story (pdf, audio, video, embeddings).
458
+
8
459
  ## [1.3.0] — 2026-07-07
9
460
 
10
461
  Installs from PyPI as **`smartpipe-cli`** (the plain name was too close to
@@ -26,9 +477,9 @@ that degrade per-item with the provider's real reason quoted.
26
477
  (PDF/DOCX/PPTX/XLSX/HTML/EPUB), video (bundled static ffmpeg), and chart
27
478
  `--save` all ship in the core install now, joining D44's whisper and local
28
479
  embeddings. One `pip install smartpipe-cli` is the entire multimodal surface.
29
- The old extra names (`[files]`, `[video]`, `[charts]`, `[anthropic]`,
30
- `[audio]`, `[all]`) remain as empty aliases so historical commands keep
31
- working. `doctor`'s extras row now verifies the bundled components and
480
+ The old extra names briefly remained as empty aliases (removed for real
481
+ in 1.3.1 - nothing was ever published under the old name, so they only
482
+ advertised a false install story). `doctor`'s extras row now verifies the bundled components and
32
483
  FAILS on a broken install instead of suggesting installs.
33
484
  - **The gemini profile's default chat model is `gemini-3.1-flash-lite` (D45).**
34
485
  Verified against the live catalog (GA, not a preview) and through the
@@ -344,6 +795,10 @@ estimated dollars.
344
795
  live-caught). `doctor` now closes with a bold yellow pointer at `--probe`.
345
796
  Also fixed live: streaming `embed` emitted the pre-conversion item text
346
797
  (empty for media), so records now carry the text the vector actually means.
798
+ And the streaming path (piped stdin) skipped the native media route
799
+ entirely - image-only items caption-pivoted even on jina-clip while the
800
+ finite-corpus branch embedded pixels. Both branches now share one router
801
+ (live-verified: `dims: 1024` from jina-clip-v2 on a piped image).
347
802
  - **Gemini watches video natively (D34).** Gemini chat moved to Google's
348
803
  native `:generateContent` wire — the only wired endpoint with video input.
349
804
  `map "what happens?" --in demo.mp4 --model gemini-2.5-flash` sends the
@@ -7,5 +7,5 @@ authors:
7
7
  given-names: Prabal
8
8
  repository-code: "https://github.com/prabal-rje/smartpipe"
9
9
  license: Apache-2.0
10
- version: 1.3.0
11
- date-released: '2026-07-07'
10
+ version: 1.4.0
11
+ date-released: '2026-07-08'
@@ -9,7 +9,7 @@ Requires [uv](https://docs.astral.sh/uv/) and Python ≥ 3.11 (uv can fetch one
9
9
 
10
10
  ```console
11
11
  $ git clone https://github.com/prabal-rje/smartpipe && cd smartpipe
12
- $ uv sync --all-extras # creates .venv with dev + optional deps
12
+ $ uv sync --all-extras # creates .venv with the project and dev tools
13
13
  $ uv run smartpipe # welcome screen = working install
14
14
  ```
15
15
 
@@ -44,14 +44,33 @@ Optional but recommended: `uv run pre-commit install` wires ruff into your commi
44
44
 
45
45
  Release ritual: [RELEASING.md](RELEASING.md) · upkeep: [MAINTENANCE.md](MAINTENANCE.md).
46
46
 
47
+ ## Docs search (Algolia DocSearch)
48
+
49
+ The site is pre-wired for [DocSearch](https://docsearch.algolia.com/) but ships
50
+ with it OFF: `extra.algolia` in `mkdocs.yml` holds three empty strings, and
51
+ while any of them is empty `overrides/main.html` renders nothing extra -
52
+ mkdocs-material's built-in search keeps working. To activate once the
53
+ DocSearch application is approved:
54
+
55
+ 1. Put the credentials Algolia sends into `mkdocs.yml` → `extra.algolia`
56
+ (`app_id`, `index_name`, and the **search-only** public `api_key` - that
57
+ key is safe to commit; never the admin key).
58
+ 2. `make docs-check` - the strict build must stay green.
59
+ 3. Open the built site and confirm the DocSearch button replaced the
60
+ built-in search box (the override hides `.md-search` and mounts
61
+ docsearch.js v3 in the header).
62
+
63
+ Reverting to built-in search is emptying the three values again.
64
+
47
65
  ## New dependencies
48
66
 
49
- Core install weight is a feature: the runtime dependency list is `click`, `httpx`,
50
- `jsonschema`, `tomli-w` a snapshot test guards it. Anything heavier goes behind an
51
- optional extra, and heavy imports stay function-local (startup time is budgeted).
67
+ Core install weight is a feature, but D46 deliberately ships the complete
68
+ multimodal surface in core: there are no optional extras. The frozen dependency
69
+ snapshot makes every direct or transitive addition an explicit review decision.
70
+ Heavy imports stay function-local so startup remains budgeted.
52
71
 
53
72
  **New heavy import? Function-local or justify.** `--help` must never import
54
- `httpx`, `jsonschema`, `anthropic`, or `markitdown` —
73
+ `httpx`, `jsonschema`, `anthropic`, `markitdown`, or `rich` —
55
74
  `tests/test_startup_imports.py` is the enforcement (it runs `-X importtime` and
56
75
  fails on any banned module). `make startup` gives an advisory wall-clock number;
57
76
  the import test is the deterministic gate.