stream_weaver 0.3.0

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 (381) hide show
  1. checksums.yaml +7 -0
  2. data/.beads/.gitignore +77 -0
  3. data/.beads/README.md +81 -0
  4. data/.beads/config.yaml +54 -0
  5. data/.beads/metadata.json +7 -0
  6. data/.rspec +3 -0
  7. data/AGENTS.md +91 -0
  8. data/CHANGELOG.md +294 -0
  9. data/CLAUDE.md +67 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +565 -0
  12. data/Rakefile +13 -0
  13. data/assets/streamweaver-hero.jpg +0 -0
  14. data/bench/baselines/ledger.rb +58 -0
  15. data/bench/baselines/warroom.rb +51 -0
  16. data/bench/fixtures/ledger.rb +76 -0
  17. data/bench/fixtures/warroom.rb +60 -0
  18. data/bench/results/6daf8b8.md +102 -0
  19. data/bench/results/c8d749b.md +102 -0
  20. data/bench/results/eb06ab9.md +102 -0
  21. data/bench/run.rb +151 -0
  22. data/bench/support.rb +84 -0
  23. data/copy_this/dto_run_sample_run_7631.html +220 -0
  24. data/docs/SERVICE_MODE.md +302 -0
  25. data/docs/architecture/how_streamweaver_works.md +772 -0
  26. data/docs/blog/2026-01-16-streamweaver-introduction.md +515 -0
  27. data/docs/bug-2026-08-31-canvas-bridge-socket-collision.md +83 -0
  28. data/docs/canvas-ipc-session-summary.md +127 -0
  29. data/docs/canvas-panel-workflow.md +172 -0
  30. data/docs/canvas-read.md +147 -0
  31. data/docs/canvas-roadmap.md +275 -0
  32. data/docs/case-studies/2026-09-03-didx-canvas-read-shelf.md +147 -0
  33. data/docs/claude-code-companion-skill-spec.md +567 -0
  34. data/docs/components_reference.md +1223 -0
  35. data/docs/crud-patterns.md +265 -0
  36. data/docs/endpoints.md +122 -0
  37. data/docs/for_llms.md +1 -0
  38. data/docs/form-patterns.md +165 -0
  39. data/docs/frontend-only.md +169 -0
  40. data/docs/html-artifact-audit.md +238 -0
  41. data/docs/ideas/2025-01-01-as-a-service.md +203 -0
  42. data/docs/ideas/2026-01-16-charm-tui-exploration.md +542 -0
  43. data/docs/ideas/2026-08-27-static-doc-shelf-export.md +153 -0
  44. data/docs/ideas/dhh-review-future-refactors.md +142 -0
  45. data/docs/opal-jamstack.md +47 -0
  46. data/docs/opal-npm-direction.md +184 -0
  47. data/docs/opal-spike-findings.md +194 -0
  48. data/docs/plans/2025-12-16-form-blocks-design.md +124 -0
  49. data/docs/plans/2025-12-30-examples-browser-design.md +152 -0
  50. data/docs/plans/2026-01-02-charts-design.md +288 -0
  51. data/docs/plans/2026-01-10-canvas-ipc-design.md +247 -0
  52. data/docs/plans/2026-01-19-cabinet-control-components.md +176 -0
  53. data/docs/plans/2026-01-26-gem-release-and-panel.md +140 -0
  54. data/docs/plans/canvas-claude-project-design.md +238 -0
  55. data/docs/plans/canvas-doc-location-and-discovery.md +32 -0
  56. data/docs/plans/org-doc-preview-surfaces.md +293 -0
  57. data/docs/plans/shadcn-polish-plan.md +417 -0
  58. data/docs/porting-artifacts.md +252 -0
  59. data/docs/reference/agent-skills-comparison.md +369 -0
  60. data/docs/reference/travel-state-prd.artifact.html +780 -0
  61. data/docs/research/2026-08-17-hotwire-alike-landscape.md +268 -0
  62. data/docs/research/2026-08-17-hotwire-concept-map.md +404 -0
  63. data/docs/research/2026-08-22-lazy-fragments-trigger-decision.md +246 -0
  64. data/docs/research/2026-08-22-learnhotwire-syllabus-coverage.md +239 -0
  65. data/docs/research/frontend-only-matrix.md +278 -0
  66. data/docs/research/streamweaver-way-spike-findings.md +529 -0
  67. data/docs/resource-dsl.md +342 -0
  68. data/docs/routing.md +302 -0
  69. data/docs/ruby-ui-comparison.md +319 -0
  70. data/docs/shared-dsl-fragments.md +356 -0
  71. data/docs/streamweaver-for-ai-agents.md +401 -0
  72. data/docs/streamweaver-frontend-vision.md +123 -0
  73. data/docs/streamweaver_canvas/glimmer_initial_final_layer.rb +77 -0
  74. data/docs/streamweaver_canvas/save_example.rb +9 -0
  75. data/docs/templates.md +213 -0
  76. data/docs/testing.md +155 -0
  77. data/docs/theming-hooks.md +281 -0
  78. data/docs/tutorials/the-streamweaver-way.md +882 -0
  79. data/docs/university/capability-inventory.md +137 -0
  80. data/docs/university/dependency-survey.md +114 -0
  81. data/docs/university/design-spec.md +217 -0
  82. data/docs/university/mockups/code-block-doc-theme-dark.png +0 -0
  83. data/docs/university/mockups/code-block-doc-theme-light.png +0 -0
  84. data/docs/university/mockups/course-list-dark.png +0 -0
  85. data/docs/university/mockups/course-list-light.png +0 -0
  86. data/docs/university/mockups/course_canvas_mockup.rb +741 -0
  87. data/docs/university/mockups/step-screen-dark.png +0 -0
  88. data/docs/university/mockups/step-screen-light.png +0 -0
  89. data/docs/university/roadmap.md +72 -0
  90. data/docs/university/send-to-coworker.md +77 -0
  91. data/docs/university/worker-session-mining.md +109 -0
  92. data/docs/visual/browser-rendering-spike.md +173 -0
  93. data/docs/visual/builder-visual-plan-analysis.md +378 -0
  94. data/docs/visual/sw-plan-format-exploration.md +511 -0
  95. data/docs/visual/sw-plan-rendering-deep-dive.md +453 -0
  96. data/docs/visual-skills/PROGRESS.md +60 -0
  97. data/docs/visual-skills/SESSION-CONTEXT.md +207 -0
  98. data/docs/visual-skills/analysis/components.md +317 -0
  99. data/docs/visual-skills/analysis/overlap.md +360 -0
  100. data/docs/visual-skills/analysis/pi-design-deck.md +1102 -0
  101. data/docs/visual-skills/analysis/streamweaver-inventory.md +93 -0
  102. data/docs/visual-skills/analysis/unified-specs.feature +1003 -0
  103. data/docs/visual-skills/analysis/visual-explainer.md +964 -0
  104. data/docs/visual-skills/blog/blog-series-outline.md +39 -0
  105. data/docs/visual-skills/blog/token-efficiency.md +73 -0
  106. data/docs/visual-skills/design/architecture.md +1725 -0
  107. data/docs/visual-skills/design/codex-review.md +340 -0
  108. data/docs/visual-skills/design/dhh-review.md +209 -0
  109. data/docs/visual-skills/design/evolution.md +100 -0
  110. data/docs/visual-skills/design/gemini-review.md +55 -0
  111. data/docs/visual-skills/design/review-synthesis.md +149 -0
  112. data/docs/visual-skills/implementation/STATE.md +22 -0
  113. data/docs/visual-skills/implementation/plan.md +347 -0
  114. data/docs/visual-skills/implementation/spike-findings.md +237 -0
  115. data/docs/visual-skills/implementation/tasks.md +702 -0
  116. data/docs/visual-skills/lessons-learned/process.md +145 -0
  117. data/examples/README.md +96 -0
  118. data/examples/advanced/all_components.rb +177 -0
  119. data/examples/advanced/examples_browser.rb +394 -0
  120. data/examples/advanced/teachables_browser.rb +261 -0
  121. data/examples/advanced/theme_tweaker.rb +366 -0
  122. data/examples/advanced/tutorial.rb +1528 -0
  123. data/examples/agentic/agentic_form.rb +30 -0
  124. data/examples/agentic/agentic_form_autoclose.rb +30 -0
  125. data/examples/agentic/cultivation_tracker.rb +69 -0
  126. data/examples/basic/hello_world.rb +22 -0
  127. data/examples/basic/opal_tabs_table.rb +44 -0
  128. data/examples/basic/todo_list.rb +39 -0
  129. data/examples/button_loading_test.rb +36 -0
  130. data/examples/canvas/mermaid_canvas_demo.sh +151 -0
  131. data/examples/charts/bar_chart_demo.rb +57 -0
  132. data/examples/charts/line_chart_demo.rb +73 -0
  133. data/examples/charts/pie_area_demo.rb +87 -0
  134. data/examples/charts/stacked_bar_chart_demo.rb +69 -0
  135. data/examples/claude_code/README.md +85 -0
  136. data/examples/claude_code/codebreaker/.claude/commands/infiltrate.md +632 -0
  137. data/examples/claude_code/codebreaker/.claude/settings.json +11 -0
  138. data/examples/claude_code/codebreaker/.claude/settings.local.json +17 -0
  139. data/examples/claude_code/codebreaker/.claude/skills/infiltrate.md +0 -0
  140. data/examples/claude_code/codebreaker/README.md +213 -0
  141. data/examples/claude_code/tutorial/.claude/commands/learn.md +453 -0
  142. data/examples/claude_code/tutorial/README.md +102 -0
  143. data/examples/claude_code/verification_flow/.claude/commands/verify.md +171 -0
  144. data/examples/claude_code/verification_flow/README.md +126 -0
  145. data/examples/components/annotated_code_demo.rb +54 -0
  146. data/examples/components/callout_demo.rb +33 -0
  147. data/examples/components/checkbox_group_demo.rb +46 -0
  148. data/examples/components/design_review.css +468 -0
  149. data/examples/components/design_review_demo.rb +44 -0
  150. data/examples/components/design_review_dsl.rb +300 -0
  151. data/examples/components/diff_block_demo.rb +112 -0
  152. data/examples/components/events_demo.rb +184 -0
  153. data/examples/components/form_demo.rb +62 -0
  154. data/examples/components/lesson_demo.rb +53 -0
  155. data/examples/components/markdown_demo.rb +110 -0
  156. data/examples/components/mermaid_demo.rb +166 -0
  157. data/examples/components/pareto_set.rb +64 -0
  158. data/examples/components/prd_demo.rb +21 -0
  159. data/examples/components/prd_dsl.rb +385 -0
  160. data/examples/components/quiz_demo.rb +47 -0
  161. data/examples/components/run_viewer_demo.rb +100 -0
  162. data/examples/components/score_and_collapsible_demo.rb +82 -0
  163. data/examples/components/select_stale_value_smoke_test.rb +39 -0
  164. data/examples/components/table_demo.rb +247 -0
  165. data/examples/components/timer_with_state_demo.rb +58 -0
  166. data/examples/components/todo_due_dates.rb +63 -0
  167. data/examples/components/uat_gaps_demo.rb +112 -0
  168. data/examples/dashboard/feed_simulator.rb +60 -0
  169. data/examples/dashboard/live_dashboard.rb +80 -0
  170. data/examples/dashboard_components.rb +108 -0
  171. data/examples/deferred_fragments_demo.rb +62 -0
  172. data/examples/generate_more_spike/README.md +63 -0
  173. data/examples/generate_more_spike/app.rb +441 -0
  174. data/examples/git_health.sh +401 -0
  175. data/examples/layout/layout_components_demo.rb +174 -0
  176. data/examples/layout/modal_demo.rb +215 -0
  177. data/examples/layout/navigation_demo.rb +227 -0
  178. data/examples/layout/route_tabs_demo.rb +52 -0
  179. data/examples/layout/routing_demo.rb +52 -0
  180. data/examples/layout/scroll_box_demo.rb +154 -0
  181. data/examples/lazy_fragments_demo.rb +151 -0
  182. data/examples/my_todos/README.md +29 -0
  183. data/examples/my_todos/my_todos.rb +312 -0
  184. data/examples/my_todos/store.rb +86 -0
  185. data/examples/opal/reactive_demo.rb +62 -0
  186. data/examples/opal/scenarios/s1_counter.rb +15 -0
  187. data/examples/opal/scenarios/s2_search_filter.rb +17 -0
  188. data/examples/opal/scenarios/s3_sibling_tabs.rb +25 -0
  189. data/examples/opal/scenarios/s4_shopping_cart.rb +34 -0
  190. data/examples/opal/scenarios/s5_watch.rb +39 -0
  191. data/examples/opal/scenarios/s6_on_start.rb +20 -0
  192. data/examples/opal/scenarios/s7_wizard.rb +33 -0
  193. data/examples/opal/scenarios/s8_loan_calculator.rb +21 -0
  194. data/examples/opal/scenarios/s9_dashboard.rb +27 -0
  195. data/examples/operations_dashboard_demo.rb +167 -0
  196. data/examples/panel_demo.sh +447 -0
  197. data/examples/parity/assets/tyrion_slice.css +86 -0
  198. data/examples/parity/rivet_people_slice.rb +182 -0
  199. data/examples/parity/tyrion_components.css +777 -0
  200. data/examples/parity/tyrion_warroom_components.rb +414 -0
  201. data/examples/parity/tyrion_warroom_slice.rb +549 -0
  202. data/examples/puma_dev/README.md +124 -0
  203. data/examples/puma_dev/config.ru +34 -0
  204. data/examples/puma_dev/standalone_app.rb +34 -0
  205. data/examples/scaffolding/blog.rb +49 -0
  206. data/examples/scaffolding/utf_lite.rb +105 -0
  207. data/examples/styling/feedback_demo.rb +229 -0
  208. data/examples/styling/style_showcase.rb +172 -0
  209. data/examples/styling/theme_demo.rb +508 -0
  210. data/examples/timer_health_checker.rb +111 -0
  211. data/examples/timer_showcase.rb +131 -0
  212. data/examples/tutorials/render_markdown.rb +112 -0
  213. data/examples/tutorials/streamweaver_way_tutorial.rb +44 -0
  214. data/examples/tutorials/tutorial_content.rb +1082 -0
  215. data/examples/visual_skills/design_deck_demo.rb +314 -0
  216. data/examples/visual_skills/explainer_demo.rb +499 -0
  217. data/exe/streamweaver +9 -0
  218. data/gsd/ROADMAP-1.0.md +167 -0
  219. data/gsd/STATE.md +13 -0
  220. data/gsd/research/market-positioning-research.md +139 -0
  221. data/gsd/research/production-patterns-research.md +270 -0
  222. data/gsd/research/repo-audit-1.0.md +274 -0
  223. data/lib/stream_weaver/action_token.rb +58 -0
  224. data/lib/stream_weaver/adapter/alpinejs.rb +8249 -0
  225. data/lib/stream_weaver/adapter/base.rb +591 -0
  226. data/lib/stream_weaver/adapter/opal.rb +334 -0
  227. data/lib/stream_weaver/adapter/static.rb +1118 -0
  228. data/lib/stream_weaver/admin.rb +176 -0
  229. data/lib/stream_weaver/app.rb +1821 -0
  230. data/lib/stream_weaver/assets/js/sw-copy.js +50 -0
  231. data/lib/stream_weaver/assets/js/sw-heredoc-rewrite.js +68 -0
  232. data/lib/stream_weaver/assets/js/sw-keyboard.js +165 -0
  233. data/lib/stream_weaver/assets/js/sw-mermaid-zoom.js +621 -0
  234. data/lib/stream_weaver/assets/js/sw-route-tabs.js +53 -0
  235. data/lib/stream_weaver/assets/js/sw-sidebar-toc.js +116 -0
  236. data/lib/stream_weaver/assets/js/sw-slide-nav.js +103 -0
  237. data/lib/stream_weaver/canvas/bridge.rb +239 -0
  238. data/lib/stream_weaver/canvas/bridge_server.rb +646 -0
  239. data/lib/stream_weaver/canvas/client.rb +298 -0
  240. data/lib/stream_weaver/canvas/doc_roots.rb +233 -0
  241. data/lib/stream_weaver/canvas/doc_store.rb +252 -0
  242. data/lib/stream_weaver/canvas/gist_publisher.rb +264 -0
  243. data/lib/stream_weaver/canvas/gist_save_handler.rb +89 -0
  244. data/lib/stream_weaver/canvas/gist_store.rb +135 -0
  245. data/lib/stream_weaver/canvas/helpers.rb +109 -0
  246. data/lib/stream_weaver/canvas/history.rb +90 -0
  247. data/lib/stream_weaver/canvas/protocol.rb +86 -0
  248. data/lib/stream_weaver/canvas/reader.rb +853 -0
  249. data/lib/stream_weaver/canvas/save_doc_widget.rb +457 -0
  250. data/lib/stream_weaver/canvas/scroll_top_hint.rb +21 -0
  251. data/lib/stream_weaver/canvas/session.rb +132 -0
  252. data/lib/stream_weaver/cli.rb +3235 -0
  253. data/lib/stream_weaver/component_assets.rb +70 -0
  254. data/lib/stream_weaver/component_registry.rb +67 -0
  255. data/lib/stream_weaver/component_renderer.rb +48 -0
  256. data/lib/stream_weaver/components/annotated_code.rb +53 -0
  257. data/lib/stream_weaver/components/api_endpoint.rb +42 -0
  258. data/lib/stream_weaver/components/callout.rb +59 -0
  259. data/lib/stream_weaver/components/chart.rb +84 -0
  260. data/lib/stream_weaver/components/code_block.rb +77 -0
  261. data/lib/stream_weaver/components/comparison.rb +39 -0
  262. data/lib/stream_weaver/components/decision.rb +38 -0
  263. data/lib/stream_weaver/components/deck/close_overlay.rb +84 -0
  264. data/lib/stream_weaver/components/deck/confirmation_bar.rb +60 -0
  265. data/lib/stream_weaver/components/deck/deck_option.rb +61 -0
  266. data/lib/stream_weaver/components/deck/deck_slide.rb +77 -0
  267. data/lib/stream_weaver/components/deck/deck_state.rb +469 -0
  268. data/lib/stream_weaver/components/deck/deck_summary.rb +73 -0
  269. data/lib/stream_weaver/components/deck/design_deck.rb +60 -0
  270. data/lib/stream_weaver/components/deck/generate_more_controls.rb +84 -0
  271. data/lib/stream_weaver/components/deck/model_selector.rb +84 -0
  272. data/lib/stream_weaver/components/deck/skeleton_placeholder.rb +36 -0
  273. data/lib/stream_weaver/components/diff_block.rb +125 -0
  274. data/lib/stream_weaver/components/doc_header.rb +57 -0
  275. data/lib/stream_weaver/components/image_block.rb +70 -0
  276. data/lib/stream_weaver/components/implementation_map.rb +33 -0
  277. data/lib/stream_weaver/components/keyboard_shortcuts.rb +94 -0
  278. data/lib/stream_weaver/components/kpi_dashboard.rb +78 -0
  279. data/lib/stream_weaver/components/mermaid.rb +79 -0
  280. data/lib/stream_weaver/components/pipeline.rb +63 -0
  281. data/lib/stream_weaver/components/sidebar_toc.rb +46 -0
  282. data/lib/stream_weaver/components/slide_container.rb +141 -0
  283. data/lib/stream_weaver/components/timeline_event.rb +58 -0
  284. data/lib/stream_weaver/components/wireframe.rb +29 -0
  285. data/lib/stream_weaver/components/wireframe_block.rb +34 -0
  286. data/lib/stream_weaver/components.rb +2711 -0
  287. data/lib/stream_weaver/css.rb +230 -0
  288. data/lib/stream_weaver/dev_fallback_overlay.rb +61 -0
  289. data/lib/stream_weaver/display_dsl.rb +1004 -0
  290. data/lib/stream_weaver/export/html_exporter.rb +478 -0
  291. data/lib/stream_weaver/feed.rb +34 -0
  292. data/lib/stream_weaver/feed_builder.rb +31 -0
  293. data/lib/stream_weaver/fonts.rb +33 -0
  294. data/lib/stream_weaver/interaction_runner.rb +487 -0
  295. data/lib/stream_weaver/iterm.rb +460 -0
  296. data/lib/stream_weaver/layout_registry.rb +92 -0
  297. data/lib/stream_weaver/opal/bridge.rb +52 -0
  298. data/lib/stream_weaver/opal/builder.rb +193 -0
  299. data/lib/stream_weaver/opal/env.rb +29 -0
  300. data/lib/stream_weaver/opal/reactive_state.rb +75 -0
  301. data/lib/stream_weaver/opal/regexp_anchor_patch.rb +62 -0
  302. data/lib/stream_weaver/opal/renderer.rb +77 -0
  303. data/lib/stream_weaver/opal/runtime.rb +250 -0
  304. data/lib/stream_weaver/opal/shell.rb +145 -0
  305. data/lib/stream_weaver/opal/string_bridge.rb +50 -0
  306. data/lib/stream_weaver/opal/stubs/diff.min.js +1 -0
  307. data/lib/stream_weaver/opal/stubs/digest.rb +15 -0
  308. data/lib/stream_weaver/opal/stubs/marked.umd.js +79 -0
  309. data/lib/stream_weaver/opal/stubs/md5.rb +3 -0
  310. data/lib/stream_weaver/opal/stubs/morphdom.min.js +775 -0
  311. data/lib/stream_weaver/opal/stubs/prism-tomorrow.min.css +1 -0
  312. data/lib/stream_weaver/opal/stubs/prism.min.js +1967 -0
  313. data/lib/stream_weaver/opal_entry.rb +136 -0
  314. data/lib/stream_weaver/org/inline.rb +95 -0
  315. data/lib/stream_weaver/org/reader.rb +561 -0
  316. data/lib/stream_weaver/org/recording_context.rb +86 -0
  317. data/lib/stream_weaver/org/source_splitter.rb +63 -0
  318. data/lib/stream_weaver/org/writer.rb +300 -0
  319. data/lib/stream_weaver/page_shell.rb +530 -0
  320. data/lib/stream_weaver/portfile.rb +79 -0
  321. data/lib/stream_weaver/pushable.rb +42 -0
  322. data/lib/stream_weaver/resource/default_views.rb +111 -0
  323. data/lib/stream_weaver/resource/field_input.rb +25 -0
  324. data/lib/stream_weaver/resource/state_keys.rb +16 -0
  325. data/lib/stream_weaver/resource/store.rb +18 -0
  326. data/lib/stream_weaver/resource.rb +104 -0
  327. data/lib/stream_weaver/server.rb +1471 -0
  328. data/lib/stream_weaver/service.rb +1240 -0
  329. data/lib/stream_weaver/service_client.rb +104 -0
  330. data/lib/stream_weaver/session_store.rb +186 -0
  331. data/lib/stream_weaver/skills/streamweaver-canvas-safe/SKILL.md +66 -0
  332. data/lib/stream_weaver/skills/streamweaver-canvas-safe/examples/canvas-safe-showcase.rb +98 -0
  333. data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/actions-and-buttons.md +47 -0
  334. data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/charts-and-diagrams.md +38 -0
  335. data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/deck.md +32 -0
  336. data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/inputs-and-forms.md +65 -0
  337. data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/tabs-and-navigation.md +53 -0
  338. data/lib/stream_weaver/skills/streamweaver-doc-builder/SKILL.md +298 -0
  339. data/lib/stream_weaver/skills/streamweaver-visual-companion/SKILL.md +130 -0
  340. data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.css +468 -0
  341. data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.rb +39 -0
  342. data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example_dsl.rb +300 -0
  343. data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example.rb +24 -0
  344. data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example_dsl.rb +385 -0
  345. data/lib/stream_weaver/skills/streamweaver-visual-companion/references/checkpoints-and-forms.md +28 -0
  346. data/lib/stream_weaver/skills/streamweaver-visual-companion/references/cleanup-and-panel.md +44 -0
  347. data/lib/stream_weaver/skills/streamweaver-visual-companion/references/example-gallery.md +8 -0
  348. data/lib/stream_weaver/skills/streamweaver-visual-companion/references/persistence.md +58 -0
  349. data/lib/stream_weaver/skills/streamweaver-way/SKILL.md +396 -0
  350. data/lib/stream_weaver/skills/visual-plan/SKILL.md +201 -0
  351. data/lib/stream_weaver/skills/visual-recap/SKILL.md +244 -0
  352. data/lib/stream_weaver/streamer.rb +63 -0
  353. data/lib/stream_weaver/templates/choices.rb +149 -0
  354. data/lib/stream_weaver/templates/code.rb +157 -0
  355. data/lib/stream_weaver/templates/confirm.rb +110 -0
  356. data/lib/stream_weaver/templates/diff.rb +195 -0
  357. data/lib/stream_weaver/templates/info.rb +142 -0
  358. data/lib/stream_weaver/templates/table.rb +169 -0
  359. data/lib/stream_weaver/templates/wizard.rb +271 -0
  360. data/lib/stream_weaver/theme/auto_mode.rb +116 -0
  361. data/lib/stream_weaver/theme/presets.rb +555 -0
  362. data/lib/stream_weaver/theme.rb +639 -0
  363. data/lib/stream_weaver/university/canvas.rb +924 -0
  364. data/lib/stream_weaver/university/course.rb +699 -0
  365. data/lib/stream_weaver/university/demos/counter.rb +33 -0
  366. data/lib/stream_weaver/university/demos/dashboard.rb +147 -0
  367. data/lib/stream_weaver/university/demos/decision_form.rb +143 -0
  368. data/lib/stream_weaver/university/demos.rb +50 -0
  369. data/lib/stream_weaver/university/listener.rb +467 -0
  370. data/lib/stream_weaver/university/progress.rb +201 -0
  371. data/lib/stream_weaver/university/runner.rb +138 -0
  372. data/lib/stream_weaver/university/scripts/growing_doc.rb +609 -0
  373. data/lib/stream_weaver/university/scripts/growing_doc_state.rb +91 -0
  374. data/lib/stream_weaver/utils.rb +31 -0
  375. data/lib/stream_weaver/version.rb +5 -0
  376. data/lib/stream_weaver/views/canvas/reader_layout.erb +800 -0
  377. data/lib/stream_weaver/views.rb +3940 -0
  378. data/lib/stream_weaver.rb +122 -0
  379. data/llms.txt +1269 -0
  380. data/sig/stream_weaver.rbs +4 -0
  381. metadata +598 -0
@@ -0,0 +1,511 @@
1
+ # StreamWeaver Plan Format Exploration: Ruby DSL vs MDX vs Org-mode
2
+
3
+ **Date:** 2026-06-17
4
+ **Status:** Exploratory design — not implemented
5
+ **TL;DR:** Org-mode wins for checked-in plan files. Ruby DSL wins for live canvas. The formats serve different moments and don't need to compete.
6
+
7
+ ---
8
+
9
+ ## The Problem
10
+
11
+ Builder's visual-plan uses MDX (Markdown + JSX components). It's clever, but
12
+ they themselves acknowledge a tension: **MDX looks ugly when read raw**. Custom
13
+ components like `<ImplementationMap files={[{path: "...", note: "..."}]} />` are
14
+ not human-readable without the renderer. The whole point of a checked-in plan
15
+ file is that a human (or Claude) can read it cold without spinning up a server.
16
+
17
+ StreamWeaver already has a live Ruby DSL for the canvas. But a canvas-push DSL
18
+ as a committed artifact is also awkward — it's executable Ruby, not prose.
19
+
20
+ So three candidates emerge:
21
+
22
+ 1. **MDX** — what Builder does (Markdown + JSX props)
23
+ 2. **Org-mode** — structured plaintext with native extensibility
24
+ 3. **"SW-Ruby"** — StreamWeaver DSL embedded in a plan file format
25
+
26
+ ---
27
+
28
+ ## What We Proved in 30 Minutes
29
+
30
+ `org-ruby 0.9.12` is **already installed** in the StreamWeaver gem environment.
31
+ After a quick spike, the org-ruby parser:
32
+
33
+ - Parses `#+TITLE:`, `#+DATE:`, `#+SW_VERSION:` as in-buffer settings cleanly
34
+ - Exposes `:PROPERTIES:` drawers per-headline with full key-value access
35
+ - Headline + property combo maps directly to StreamWeaver component dispatch
36
+ - `#+BEGIN_SRC ruby` blocks are code-highlighted already
37
+ - Tables parse as table objects
38
+
39
+ This isn't theoretical. A working prototype parser is ~60 lines of Ruby.
40
+
41
+ ---
42
+
43
+ ## Format Comparison: Same Plan in All Three
44
+
45
+ ### The Plan: Guest Auth Flow
46
+
47
+ A plan for adding guest checkout to a Rails app.
48
+ We want to show: prose, file map, a decision, a mermaid diagram, annotated code,
49
+ and a risk callout.
50
+
51
+ ---
52
+
53
+ ### Option A: MDX (Builder's way)
54
+
55
+ ```mdx
56
+ ---
57
+ title: "Guest Auth Flow"
58
+ brief: "Enable checkout without account creation."
59
+ version: 2
60
+ planId: "plan_84f748..."
61
+ source: "agent-native-plan"
62
+ ---
63
+
64
+ <RichText id="b1">
65
+ ### Overview
66
+
67
+ Enable users to proceed through checkout without creating an account.
68
+ Currently all paths require registration, causing ~30% mobile drop-off.
69
+ </RichText>
70
+
71
+ <ImplementationMap
72
+ id="b2"
73
+ files={[
74
+ { path: "lib/auth/session.rb", note: "Add guest token issuer" },
75
+ { path: "app/routes/checkout.rb", note: "Branch on guest vs auth user" },
76
+ { path: "db/schema.rb", note: "Add guest_sessions table" },
77
+ ]}
78
+ />
79
+
80
+ <Decision
81
+ id="b3"
82
+ question={"How should guest sessions be stored?"}
83
+ options={[
84
+ { id: "o1", label: "JWT", detail: "Stateless, no DB lookup" },
85
+ { id: "o2", label: "Opaque token", detail: "Revocable, account merge later", recommended: true },
86
+ ]}
87
+ />
88
+
89
+ <Callout id="b4" tone="risk">
90
+ Guest sessions must expire. Proposed TTL: 24h — confirm with data team.
91
+ </Callout>
92
+ ```
93
+
94
+ **Raw readability:** ⚠️ Moderate. Prose sections are fine. Component props
95
+ are JSON-in-JSX — readable but verbose. The `files={[...]}` syntax is noise
96
+ that disappears in the renderer.
97
+
98
+ ---
99
+
100
+ ### Option B: Org-mode (proposed SW-Org format)
101
+
102
+ ```org
103
+ #+TITLE: Guest Auth Flow
104
+ #+DATE: 2026-06-17
105
+ #+BRIEF: Enable checkout without account creation.
106
+ #+SW_VERSION: 1
107
+
108
+ * Overview
109
+
110
+ Enable users to proceed through checkout without creating an account.
111
+ Currently all paths require registration, causing ~30% mobile drop-off.
112
+
113
+ * Implementation Map
114
+ :PROPERTIES:
115
+ :SW_COMPONENT: implementation_map
116
+ :END:
117
+
118
+ | lib/auth/session.rb | Add guest token issuer |
119
+ | app/routes/checkout.rb | Branch on guest vs auth user |
120
+ | db/schema.rb | Add guest_sessions table |
121
+
122
+ * Decision: Token Storage
123
+ :PROPERTIES:
124
+ :SW_COMPONENT: decision
125
+ :SW_RECOMMENDED: opaque
126
+ :END:
127
+
128
+ | jwt | Stateless, no DB lookup |
129
+ | opaque | Revocable, supports account merge later |
130
+
131
+ * Auth Flow Architecture
132
+ :PROPERTIES:
133
+ :SW_COMPONENT: diagram
134
+ :SW_DIAGRAM: mermaid
135
+ :END:
136
+
137
+ #+BEGIN_SRC mermaid
138
+ sequenceDiagram
139
+ User->>App: Request checkout
140
+ App->>Auth: Issue guest token
141
+ Auth-->>App: JWT (role: guest, TTL: 24h)
142
+ App-->>User: Checkout continues
143
+ #+END_SRC
144
+
145
+ * Issue Guest Token
146
+ :PROPERTIES:
147
+ :SW_COMPONENT: annotated_code
148
+ :SW_LANG: ruby
149
+ :END:
150
+
151
+ #+BEGIN_SRC ruby
152
+ def issue_guest_token(email)
153
+ JWT.encode({ sub: email, role: 'guest' }, SECRET, exp: 24.hours.from_now)
154
+ end
155
+ #+END_SRC
156
+
157
+ #+BEGIN_ANNOTATIONS
158
+ [1] Guest tokens use restricted scope — limits what APIs they can call
159
+ [2] 24h TTL matches cleanup job cadence on the data team's cron
160
+ #+END_ANNOTATIONS
161
+
162
+ * Risk: Session Expiry
163
+ :PROPERTIES:
164
+ :SW_COMPONENT: callout
165
+ :SW_TONE: risk
166
+ :END:
167
+
168
+ Guest sessions must expire to prevent unbounded DB growth.
169
+ Proposed TTL: 24h — needs confirmation from data team.
170
+ ```
171
+
172
+ **Raw readability:** ✅ Excellent. Every section reads as plain prose/table.
173
+ The `:PROPERTIES:` drawers are structured metadata that org-mode users understand
174
+ immediately. Tables are ASCII-legible. Code blocks are standard. Nothing requires
175
+ a renderer to understand.
176
+
177
+ ---
178
+
179
+ ### Option C: StreamWeaver Ruby DSL (canvas-push format)
180
+
181
+ ```ruby
182
+ # guest-auth-flow.sw.rb
183
+ # SW Plan: Guest Auth Flow
184
+ # Brief: Enable checkout without account creation.
185
+
186
+ theme_preset :technical
187
+
188
+ header2 "Guest Auth Flow"
189
+ md "Enable users to proceed through checkout without creating an account."
190
+
191
+ implementation_map files: [
192
+ { path: "lib/auth/session.rb", note: "Add guest token issuer" },
193
+ { path: "app/routes/checkout.rb", note: "Branch on guest vs auth user" },
194
+ { path: "db/schema.rb", note: "Add guest_sessions table" }
195
+ ]
196
+
197
+ decision question: "How should guest sessions be stored?" do
198
+ option "jwt", "Stateless, no DB lookup"
199
+ option "opaque", "Revocable, supports account merge later", recommended: true
200
+ end
201
+
202
+ mermaid do
203
+ <<~MERMAID
204
+ sequenceDiagram
205
+ User->>App: Request checkout
206
+ App->>Auth: Issue guest token
207
+ Auth-->>App: JWT (role: guest, TTL: 24h)
208
+ MERMAID
209
+ end
210
+
211
+ annotated_code language: :ruby, annotations: [
212
+ { line: 1, note: "Guest tokens use restricted scope" },
213
+ { line: 2, note: "24h TTL matches cleanup job cadence" }
214
+ ] do
215
+ <<~RUBY
216
+ def issue_guest_token(email)
217
+ JWT.encode({ sub: email, role: 'guest' }, SECRET, exp: 24.hours.from_now)
218
+ end
219
+ RUBY
220
+ end
221
+
222
+ callout :risk do
223
+ "Guest sessions must expire to prevent unbounded DB growth. TTL: 24h."
224
+ end
225
+ ```
226
+
227
+ **Raw readability:** ✅ Good for Ruby devs, readable for anyone. Clean method
228
+ names, block syntax is familiar. But it's executable — `require 'stream_weaver'`
229
+ and it runs. That's a feature AND a bug: nice for live push, weird for a
230
+ committed plan artifact.
231
+
232
+ ---
233
+
234
+ ## Side-by-Side Analysis
235
+
236
+ | Criterion | MDX | Org-mode | SW-Ruby DSL |
237
+ |---|---|---|---|
238
+ | **Raw readability** | ⚠️ Moderate | ✅ Excellent | ✅ Good |
239
+ | **LLM writability** | ✅ Easy | ✅ Easy | ✅ Easy |
240
+ | **GitHub renders nicely** | ❌ Shows JSX noise | ✅ Renders as plain text, tables intact | ⚠️ Syntax highlighted but not semantic |
241
+ | **Emacs native** | ❌ | ✅ Full org-mode tooling | ❌ |
242
+ | **VS Code** | ✅ MDX extension | ✅ org-mode extension | ✅ Ruby extension |
243
+ | **Structured metadata** | ✅ Frontmatter YAML | ✅ In-buffer settings + drawers | ⚠️ Comments only |
244
+ | **Extensible blocks** | ✅ Custom JSX | ✅ Custom drawers + keywords | ✅ Method calls |
245
+ | **Parse complexity** | High (JSX AST) | Medium (org-ruby exists) | Low (just Ruby eval) |
246
+ | **SW integration** | Would need port | **~60 line parser → SW components** | **Direct — already SW** |
247
+ | **Stands alone without renderer** | ❌ JSX unreadable | ✅ Yes | ⚠️ Only with Ruby context |
248
+ | **Diff-friendly** | ⚠️ Okay | ✅ Great | ✅ Great |
249
+ | **Works in GitHub PR review** | ❌ | ✅ Readable tables, code blocks | ✅ Ruby coloring |
250
+
251
+ ---
252
+
253
+ ## The Org-mode Advantage: What GitHub Actually Does
254
+
255
+ GitHub renders `.org` files natively — headings, bold, italic, links, tables,
256
+ code blocks. The `:PROPERTIES:` drawer is the one thing that doesn't render
257
+ beautifully (it shows as literal text), but it's concise and clearly structured.
258
+
259
+ Compare how a Decision block looks raw on GitHub:
260
+
261
+ **MDX (what you'd see in a PR):**
262
+ ```
263
+ <Decision
264
+ id="b3"
265
+ question={"How should guest sessions be stored?"}
266
+ options={[
267
+ { id: "o1", label: "JWT", detail: "Stateless, no DB lookup" },
268
+ { id: "o2", label: "Opaque token", detail: "Revocable", recommended: true },
269
+ ]}
270
+ />
271
+ ```
272
+ → Unrenderable JSX. A reviewer sees noise.
273
+
274
+ **Org-mode (what you'd see in a PR):**
275
+ ```
276
+ * Decision: Token Storage
277
+ :PROPERTIES:
278
+ :SW_COMPONENT: decision
279
+ :SW_RECOMMENDED: opaque
280
+ :END:
281
+
282
+ | jwt | Stateless, no DB lookup |
283
+ | opaque | Revocable, supports account merge later |
284
+ ```
285
+ → GitHub renders the table. The properties are visible but terse. A reviewer
286
+ understands the intent immediately, even without the StreamWeaver renderer.
287
+
288
+ This directly addresses Builder's cited concern: plan files should be readable
289
+ *raw*.
290
+
291
+ ---
292
+
293
+ ## Implementation Plan: SW-Org Format
294
+
295
+ ### Phase 1 — Parser (~1 session, ~150 lines Ruby)
296
+
297
+ ```ruby
298
+ # lib/stream_weaver/plan/org_parser.rb
299
+
300
+ module StreamWeaver
301
+ module Plan
302
+ class OrgParser
303
+ COMPONENT_MAP = {
304
+ "implementation_map" => :render_implementation_map,
305
+ "decision" => :render_decision,
306
+ "annotated_code" => :render_annotated_code,
307
+ "diagram" => :render_diagram,
308
+ "callout" => :render_callout,
309
+ "wireframe" => :render_wireframe,
310
+ "api_endpoint" => :render_api_endpoint,
311
+ nil => :render_prose, # no SW_COMPONENT = plain markdown
312
+ }
313
+
314
+ def initialize(org_text)
315
+ @parser = Orgmode::Parser.new(org_text)
316
+ @meta = @parser.in_buffer_settings
317
+ end
318
+
319
+ def title = @meta["TITLE"]
320
+ def brief = @meta["BRIEF"]
321
+ def date = @meta["DATE"]
322
+
323
+ # Yields DSL blocks to a StreamWeaver App context
324
+ def to_canvas_dsl
325
+ @parser.headlines.map do |headline|
326
+ props = headline.property_drawer || {}
327
+ component = props["SW_COMPONENT"]
328
+ body = extract_body(headline)
329
+ { component:, props:, headline: headline.headline_text, body: }
330
+ end
331
+ end
332
+
333
+ private
334
+
335
+ def extract_body(headline)
336
+ # Get raw lines, skip property drawer lines
337
+ lines = headline.body_lines.map do |l|
338
+ next unless l.respond_to?(:line)
339
+ next if [:property_drawer_begin_block,
340
+ :property_drawer_item,
341
+ :property_drawer_end_block].include?(l.paragraph_type)
342
+ l.line
343
+ end.compact
344
+ lines.join("\n").strip
345
+ end
346
+ end
347
+ end
348
+ end
349
+ ```
350
+
351
+ ### Phase 2 — Component renderers (~1-2 sessions)
352
+
353
+ Each `SW_COMPONENT` type gets a renderer that emits StreamWeaver DSL:
354
+
355
+ ```ruby
356
+ # For implementation_map: parse org table rows → files array
357
+ def render_implementation_map(headline:, props:, body:, **)
358
+ files = parse_org_table(body).map do |path, note|
359
+ { path: path.strip, note: note.strip }
360
+ end
361
+ implementation_map(files:)
362
+ end
363
+
364
+ # For decision: first column = option id/label, second = detail
365
+ # SW_RECOMMENDED property picks the winner
366
+ def render_decision(headline:, props:, body:, **)
367
+ recommended = props["SW_RECOMMENDED"]
368
+ options = parse_org_table(body).map do |label, detail|
369
+ { label: label.strip, detail: detail.strip,
370
+ recommended: label.strip.downcase == recommended&.downcase }
371
+ end
372
+ decision(question: headline, options:)
373
+ end
374
+
375
+ # For annotated_code: SRC block + ANNOTATIONS block
376
+ def render_annotated_code(headline:, props:, body:, **)
377
+ code = extract_src_block(body)
378
+ notes = extract_annotations_block(body)
379
+ lang = props["SW_LANG"]&.to_sym || :ruby
380
+ annotated_code(language: lang, code:, annotations: notes)
381
+ end
382
+ ```
383
+
384
+ ### Phase 3 — CLI integration (~half session)
385
+
386
+ ```bash
387
+ # Push org plan to live canvas
388
+ streamweaver canvas-push <session> --file plan.org
389
+
390
+ # Serve org plan as standalone page
391
+ streamweaver serve plan.org
392
+
393
+ # Export running canvas as org plan
394
+ streamweaver canvas-export <session> --format org > plan.org
395
+ ```
396
+
397
+ ### Phase 4 — Bidirectional: Canvas → Org (~1 session)
398
+
399
+ The really interesting capability: Claude Code builds a live canvas, then you
400
+ can export it as a checked-in org plan file. Builder has no equivalent — their
401
+ plans live in the hosted DB. Your plans live in git.
402
+
403
+ ```bash
404
+ streamweaver canvas-export guest-auth --format org > docs/plans/guest-auth.org
405
+ git add docs/plans/guest-auth.org && git commit -m "add guest auth plan"
406
+ ```
407
+
408
+ ---
409
+
410
+ ## The Hybrid Architecture
411
+
412
+ These formats aren't competing — they serve different moments:
413
+
414
+ ```
415
+ Planning Phase
416
+ ──────────────
417
+ Claude Code thinks → canvas-push (live Ruby DSL)
418
+ ↓ (user reviews in browser)
419
+ User approves → canvas-export --format org (checked-in artifact)
420
+ ↓ (in git, readable in GitHub PR)
421
+ Future Claude Code → canvas-push --file plan.org (restore from org)
422
+ ↓ (live again for the implementation phase)
423
+ Implementation done → streamweaver recap <session> (visual-recap equivalent)
424
+
425
+ docs/recaps/YYYY-MM-DD-feature.org (committed recap)
426
+ ```
427
+
428
+ The Ruby DSL is the **live wire** format — what Claude Code pushes in real time.
429
+ The org file is the **resting state** format — what gets committed, reviewed,
430
+ and loaded back.
431
+
432
+ You never need to write org by hand. Claude Code writes it. Humans read it raw.
433
+
434
+ ---
435
+
436
+ ## Is This Better Than MDX?
437
+
438
+ For StreamWeaver's use case: yes, clearly, on three dimensions:
439
+
440
+ **1. Raw readability.** Org tables and headings render well on GitHub. MDX JSX
441
+ component syntax doesn't. Builder acknowledged this as a concern — org solves
442
+ it without any compromise.
443
+
444
+ **2. No external dependency.** MDX requires a React renderer and a hosted Plan
445
+ app. Org-mode parsing is a pure Ruby library, already installed. A plan file
446
+ is readable with zero infrastructure — any text editor, GitHub's web UI, Emacs,
447
+ VS Code with the org extension. Builder's plan files are essentially useless
448
+ without plan.agent-native.com.
449
+
450
+ **3. Bidirectionality.** Canvas → Org export is natural. MDX round-trips are
451
+ hard (JSX isn't designed for serialization). Org is a text format that's
452
+ designed to be written by programs and read by humans.
453
+
454
+ Where MDX wins: if you're in a React/JS ecosystem with a polished hosted viewer.
455
+ Builder has that viewer. StreamWeaver's viewer is your local browser tab. For
456
+ that context, org-mode is strictly better.
457
+
458
+ ---
459
+
460
+ ## Effort Estimate
461
+
462
+ | Phase | Work | Estimate |
463
+ |---|---|---|
464
+ | Org parser + component dispatch | New file, ~150 lines | 1 session |
465
+ | Component renderers (5 types) | New file, ~200 lines | 1-2 sessions |
466
+ | CLI `--file plan.org` flag | Extend canvas-push | 0.5 session |
467
+ | Canvas → Org export | New renderer | 1 session |
468
+ | Tests + example plans | — | 0.5 session |
469
+ | **Total** | | **4-5 sessions** |
470
+
471
+ Comparison: MDX support would require a JS parser (or porting org-ruby's
472
+ equivalent), a React component registry, and a hosted viewer. That's a full
473
+ project, not a feature.
474
+
475
+ ---
476
+
477
+ ## Open Questions
478
+
479
+ 1. **Property drawer vs tag syntax?** Could use org tags instead of drawers
480
+ for component type: `* Implementation Map :implementation_map:` — less
481
+ verbose, but tags are normally for categorization not typing. Drawer is
482
+ semantically cleaner.
483
+
484
+ 2. **Nested components in org?** Org doesn't have great support for nesting
485
+ blocks. A `columns` layout with two `wireframe` children is harder to express
486
+ than in MDX or Ruby DSL. Could use level-2 headlines under a level-1
487
+ `SW_COMPONENT: columns` headline. Works but is slightly awkward.
488
+
489
+ 3. **Live push vs file format duality.** Should `canvas-push` accept both
490
+ a heredoc DSL (current) AND a `--file plan.org`? Yes — they're the same
491
+ push operation, different source formats. The parser is the adapter layer.
492
+
493
+ 4. **Lossiness on export.** Some live canvas state (Alpine.js interactions,
494
+ chart data loaded from state, button callbacks) can't round-trip to org.
495
+ Export should be a planning document, not a full canvas snapshot. Clarify
496
+ that boundary early.
497
+
498
+ 5. **Alternative: a simpler YAML-frontmatter markdown format?** Something like:
499
+ ```markdown
500
+ ---
501
+ sw_component: implementation_map
502
+ ---
503
+ | path | note |
504
+ |------|------|
505
+ ```
506
+ Lighter than org, but loses the native hierarchy. Org's heading structure
507
+ maps more naturally to a document with sections.
508
+
509
+ ---
510
+
511
+ *Exploration by Selene — June 2026*