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,53 @@
1
+ # Tabs and Navigation
2
+
3
+ ## tabs (eager, default) — plays well everywhere
4
+
5
+ ```ruby
6
+ tabs :settings_tabs do
7
+ tab "General" do
8
+ text "General settings content"
9
+ end
10
+ tab "Notifications" do
11
+ text "Notification settings content"
12
+ end
13
+ end
14
+ ```
15
+
16
+ Pure client-side `@click activeTab = N` — WORKS identically in A, B, and C. Variants (`variant: :enclosed`, `variant: :"soft-rounded"`) are CSS-only, no change to this. This is the form to reach for in the comprehensive example / any doc that has to survive an export.
17
+
18
+ ## tabs url: true — the one component that's MORE capable off the live canvas
19
+
20
+ ```ruby
21
+ tabs :view, url: true do
22
+ tab "Overview" do ... end
23
+ tab "Details" do ... end
24
+ end
25
+ ```
26
+
27
+ On canvas (A, B) this degrades to plain client-side tabs and logs a warning once per render — to the **agent's** stderr, never shown to the human viewing the page (`route_tabs? = component.url? && !websocket_mode?`). In an export (C), `sw-route-tabs.js` is inlined and runs real `pushState` routing, so the URL updates and the tab state survives a reload. This is intentional and informational (disc-099), not a bug — but if you're diagnosing "why does this tab set behave differently exported vs. on canvas," this is why. Not yet confirmed under `file://` — several browsers throw `SecurityError` for `pushState` on `file://` origins, so an exported doc opened directly from disk (not served over HTTP) may still break tab switching; check by hand if that's how the export will be opened.
28
+
29
+ ## collapsible / expandable_card / dropdown — plays well everywhere
30
+
31
+ ```ruby
32
+ collapsible "Show Details" do
33
+ text "Detail content"
34
+ end
35
+
36
+ expandable_card "Section" do # like collapsible, but the SERVER learns the expanded state
37
+ text "..."
38
+ end
39
+ ```
40
+
41
+ Pure Alpine `x-show`/`x-data`, no server dependency — WORKS in A, B, C. Use `expandable_card` over `collapsible` only if you need `state` to know whether a section is open; that's a server round-trip and inherits the sendEvent-only-on-live-canvas disposition for that specific bit of state (the panel itself still opens/closes client-side everywhere).
42
+
43
+ ## modal — needs a real server, half the time
44
+
45
+ Modal *closing* is Alpine-only and works everywhere. Modal *opening* is server-state driven — on the live canvas an agent has to push the state that opens it; on canvas-read and export there's no way to open one at all (SILENTLY-DEAD). Don't build a doc where the only path to some content is "click to open a modal" if that doc needs to survive being saved and reopened later.
46
+
47
+ ## route_by / route / page — needs a real server
48
+
49
+ The SSE client and routing/`popstate` scripts are `AppView`-only. Canvas (A, B) renders through `AppContentView`, export (C) through `ComponentRenderer.render_html` — neither ever gets those scripts, so `route_by` has no client at all backend-less. The initial paint shows and nothing ever updates. Out of scope for this skill's fixes; know it going in rather than debug a page that "isn't routing."
50
+
51
+ ## The gotcha
52
+
53
+ Route tabs are the one component in this whole skill where "more functional off the live canvas" is correct and not a regression. Every other asymmetry in this doc runs the other direction (live canvas is the most capable context) — this is the exception, and it's easy to mistake for a bug if you don't know it's by design.
@@ -0,0 +1,298 @@
1
+ ---
2
+ name: streamweaver-doc-builder
3
+ description: Use when building editorial "doc"-style StreamWeaver apps — PRDs, reports, explainers, long-form write-ups — with the :doc theme, doc_header/doc_section_header/sidebar_toc, and the shared-DSL pattern for standalone + canvas delivery
4
+ ---
5
+
6
+ # StreamWeaver Doc Builder
7
+
8
+ Build long-form, editorial-style documents (PRDs, reports, explainers) as StreamWeaver apps using the `:doc` theme and the document component family. Documents can be authored once as a shared DSL body and delivered two ways — standalone Ruby app or live canvas — without duplicating content.
9
+
10
+ ## When to Use
11
+
12
+ Use when the deliverable is a **document**, not a dashboard or a brainstorming canvas:
13
+
14
+ - A PRD, spec, or proposal that needs sections, a table of contents, callouts, and tables
15
+ - A report or explainer meant to be read top-to-bottom
16
+ - Anything you'd otherwise write as a long markdown file, but want scroll-spy navigation, styled callouts, and diagrams rendered live
17
+
18
+ Skip for: dashboards (use standard components), quick visual A/B comparisons or brainstorming (use `streamweaver-visual-companion`), pre-flight implementation plans (use `visual-plan`).
19
+
20
+ ## !! DO NOT LAUNCH STANDALONE SERVERS PER QUESTION !!
21
+
22
+ Same rule as the other canvas-based skills: **never** run `ruby app.rb` or `streamweaver <file.rb>` for each content update while iterating on a doc with the user. Use `canvas-push` to update a single persistent session. Only reach for a standalone `ruby` run when you want a permanent, git-tracked app file from the start (see "Two Delivery Modes" below).
23
+
24
+ ## The `:doc` Theme
25
+
26
+ `:doc` — "Compact Editorial" — is the theme for document-style apps: Charter/system-ui fonts, 15px base size, `#1E4ED8` primary blue, `#F5F4EF` background. Defined in `lib/stream_weaver/theme.rb`.
27
+
28
+ ```ruby
29
+ app "My Document Title", theme: :doc do
30
+ # ... doc components here
31
+ end
32
+ ```
33
+
34
+ **Do not confuse this with the older `:document` theme** (serif Crimson Pro, 19px, "Reading Mode"). `:document` predates `:doc` and some older example files in this repo still reference it — for new doc-style apps, always use `theme: :doc`.
35
+
36
+ Dark mode works automatically — the `:doc` theme has a dark variant, and `theme_toggle` / auto-mode JS sets `data-sw-theme="dark"` on `<html>` for you. Don't hand-roll dark-mode styling; just use `theme: :doc` (standalone) or `--theme=doc` (canvas panel) and it's wired through, including Mermaid diagram dark-sync.
37
+
38
+ ## Two Delivery Modes, One DSL Body
39
+
40
+ The core pattern: write your document content **once**, as a bare DSL body file — no `app` wrapper, just a sequence of top-level component calls. Then consume that same file two ways:
41
+
42
+ 1. **Standalone app** — `instance_eval` the body inside an `app "...", theme: :doc do ... end` wrapper
43
+ 2. **Canvas push** — pipe the body file directly to `streamweaver canvas-push <session>`
44
+
45
+ Because both modes read the exact same file, content never drifts between "the app I can `ruby run.rb`" and "the live canvas I've been iterating on with the user."
46
+
47
+ **Start every DSL body with `# streamweaver-doc: v1`.** A body is bare component calls with no `require` and no `app` wrapper, so nothing about the file says what it is — tooling that meets one out of context (a renderer pointed at a GitHub blob, an editor plugin) can't tell it from ordinary Ruby, and guessing from content is unreliable for short docs. "Save as doc" adds the line automatically; hand-written bodies need it written in. It's a comment, so it costs nothing at eval time.
48
+
49
+ Reference implementation in this repo: `examples/components/prd_dsl.rb` (body only) + `examples/components/prd_demo.rb` (standalone wrapper). Copy the shared-body/`instance_eval` structure — but note `prd_demo.rb` still says `theme: :document`, since it predates the `:doc` theme; use `theme: :doc` in new work.
50
+
51
+ ```ruby
52
+ # doc_body.rb — no `app` block, just component calls
53
+ # streamweaver-doc: v1
54
+ sidebar_toc sections: [
55
+ { id: "problem", label: "Problem Statement" },
56
+ { id: "architecture", label: "Architecture" }
57
+ ]
58
+
59
+ doc_header(title: "My PRD", pills: [{ text: "Draft" }])
60
+
61
+ doc_section_header "01", "Problem Statement", id: "problem"
62
+ md "Prose goes here."
63
+ ```
64
+
65
+ ```ruby
66
+ # doc_app.rb — standalone wrapper
67
+ require_relative "../../lib/stream_weaver"
68
+
69
+ DOC_BODY_PATH = File.join(__dir__, "doc_body.rb")
70
+
71
+ DocApp = app "My PRD", theme: :doc do
72
+ instance_eval(File.read(DOC_BODY_PATH), DOC_BODY_PATH)
73
+ end
74
+
75
+ DocApp.run! if __FILE__ == $0
76
+ ```
77
+
78
+ ```bash
79
+ # Same doc_body.rb, pushed to a live canvas instead
80
+ streamweaver canvas-push my-doc < doc_body.rb
81
+ ```
82
+
83
+ ## Shared DSL Fragments (multi-audience docs)
84
+
85
+ When two docs for **different audiences** (a decision memo and its engineering companion, say) must quote the same tables, rules, or numbers, put those tables in ONE fragment file and load it from both bodies. Prose stays per-audience; only the facts are shared.
86
+
87
+ A fragment is a plain `.rb` under `shared/` that defines methods emitting DSL and nothing else: no `app` wrapper, no `doc_header`/`sidebar_toc`, no side effects, no `# streamweaver-doc: v1` marker. Name the methods with a doc-family prefix (`pm_base_rules_table`), because `instance_eval` turns them into singleton methods on the App and they share a namespace with every DSL verb.
88
+
89
+ Consumer snippet, top of each doc body:
90
+
91
+ ```ruby
92
+ unless respond_to?(:pm_base_rules_table)
93
+ _root = __dir__ || ENV["SW_DOC_DIR"] || Dir.pwd
94
+ _frag = File.expand_path("shared/pm_discount_shared.rb", _root)
95
+ raise "shared DSL fragment not found: #{_frag}" unless File.file?(_frag)
96
+ instance_eval(File.read(_frag), _frag)
97
+ end
98
+ ```
99
+
100
+ `export` and `canvas-read` pass the doc's path to `instance_eval`, so `__dir__` resolves the fragment there. `org-export` and the canvas-push bridge do not, so `__dir__` is `nil`: run `org-export` from the doc's directory (or set `SW_DOC_DIR`), and for canvas-push concatenate the fragment ahead of the body, which the `respond_to?` guard makes idempotent:
101
+
102
+ ```bash
103
+ cat shared/pm_discount_shared.rb my-doc.rb | streamweaver canvas-push my-doc
104
+ ```
105
+
106
+ Never hardcode an absolute home-directory path as a fallback. Full rationale, the per-mode `__dir__` truth table with code cites, the org-mode answers, and a proposal for a first-class `dsl_fragment` helper: `docs/shared-dsl-fragments.md` in the stream_weaver repo.
107
+
108
+ ## Component Reference
109
+
110
+ ### `doc_header` — title block
111
+
112
+ ```ruby
113
+ doc_header(
114
+ eyebrow: "Acme Corp · Internal Wiki", # optional small label above the title
115
+ title: "Calendar-Driven Travel State", # required
116
+ pills: [ # optional meta row
117
+ { text: "Draft" }, # Hash -> colored pill (variant: :default/:warn/:good)
118
+ "June 25, 2026", # String -> plain meta text
119
+ "Author: Jane Doe"
120
+ ]
121
+ )
122
+ ```
123
+
124
+ ### `doc_section_header` — numbered section heading
125
+
126
+ ```ruby
127
+ doc_section_header "01", "Problem Statement", id: "problem"
128
+ # number, title positional; id: becomes the DOM anchor id
129
+ ```
130
+
131
+ ### `sidebar_toc` — sticky scroll-spy table of contents
132
+
133
+ Call once, near the top of the doc:
134
+
135
+ ```ruby
136
+ sidebar_toc sections: [
137
+ { id: "problem", label: "Problem Statement" },
138
+ { id: "architecture", label: "Architecture" }
139
+ ]
140
+ ```
141
+
142
+ Desktop (>=1000px): sticky 170px sidebar, active section highlighted via `IntersectionObserver`. Mobile (<1000px): horizontal scrollable sticky bar at top. Each `id:` here must exactly match the `id:` on a `doc_section_header` (see Known Gotchas).
143
+
144
+ ### `callout` — non-dismissible tip/warning box
145
+
146
+ ```ruby
147
+ callout(variant: :warning, title: "Root cause:") do
148
+ text "Explanation text here."
149
+ end
150
+ # variants: :info, :warning, :success, :error, :tip, :decision, :risk
151
+ ```
152
+
153
+ ### `table` — data table
154
+
155
+ ```ruby
156
+ table(
157
+ headers: ["Component", "Responsibility", "Owner"],
158
+ rows: [
159
+ ["Enforcement", "Require calendar entry", "scheduler secretary"],
160
+ ["Sync script", "Read calendars, write state", "launchd"]
161
+ ]
162
+ )
163
+ ```
164
+
165
+ ### `card` / `card_header` / `card_body` — boxed section
166
+
167
+ ```ruby
168
+ card do
169
+ card_header "Component Title", badge: "C1", meta: "owner · trigger"
170
+ # badge: optional small tag before title; meta: optional right-aligned text
171
+ card_body do
172
+ md "Body content, supports **markdown**."
173
+ code_block(<<~TXT, lang: "text")
174
+ inline code sample
175
+ TXT
176
+ end
177
+ end
178
+ ```
179
+
180
+ ### `comparison` — side-by-side before/after panels
181
+
182
+ Useful for "In Scope" / "Out of Scope" grids:
183
+
184
+ ```ruby
185
+ comparison(before_label: "In Scope", after_label: "Out of Scope") do
186
+ before { md "- Item 1\n- Item 2" }
187
+ after { md "- Excluded item" }
188
+ end
189
+ # Stacks vertically on viewports <768px.
190
+ ```
191
+
192
+ ### `code_block` — syntax-highlighted code
193
+
194
+ ```ruby
195
+ code_block(<<~RUBY, lang: "ruby")
196
+ def hello
197
+ puts "hi"
198
+ end
199
+ RUBY
200
+ # Options: file: "path/to/file.rb" (shows file header bar),
201
+ # truncate: N (thumbnail line limit), scroll: true/false
202
+ ```
203
+
204
+ ### `mermaid` — diagrams (dark-mode aware)
205
+
206
+ ```ruby
207
+ mermaid <<~MERMAID
208
+ graph LR
209
+ A["Calendar"] --> B["Sync script"] --> C["state.yaml"]
210
+ style A fill:#EEF2FF,stroke:#1E4ED8,color:#1E4ED8
211
+ MERMAID
212
+ # Options: zoom: true (pan/zoom controls), compact: true (reduced padding
213
+ # for card embedding), layout: :elk
214
+ ```
215
+
216
+ ### `md` — prose
217
+
218
+ Use `md` for all body copy that needs bold/italic/links/lists. **`text` does not render markdown** — see Known Gotchas.
219
+
220
+ ## Minimal Copy-Paste Template
221
+
222
+ A complete, runnable doc in under 30 lines. Adapt the titles/sections/content and go.
223
+
224
+ ```ruby
225
+ require_relative "../../lib/stream_weaver"
226
+
227
+ MyDoc = app "My Report Title", theme: :doc do
228
+ sidebar_toc sections: [
229
+ { id: "overview", label: "Overview" },
230
+ { id: "findings", label: "Findings" }
231
+ ]
232
+
233
+ doc_header(
234
+ eyebrow: "Team · Project",
235
+ title: "My Report Title",
236
+ pills: [{ text: "Draft" }, "July 2, 2026"]
237
+ )
238
+
239
+ doc_section_header "01", "Overview", id: "overview"
240
+ md "This report covers **what changed** and *why it matters*."
241
+
242
+ callout(variant: :info, title: "Key takeaway") do
243
+ text "The short version, up front."
244
+ end
245
+
246
+ doc_section_header "02", "Findings", id: "findings"
247
+ table(
248
+ headers: ["Metric", "Before", "After"],
249
+ rows: [["Latency", "220ms", "80ms"]]
250
+ )
251
+ end
252
+
253
+ MyDoc.run! if __FILE__ == $0
254
+ ```
255
+
256
+ To push the same content live instead of running it standalone: strip the `require_relative`/`app ... do`/`.run!` wrapper down to just the component calls (the body), and pipe it: `streamweaver canvas-push my-doc < doc_body.rb`.
257
+
258
+ ## Canvas Workflow
259
+
260
+ ```bash
261
+ # 1. Open a themed canvas panel (iTerm2 split pane, or browser tab elsewhere)
262
+ streamweaver panel my-doc --theme=doc --fresh
263
+
264
+ # 2. Push the DSL body (same file used standalone — see shared-DSL pattern above)
265
+ streamweaver canvas-push my-doc < path/to/doc_body.rb
266
+
267
+ # 3. Interact — user can click, scroll, use theme_toggle if included; you can push
268
+ # updates to the SAME session as content evolves (re-run canvas-push with the
269
+ # updated body — never spin up a second session)
270
+
271
+ # 4. Save as doc — a floating 💾 "Save as doc" button sits bottom-right on the canvas.
272
+ # User clicks it, names the doc, and it's written to docs/streamweaver_canvas/<name>.rb
273
+ # — git-tracked, permanent. Don't reinvent this flow for the user; point them at the
274
+ # button. Fallback (only if the button isn't reachable, e.g. non-canvas context) —
275
+ # get <bridge-port> from `streamweaver canvas-list` output:
276
+ curl -sX POST "http://localhost:<bridge-port>/canvas/my-doc/save-doc" \
277
+ -H 'Content-Type: application/json' \
278
+ -d '{"name":"<doc-name>"}'
279
+ ```
280
+
281
+ `--theme=doc` on `panel` renders the canvas in the `:doc` theme, dark-mode variant included — the canvas body gets class `sw-theme-doc`, and Mermaid dark-attribute sync wires through automatically.
282
+
283
+ `streamweaver canvas-read` (no args) opens a browsable viewer over `docs/streamweaver_canvas/` — saved Docs and auto-saved History, both promotable/viewable from the same UI.
284
+
285
+ Every `canvas-push` is auto-saved to history (`~/.streamweaver/history/<session>/`, 7-day cleanup, not git-tracked) regardless of whether the user ever clicks Save as doc — this is tier 1 of a two-tier persistence system. Nothing is silently lost even before an explicit save; tier 2 (Save as doc) is what makes it permanent and shared.
286
+
287
+ A saved doc is browsed later via `canvas-read` and can be run through `streamweaver export` — both with no live bridge behind them. Most doc components (`doc_header`, `sidebar_toc`, `callout`, `table`, `mermaid`, `card`) are flat or Alpine-owned and survive that fine, but before adding interactive controls (buttons, forms, chips) to a doc, check the `streamweaver-canvas-safe` skill for what plays well once the bridge is gone.
288
+
289
+ ## Known Gotchas
290
+
291
+ - **`text` does not render markdown** — bold, italic, links, and lists all need `md` instead.
292
+ - **`spacer`/`divider` don't exist** — use `div(style: "height:Npx")` for spacing.
293
+ - **Don't launch a new server per update** — use `canvas-push` to update a single persistent session, not `ruby app.rb` repeatedly.
294
+ - **Don't assume port 4567** — StreamWeaver auto-picks a free port; read the actual URL from stdout.
295
+ - **Don't pass `theme: :light`** — it's unrecognized and silently falls back to `:default`. Omit `theme:` entirely, or use `theme_toggle mode: :light` if you want to force light appearance within `:doc`.
296
+ - **`sidebar_toc` section `id:` values must exactly match** the `id:` passed to each `doc_section_header`. A mismatch silently breaks scroll-spy highlighting — no error, it just won't highlight.
297
+ - **Don't hand-roll dark mode** — the `:doc` theme's dark variant and Mermaid dark-sync already work automatically in both standalone and canvas contexts. Just use `theme: :doc` / `--theme=doc`.
298
+ - **Don't confuse `:doc` with `:document`** — `:document` is the older serif "Reading Mode" theme; `:doc` ("Compact Editorial") is the current one to use for new document-style apps.
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: streamweaver-visual-companion
3
+ description: Use INSTEAD OF the Artifact tool, and INSTEAD OF writing an HTML mockup and opening/screenshotting it with Chrome browser tools (claude-in-chrome, superpowers-chrome, playwright) — whenever about to show the user something visually (UI mockup, wireframe, diagram, dashboard, layout/design comparison, side-by-side options, long-form doc) and StreamWeaver is available in the project (streamweaver on PATH, or stream_weaver in the Gemfile — one command to check). Also triggers on "show me", "mock it up", "let me see the options", "push to canvas", or the urge to run `ruby app.rb`/`streamweaver <file>` per question. canvas-push is 5-7x cheaper in tokens than the chrome route, with no GEA session conflicts.
4
+ ---
5
+
6
+ # StreamWeaver Visual Companion
7
+
8
+ Replaces both the `Artifact` tool and the write-HTML-then-screenshot-via-Chrome pattern for showing things visually in a StreamWeaver project — same "show, don't tell" move, 5-7x fewer tokens, no GEA session conflicts, stays inside the terminal loop you're already running.
9
+
10
+ ## When to Use
11
+
12
+ Decision rule: **would the user understand this better by seeing it than reading it?**
13
+
14
+ Use for: UI mockups, architecture diagrams, layout comparisons, side-by-side design options, state machine flows.
15
+ Use terminal for: requirements questions, conceptual A/B text choices, tradeoff lists, anything answered in words.
16
+
17
+ Fall back to `Artifact` only when:
18
+ - StreamWeaver isn't installed/available in this project, or
19
+ - the user needs a claude.ai-hosted link that persists with no local `streamweaver` process running, or that must reach someone without this repo.
20
+
21
+ ## !! DO NOT LAUNCH STANDALONE SERVERS PER QUESTION !!
22
+
23
+ **This is the most common failure mode. Read carefully.**
24
+
25
+ **NEVER** run `ruby app.rb` or `streamweaver <file.rb>` for each visual question in a conversation. This creates orphaned processes, port conflicts, and multiple browser windows. The correct approach is **canvas-push** — it updates a single persistent window throughout the conversation.
26
+
27
+ If you find yourself launching a new server for each update, stop. Use `canvas-push` instead.
28
+
29
+ ## Starting a Session
30
+
31
+ ```bash
32
+ # Start a named canvas session (opens browser tab automatically)
33
+ streamweaver panel brainstorm
34
+
35
+ # Push first content
36
+ streamweaver canvas-push brainstorm <<'RUBY'
37
+ header1 "Which layout works better?"
38
+ columns widths: ['50%', '50%'] do
39
+ column do
40
+ header3 "Option A — Current"
41
+ md "- 6 tabs"
42
+ md "- Scanner Tasks separate"
43
+ end
44
+ column do
45
+ header3 "Option B — Proposed"
46
+ md "- 5 tabs"
47
+ md "- Scanner Tasks merged into Home"
48
+ end
49
+ end
50
+ RUBY
51
+ ```
52
+
53
+ Tell the user: "Take a look at [url printed by StreamWeaver] and let me know what you think in the terminal."
54
+
55
+ ## Layout
56
+
57
+ Canvas sessions default to **`:fluid` (full viewport width)** — the best choice for side-by-side comparisons. Override with `--layout=` if you need a narrower centered card:
58
+
59
+ ```bash
60
+ streamweaver panel brainstorm # fluid (default, full-width)
61
+ streamweaver panel brainstorm --layout=default # 900px centered card
62
+ streamweaver panel brainstorm --layout=wide # 1100px
63
+ streamweaver panel brainstorm --layout=full # 1400px
64
+ ```
65
+
66
+ ## The Loop
67
+
68
+ 1. Push DSL content via `canvas-push`
69
+ 2. Tell user what to expect, give the URL, end your turn
70
+ 3. User responds in terminal — use their text as feedback
71
+ 4. Push updated content or next question
72
+ 5. Repeat until done
73
+
74
+ Blocking selection: `radio_group` + `button`, then `canvas-wait <session>` to get their click as JSON. Ending a push with more than one question? Bundle into one form instead of one round-trip each — see `references/checkpoints-and-forms.md`.
75
+
76
+ Every push auto-saves to history; the user can promote it to a permanent doc with the canvas's own Save-as-doc button (their action, never yours) — see `references/persistence.md`.
77
+
78
+ ## Returning to Terminal
79
+
80
+ When the next step is text-only, push a placeholder so the user isn't staring at a resolved mockup:
81
+
82
+ ```bash
83
+ streamweaver canvas-push brainstorm <<'RUBY'
84
+ div(style: "display:flex;align-items:center;justify-content:center;min-height:60vh") do
85
+ text "Continuing in terminal..."
86
+ end
87
+ RUBY
88
+ ```
89
+
90
+ ## DSL Quick Reference
91
+
92
+ ```ruby
93
+ header1 "Title" # h1–h6 available
94
+ text "Plain text" # NEVER put markdown in text — use md instead
95
+ md "**Bold** and *italic*" # markdown renderer
96
+ div(style: "height:16px") # spacing (spacer/divider not available)
97
+
98
+ columns widths: ['50%','50%'] do # side-by-side comparison
99
+ column { header3 "Left" }
100
+ column { header3 "Right" }
101
+ end
102
+
103
+ card do # boxed section
104
+ header3 "Section"
105
+ text "Content"
106
+ end
107
+
108
+ table headers: ["Col","Col2"], rows: [["a","b"],["c","d"]]
109
+ radio_group :choice, ["Option A", "Option B", "Option C"]
110
+ button "Select"
111
+ badge "New", color: :green
112
+ status_dot :green, "Active"
113
+ ```
114
+
115
+ ## Known Gotchas
116
+
117
+ - `spacer` and `divider` don't exist — use `div(style: "height:Npx")`
118
+ - `theme: :light` unrecognized — omit, defaults to `:default`
119
+ - StreamWeaver auto-selects an available port (not always 4567) — capture the URL from stdout
120
+ - Canvas sessions default to `:fluid` (full-width) — use `--layout=default` if you want the 900px centered card
121
+ - Numbered/bulleted list items split across **separate `md()` calls don't continue** — each `md()` call is its own independent markdown block, so three calls each starting `"1. ..."` render as three separate one-item lists (all showing "1.") instead of counting up 1/2/3. Put a multi-item list in **one** `md()` call, one item per line, e.g. `md "1. First\n2. Second\n3. Third"`.
122
+
123
+ ## Reference Files — Load On Demand
124
+
125
+ | Doing... | Read |
126
+ |---|---|
127
+ | Porting a claude.ai Artifact 1:1, or building a long-form doc | `references/example-gallery.md` |
128
+ | Ending a push with more than one question | `references/checkpoints-and-forms.md` |
129
+ | Saving/persisting a canvas doc, sharing DSL across two docs | `references/persistence.md` |
130
+ | Cleaning up orphaned processes, or how `panel` opens the browser | `references/cleanup-and-panel.md` |