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
data/bench/support.rb ADDED
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+ require "json"
5
+ require "fileutils"
6
+ require "rack/test"
7
+ require "tmpdir"
8
+
9
+ ENV["RACK_ENV"] ||= "test"
10
+ ENV["SW_SESSION_DIR"] ||= File.join(Dir.tmpdir, "stream-weaver-bench-sessions")
11
+ FileUtils.mkdir_p(ENV.fetch("SW_SESSION_DIR"))
12
+ require "stream_weaver"
13
+
14
+ module StreamWeaverBench
15
+ PEOPLE = Array.new(50) do |index|
16
+ id = index + 1
17
+ { id: id, name: format("Person %02d", id), email: format("person%02d@example.test", id), touched: "2026-07-01" }
18
+ end.freeze
19
+ STORIES = Array.new(12) do |index|
20
+ id = index + 1
21
+ { id: id, title: format("Story %02d", id), column: %w[Ready Active Done][index % 3], notes: ["Seed note #{id}"] }
22
+ end.freeze
23
+
24
+ class MemoryStore
25
+ def initialize(records)
26
+ @records = StreamWeaverBench.deep_copy(records)
27
+ end
28
+
29
+ def all = @records
30
+ def find(id) = @records.find { |record| record[:id] == id }
31
+ def create(attributes) = @records << attributes.dup
32
+
33
+ def update(id, attributes)
34
+ find(id)&.merge!(attributes)
35
+ end
36
+
37
+ def destroy(id)
38
+ @records.reject! { |record| record[:id] == id }
39
+ end
40
+ end
41
+
42
+ class Metrics
43
+ attr_accessor :rebuilds, :callbacks
44
+
45
+ def initialize = reset!
46
+ def reset! = (@rebuilds = @callbacks = 0)
47
+ def callback! = (@callbacks += 1)
48
+ end
49
+
50
+ module Instrumented
51
+ attr_accessor :bench_metrics
52
+
53
+ def rebuild_with_state(...)
54
+ bench_metrics.rebuilds += 1 if bench_metrics
55
+ super
56
+ end
57
+ end
58
+
59
+ def self.instrument(app, metrics)
60
+ app.singleton_class.prepend(Instrumented)
61
+ app.bench_metrics = metrics
62
+ app
63
+ end
64
+
65
+ def self.deep_copy(value) = Marshal.load(Marshal.dump(value))
66
+
67
+ module Html
68
+ module_function
69
+
70
+ def action_path(body, label)
71
+ tags = body.scan(/<button\b[^>]*>.*?<\/button>/m)
72
+ tag = tags.find { |candidate| candidate.gsub(/<[^>]+>/, "").include?(label) }
73
+ raise "button not found: #{label}" unless tag
74
+ tag[%r{hx-post="([^"]+)"}, 1] || raise("action path missing for #{label}")
75
+ end
76
+
77
+ def fragment_token(body)
78
+ encoded = body[/name="_sw_fragment" value="([^"]+)"/, 1]
79
+ encoded && CGI.unescapeHTML(encoded)
80
+ end
81
+
82
+ def node_count(body) = body.scan(/<(?!\/|!|\?)[a-z][^>]*>/i).length
83
+ end
84
+ end
@@ -0,0 +1,220 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Run Viewer — abc-123</title>
6
+ <style>
7
+ * { margin: 0; padding: 0; box-sizing: border-box; }
8
+ body { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 13px; background: #1a1a2e; color: #e0e0e0; padding: 16px; }
9
+ header { margin-bottom: 16px; }
10
+ h1 { font-size: 18px; color: #fff; margin-bottom: 8px; }
11
+ .meta { color: #888; margin-bottom: 4px; }
12
+ .meta span { margin-right: 16px; }
13
+ .timeline { display: flex; flex-direction: column; gap: 2px; }
14
+ .event { padding: 6px 10px; border-radius: 4px; cursor: pointer; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; border-left: 3px solid transparent; }
15
+ .event:hover { background: #2a2a4a; }
16
+ .idx { color: #555; width: 24px; text-align: right; flex-shrink: 0; }
17
+ .ts { color: #666; flex-shrink: 0; }
18
+ .type-badge { display: inline-block; width: 100px; padding: 1px 6px; border-radius: 3px; text-align: center; font-size: 11px; flex-shrink: 0; }
19
+ .label { color: #ccc; }
20
+ .detail { width: 100%; padding: 10px 0 6px 36px; }
21
+ .field { margin-bottom: 4px; }
22
+ .field strong { color: #aaa; }
23
+ .field pre { margin: 4px 0 4px 12px; padding: 8px; background: #0d0d1a; border-radius: 4px; overflow-x: auto; white-space: pre-wrap; }
24
+ .phase { border-left-color: #00bcd4; }
25
+ .phase .type-badge { background: #0e3a3f; color: #00bcd4; }
26
+ .snapshot { border-left-color: #ffc107; }
27
+ .snapshot .type-badge { background: #3f3500; color: #ffc107; }
28
+ .intervention { border-left-color: #ce93d8; }
29
+ .intervention .type-badge { background: #3a1a44; color: #ce93d8; }
30
+ .timeout { border-left-color: #ef5350; }
31
+ .timeout .type-badge { background: #3f0e0e; color: #ef5350; }
32
+ .guard { border-left-color: #ef5350; }
33
+ .guard .type-badge { background: #3f0e0e; color: #ef5350; }
34
+ .final { border-left-color: #66bb6a; }
35
+ .final .type-badge { background: #0e3f12; color: #66bb6a; }
36
+ </style>
37
+ </head>
38
+ <body>
39
+ <header>
40
+ <h1>Run Viewer</h1>
41
+ <div class="meta">
42
+ <span>run_id: abc-123</span>
43
+ <span>target: codex</span>
44
+ <span>duration: 60.0s</span>
45
+ <span>events: 11</span>
46
+ </div>
47
+ <div class="meta">
48
+ <span>interventions: 2</span>
49
+ <span>timeouts: 0</span>
50
+ <span>snapshots: 2</span>
51
+ </div>
52
+ <div class="meta"><span>source: demo/sample_run.jsonl</span></div>
53
+ </header>
54
+ <main><div class="timeline"><div class="event phase" onclick="toggle(this)">
55
+ <span class="idx">0</span>
56
+ <span class="type-badge">phase</span>
57
+ <span class="ts">10:00:00</span>
58
+ <span class="label">launch</span>
59
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
60
+ <div class="field"><strong>phase:</strong> launch</div>
61
+ <div class="field"><strong>target:</strong> codex</div>
62
+ <div class="field"><strong>baseline_files:</strong> lib/app.rb</div>
63
+ <div class="field"><strong>step_id:</strong> launch</div>
64
+ <div class="field"><strong>target_socket_name:</strong> dto-codex</div>
65
+ <div class="field"><strong>target_session_name:</strong> run-1</div></div>
66
+ </div>
67
+
68
+ <div class="event phase" onclick="toggle(this)">
69
+ <span class="idx">1</span>
70
+ <span class="type-badge">phase</span>
71
+ <span class="ts">10:00:05</span>
72
+ <span class="label">settle step=1</span>
73
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
74
+ <div class="field"><strong>phase:</strong> settle</div>
75
+ <div class="field"><strong>step:</strong> 1</div>
76
+ <div class="field"><strong>step_id:</strong> step-1</div></div>
77
+ </div>
78
+
79
+ <div class="event phase" onclick="toggle(this)">
80
+ <span class="idx">2</span>
81
+ <span class="type-badge">phase</span>
82
+ <span class="ts">10:00:15</span>
83
+ <span class="label">observe step=1</span>
84
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
85
+ <div class="field"><strong>phase:</strong> observe</div>
86
+ <div class="field"><strong>step:</strong> 1</div>
87
+ <div class="field"><strong>step_id:</strong> step-1</div></div>
88
+ </div>
89
+
90
+ <div class="event snapshot" onclick="toggle(this)">
91
+ <span class="idx">3</span>
92
+ <span class="type-badge">snapshot</span>
93
+ <span class="ts">10:00:16</span>
94
+ <span class="label">state=working verification_ok=false step=1</span>
95
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
96
+ <div class="field"><strong>step:</strong> 1</div>
97
+ <div class="field"><strong>step_id:</strong> step-1</div>
98
+ <div class="field"><strong>state:</strong> working</div>
99
+ <div class="field"><strong>waiting_for_input:</strong> false</div>
100
+ <div class="field"><strong>busy:</strong> true</div>
101
+ <div class="field"><strong>likely_complete:</strong> false</div>
102
+ <div class="field"><strong>signals_found:</strong> []</div>
103
+ <div class="field"><strong>signals_missing:</strong> test passes</div>
104
+ <div class="field"><strong>verification_ok:</strong> false</div>
105
+ <div class="field"><strong>changed_files:</strong> lib/app.rb</div>
106
+ <div class="field"><strong>last_assistant_lines:</strong> Writing the initial implementation...</div></div>
107
+ </div>
108
+
109
+ <div class="event phase" onclick="toggle(this)">
110
+ <span class="idx">4</span>
111
+ <span class="type-badge">phase</span>
112
+ <span class="ts">10:00:17</span>
113
+ <span class="label">decide step=1</span>
114
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
115
+ <div class="field"><strong>phase:</strong> decide</div>
116
+ <div class="field"><strong>step:</strong> 1</div>
117
+ <div class="field"><strong>step_id:</strong> step-1</div>
118
+ <div class="field"><strong>driver:</strong> ClaudeDriverBackend</div></div>
119
+ </div>
120
+
121
+ <div class="event intervention" onclick="toggle(this)">
122
+ <span class="idx">5</span>
123
+ <span class="type-badge">intervention</span>
124
+ <span class="ts">10:00:22</span>
125
+ <span class="label">action=question terminal=false step=1</span>
126
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
127
+ <div class="field"><strong>step:</strong> 1</div>
128
+ <div class="field"><strong>step_id:</strong> step-1</div>
129
+ <div class="field"><strong>action:</strong> question</div>
130
+ <div class="field"><strong>intent:</strong> Clarify scope</div>
131
+ <div class="field"><strong>why:</strong> Worker jumped into coding without asking about interface shape</div>
132
+ <div class="field"><strong>next_step:</strong> List the product choices before writing code</div>
133
+ <div class="field"><strong>stop_if:</strong> Worker starts asking clarifying questions</div>
134
+ <div class="field"><strong>rendered_message:</strong> <pre>INTENT: Clarify scope
135
+ WHY: You started coding without clarifying the interface shape.
136
+ NEXT: List the product choices first.
137
+ STOP IF: You start asking clarifying questions.</pre></div>
138
+ <div class="field"><strong>terminal:</strong> false</div></div>
139
+ </div>
140
+
141
+ <div class="event phase" onclick="toggle(this)">
142
+ <span class="idx">6</span>
143
+ <span class="type-badge">phase</span>
144
+ <span class="ts">10:00:23</span>
145
+ <span class="label">send step=1</span>
146
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
147
+ <div class="field"><strong>phase:</strong> send</div>
148
+ <div class="field"><strong>step:</strong> 1</div>
149
+ <div class="field"><strong>step_id:</strong> step-1</div></div>
150
+ </div>
151
+
152
+ <div class="event phase" onclick="toggle(this)">
153
+ <span class="idx">7</span>
154
+ <span class="type-badge">phase</span>
155
+ <span class="ts">10:00:35</span>
156
+ <span class="label">settle step=2</span>
157
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
158
+ <div class="field"><strong>phase:</strong> settle</div>
159
+ <div class="field"><strong>step:</strong> 2</div>
160
+ <div class="field"><strong>step_id:</strong> step-2</div></div>
161
+ </div>
162
+
163
+ <div class="event snapshot" onclick="toggle(this)">
164
+ <span class="idx">8</span>
165
+ <span class="type-badge">snapshot</span>
166
+ <span class="ts">10:00:45</span>
167
+ <span class="label">state=waiting verification_ok=true step=2</span>
168
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
169
+ <div class="field"><strong>step:</strong> 2</div>
170
+ <div class="field"><strong>step_id:</strong> step-2</div>
171
+ <div class="field"><strong>state:</strong> waiting</div>
172
+ <div class="field"><strong>waiting_for_input:</strong> true</div>
173
+ <div class="field"><strong>busy:</strong> false</div>
174
+ <div class="field"><strong>likely_complete:</strong> false</div>
175
+ <div class="field"><strong>signals_found:</strong> test passes</div>
176
+ <div class="field"><strong>signals_missing:</strong> []</div>
177
+ <div class="field"><strong>verification_ok:</strong> true</div>
178
+ <div class="field"><strong>changed_files:</strong> lib/app.rb, test/test_app.rb</div>
179
+ <div class="field"><strong>last_assistant_lines:</strong> All tests pass. Here is the summary...</div></div>
180
+ </div>
181
+
182
+ <div class="event intervention" onclick="toggle(this)">
183
+ <span class="idx">9</span>
184
+ <span class="type-badge">intervention</span>
185
+ <span class="ts">10:00:50</span>
186
+ <span class="label">action=verify terminal=true step=2</span>
187
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
188
+ <div class="field"><strong>step:</strong> 2</div>
189
+ <div class="field"><strong>step_id:</strong> step-2</div>
190
+ <div class="field"><strong>action:</strong> verify</div>
191
+ <div class="field"><strong>intent:</strong> Confirm completion</div>
192
+ <div class="field"><strong>why:</strong> Signals met and verification passes</div>
193
+ <div class="field"><strong>next_step:</strong> Summarize what changed</div>
194
+ <div class="field"><strong>stop_if:</strong> nil</div>
195
+ <div class="field"><strong>rendered_message:</strong> <pre>INTENT: Confirm completion
196
+ WHY: All signals met.
197
+ NEXT: Summarize.
198
+ STOP IF: n/a</pre></div>
199
+ <div class="field"><strong>terminal:</strong> true</div></div>
200
+ </div>
201
+
202
+ <div class="event final" onclick="toggle(this)">
203
+ <span class="idx">10</span>
204
+ <span class="type-badge">final</span>
205
+ <span class="ts">10:01:00</span>
206
+ <span class="label">interventions=2</span>
207
+ <div class="detail" style="display:none"><div class="field"><strong>run_id:</strong> abc-123</div>
208
+ <div class="field"><strong>interventions:</strong> 2</div>
209
+ <div class="field"><strong>final_transcript_tail:</strong> Done. All tests pass.</div>
210
+ <div class="field"><strong>step_id:</strong> final</div></div>
211
+ </div>
212
+ </div></main>
213
+ <script>
214
+ function toggle(el) {
215
+ var d = el.querySelector('.detail');
216
+ if (d) d.style.display = d.style.display === 'none' ? 'block' : 'none';
217
+ }
218
+ </script>
219
+ </body>
220
+ </html>
@@ -0,0 +1,302 @@
1
+ # StreamWeaver Service Mode
2
+
3
+ StreamWeaver operates in two modes: **standalone scripts** and **service mode**. This document explains when to use each and how the service architecture works.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ gem install stream_weaver
9
+
10
+ # Interactive tutorial
11
+ streamweaver tutorial
12
+
13
+ # Browse all examples
14
+ streamweaver showcase
15
+ ```
16
+
17
+ ## Execution Modes
18
+
19
+ ### 1. Standalone Scripts (`ruby app.rb`)
20
+
21
+ For simple, one-off scripts where you want a quick UI:
22
+
23
+ ```ruby
24
+ # greeting.rb
25
+ require 'stream_weaver'
26
+
27
+ app "Greeting" do
28
+ text_field :name, placeholder: "Your name"
29
+
30
+ if state[:name].to_s.strip != ""
31
+ text "Hello, #{state[:name]}!"
32
+ end
33
+ end.run!
34
+ ```
35
+
36
+ Run with: `ruby greeting.rb`
37
+
38
+ **Use when:**
39
+ - Quick utilities and scripts
40
+ - Single-purpose tools
41
+ - Learning StreamWeaver
42
+ - Prototyping
43
+
44
+ **Characteristics:**
45
+ - Each script runs its own Sinatra server
46
+ - Auto-detects free port (4567, 4568, etc.)
47
+ - Auto-opens browser
48
+ - Self-contained - no dependencies on service
49
+
50
+ ### 2. Service Mode (`streamweaver <file>`)
51
+
52
+ A single background service renders multiple apps, each at a unique URL:
53
+
54
+ ```bash
55
+ # Start service (auto-starts if not running)
56
+ streamweaver examples/basic/hello_world.rb
57
+
58
+ # Run another app (same service, new URL)
59
+ streamweaver examples/basic/todo_list.rb
60
+
61
+ # List all loaded apps
62
+ streamweaver list
63
+
64
+ # Admin dashboard
65
+ streamweaver admin
66
+ ```
67
+
68
+ **Use when:**
69
+ - Running multiple apps side-by-side
70
+ - Tutorial and examples browser (loads playground apps)
71
+ - Comparing different implementations
72
+ - Long-running development sessions
73
+
74
+ **Characteristics:**
75
+ - Single server process on port 4567
76
+ - Apps at human-readable `/apps/:slug` URLs (e.g. `/apps/sales-dashboard`), derived from the app's declared name
77
+ - Canonical `/apps/:app_id` hex URL always still resolves as a fallback
78
+ - Human-readable aliases like `/tutorial/philosophy`
79
+ - Hot-reload: change file, re-run command
80
+ - Persistent until `streamweaver stop`
81
+
82
+ ## CLI Commands
83
+
84
+ | Command | Description |
85
+ |---------|-------------|
86
+ | `streamweaver <file.rb>` | Run app (auto-starts service) |
87
+ | `streamweaver run --name "My App" <file>` | Run with custom name |
88
+ | `streamweaver list` | List all loaded apps |
89
+ | `streamweaver remove <app_id>` | Remove specific app |
90
+ | `streamweaver clear` | Remove all apps |
91
+ | `streamweaver admin` | Open admin dashboard |
92
+ | `streamweaver showcase` | Open examples browser |
93
+ | `streamweaver tutorial` | Open interactive tutorial |
94
+ | `streamweaver status` | Show service status |
95
+ | `streamweaver stop` | Stop background service |
96
+ | `streamweaver llm` | Output LLM documentation |
97
+
98
+ ## Service Architecture
99
+
100
+ ```
101
+ ┌─────────────────────────────────────────────────────────────┐
102
+ │ StreamWeaver Service │
103
+ │ (port 4567) │
104
+ ├─────────────────────────────────────────────────────────────┤
105
+ │ /apps/hello-world (a1b2c3d4) → hello_world.rb │
106
+ │ /apps/todo-list (e5f6g7h8) → todo_list.rb │
107
+ │ /apps/form-demo (i9j0k1l2) → form_demo.rb │
108
+ │ │
109
+ │ Aliases: │
110
+ │ /tutorial/philosophy → /apps/m3n4o5p6 │
111
+ │ /examples/hello_world → /apps/q7r8s9t0 │
112
+ ├─────────────────────────────────────────────────────────────┤
113
+ │ Admin Dashboard: /admin │
114
+ └─────────────────────────────────────────────────────────────┘
115
+ ```
116
+
117
+ ### How Apps Are Loaded
118
+
119
+ 1. **CLI calls `/load-app`** with file path and optional name/source
120
+ 2. **Service evaluates** the Ruby file in isolation
121
+ 3. **App gets a unique hex ID** (8-char hash) and a human-readable slug derived
122
+ from its declared name (falling back to the filename); colliding slugs
123
+ from different files get a numeric suffix (`-2`, `-3`, ...); re-loading the
124
+ same file reuses its existing slug
125
+ 4. **Browser opens** to `/apps/:slug` (or `/apps/:app_id` / an aliased URL)
126
+
127
+ ### Aliased URLs
128
+
129
+ Apps can have human-readable URLs:
130
+
131
+ ```ruby
132
+ # Internal: loads app with source="tutorial", name="tutorial/philosophy"
133
+ load_app_via_service(temp_file, source: "tutorial", name: "tutorial/philosophy")
134
+
135
+ # Results in alias: /tutorial/philosophy → /apps/a1b2c3d4
136
+ ```
137
+
138
+ ## Tutorial Integration
139
+
140
+ The interactive tutorial (`streamweaver tutorial`) demonstrates service integration:
141
+
142
+ ```
143
+ ┌────────────────────────────────────────────────────────────┐
144
+ │ Tutorial App (standalone on port 4567) │
145
+ ├────────────────────────────────────────────────────────────┤
146
+ │ ┌──────────────────┬─────────────────────────────────────┐│
147
+ │ │ Navigation │ Code Editor ││
148
+ │ │ - Philosophy │ ┌─────────────────────────────────┐││
149
+ │ │ - Hello World │ │ header1 "Welcome!" │││
150
+ │ │ - Getting Input │ │ text_field :name │││
151
+ │ │ - ... │ │ ... │││
152
+ │ │ │ └─────────────────────────────────┘││
153
+ │ │ │ [Check] [Reset] [Run] [Open] [Stop]││
154
+ │ └──────────────────┴─────────────────────────────────────┘│
155
+ └────────────────────────────────────────────────────────────┘
156
+
157
+ │ Click "Run" → Loads code into service
158
+
159
+ ┌────────────────────────────────────────────────────────────┐
160
+ │ StreamWeaver Service (port 4567) │
161
+ ├────────────────────────────────────────────────────────────┤
162
+ │ /tutorial/philosophy → User's edited code running │
163
+ │ /tutorial/hello_world → Another lesson's code │
164
+ └────────────────────────────────────────────────────────────┘
165
+ ```
166
+
167
+ **Flow:**
168
+ 1. User edits code in tutorial's CodeMirror editor
169
+ 2. Clicks "Run" → Tutorial writes temp file, calls service `/load-app`
170
+ 3. Service loads app, returns URL
171
+ 4. Tutorial opens browser to `/tutorial/philosophy`
172
+ 5. User sees their code running live
173
+ 6. Click "Stop" to unload from service
174
+
175
+ ## Examples Browser Integration
176
+
177
+ The examples browser (`streamweaver showcase`) works similarly:
178
+
179
+ - Displays categorized examples with syntax-highlighted previews
180
+ - "Run" loads example into service
181
+ - "Stop" unloads from service
182
+ - Multiple examples can run simultaneously
183
+
184
+ ## Use Cases
185
+
186
+ ### Quick One-Off Script
187
+
188
+ ```bash
189
+ # Just run it directly
190
+ ruby my_tool.rb
191
+ ```
192
+
193
+ ### Development Session
194
+
195
+ ```bash
196
+ # Start working on an app
197
+ streamweaver my_app.rb
198
+
199
+ # Edit code, re-run to hot-reload
200
+ streamweaver my_app.rb
201
+
202
+ # Check what's loaded
203
+ streamweaver list
204
+
205
+ # Clean up when done
206
+ streamweaver stop
207
+ ```
208
+
209
+ ### Learning StreamWeaver
210
+
211
+ ```bash
212
+ # Interactive tutorial
213
+ streamweaver tutorial
214
+
215
+ # Browse and run examples
216
+ streamweaver showcase
217
+ ```
218
+
219
+ ### Comparing Implementations
220
+
221
+ ```bash
222
+ # Load multiple versions
223
+ streamweaver v1/dashboard.rb
224
+ streamweaver v2/dashboard.rb
225
+
226
+ # Open both in browser tabs
227
+ streamweaver list # Shows URLs for both
228
+ ```
229
+
230
+ ## Session State
231
+
232
+ **Important:** Each app has isolated session state.
233
+
234
+ - Standalone scripts: Session in browser cookie per port
235
+ - Service mode: Session per app_id (apps don't share state)
236
+ - Tutorial/Examples: Playground apps are independent of the host app
237
+
238
+ ## Agentic Mode with Service
239
+
240
+ For AI agent workflows, standalone mode is typically simpler:
241
+
242
+ ```ruby
243
+ # Agent runs this, waits for response
244
+ result = app "Quick Survey" do
245
+ text_field :feedback
246
+ select :rating, ["1", "2", "3", "4", "5"]
247
+ end.run_once!
248
+
249
+ puts result.inspect
250
+ # => { "feedback" => "Great!", "rating" => "5" }
251
+ ```
252
+
253
+ Service mode can be used for persistent agent UIs that need to run alongside other apps.
254
+
255
+ ## Troubleshooting
256
+
257
+ ### Service won't start
258
+
259
+ ```bash
260
+ # Check if already running
261
+ streamweaver status
262
+
263
+ # Stop and restart
264
+ streamweaver stop
265
+ streamweaver serve # Foreground mode for debugging
266
+ ```
267
+
268
+ ### App not updating after code change
269
+
270
+ ```bash
271
+ # Re-run to hot-reload
272
+ streamweaver my_app.rb
273
+
274
+ # Or remove and re-add
275
+ streamweaver remove <app_id>
276
+ streamweaver my_app.rb
277
+ ```
278
+
279
+ ### Port conflict
280
+
281
+ ```bash
282
+ # Service uses 4575 by default
283
+ # Standalone scripts auto-detect free ports starting at 4567
284
+ # If 4575 is in use, stop other service or change port:
285
+ streamweaver serve -p 4576
286
+ ```
287
+
288
+ ### Session state persists unexpectedly
289
+
290
+ Browser cookies persist across server restarts. To reset:
291
+ 1. Clear browser cookies for localhost
292
+ 2. Use incognito mode
293
+ 3. Add reset button: `button "Reset" do |s| s.clear end`
294
+
295
+ ## Future: Claude Code Integration
296
+
297
+ *Documentation for Claude Code integration patterns coming soon.*
298
+
299
+ Key areas:
300
+ - Using `run_once!` for form collection
301
+ - Building persistent agent UIs via service mode
302
+ - Patterns for multi-step agent workflows