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,555 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StreamWeaver
4
+ class Theme
5
+ # Curated theme presets for visual skills components.
6
+ # Each preset is a data-only definition: font pairings + color palette.
7
+ # Presets do NOT contain rendering logic -- they are consumed by
8
+ # Theme#apply_preset which sets CSS custom properties.
9
+ #
10
+ # sw- CSS prefix convention:
11
+ # All visual skills CSS classes MUST use the sw- prefix.
12
+ # BEM-style modifiers: sw-component--variant (e.g. sw-card--hero)
13
+ # State classes: sw-is-active, sw-is-selected
14
+ module Presets
15
+ # Editorial preset: magazine-style with serif display font
16
+ # Instrument Serif + JetBrains Mono, Terracotta + sage palette
17
+ EDITORIAL = {
18
+ name: :editorial,
19
+ label: "Editorial",
20
+ description: "Magazine-style with serif display font",
21
+ fonts: {
22
+ display: "'Instrument Serif', Georgia, serif",
23
+ body: "'Source Sans 3', system-ui, sans-serif",
24
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
25
+ },
26
+ google_fonts: [
27
+ "Instrument+Serif:ital@0;1",
28
+ "JetBrains+Mono:wght@400;500;600",
29
+ "Source+Sans+3:wght@400;500;600;700"
30
+ ],
31
+ colors: {
32
+ light: {
33
+ bg: "#faf8f5",
34
+ surface: "#ffffff",
35
+ surface_elevated: "#f5f3f0",
36
+ border: "#e8e4df",
37
+ text: "#1a1a1a",
38
+ text_dim: "#6b6560",
39
+ accent: "#c2410c",
40
+ node_a: "#c2410c",
41
+ node_b: "#0d9488",
42
+ node_c: "#7c3aed",
43
+ success: "#16a34a",
44
+ warning: "#d97706",
45
+ error: "#dc2626",
46
+ info: "#2563eb"
47
+ },
48
+ dark: {
49
+ bg: "#1a1816",
50
+ surface: "#262220",
51
+ surface_elevated: "#332e2b",
52
+ border: "rgba(255, 255, 255, 0.1)",
53
+ text: "#f5f0eb",
54
+ text_dim: "#a89f97",
55
+ accent: "#f97316",
56
+ node_a: "#f97316",
57
+ node_b: "#2dd4bf",
58
+ node_c: "#a78bfa",
59
+ success: "#22c55e",
60
+ warning: "#fbbf24",
61
+ error: "#f87171",
62
+ info: "#60a5fa"
63
+ }
64
+ }
65
+ }.freeze
66
+
67
+ # Technical preset: clean sans-serif for data-heavy content
68
+ # DM Sans + Fira Code, Teal + slate palette
69
+ TECHNICAL = {
70
+ name: :technical,
71
+ label: "Technical",
72
+ description: "Clean sans-serif for data-heavy content",
73
+ fonts: {
74
+ display: "'DM Sans', system-ui, sans-serif",
75
+ body: "'DM Sans', system-ui, sans-serif",
76
+ mono: "'Fira Code', 'JetBrains Mono', monospace"
77
+ },
78
+ google_fonts: [
79
+ "DM+Sans:wght@400;500;600;700",
80
+ "Fira+Code:wght@400;500;600"
81
+ ],
82
+ colors: {
83
+ light: {
84
+ bg: "#f8fafc",
85
+ surface: "#ffffff",
86
+ surface_elevated: "#f1f5f9",
87
+ border: "#e2e8f0",
88
+ text: "#0f172a",
89
+ text_dim: "#64748b",
90
+ accent: "#0d9488",
91
+ node_a: "#0d9488",
92
+ node_b: "#6366f1",
93
+ node_c: "#ec4899",
94
+ success: "#16a34a",
95
+ warning: "#d97706",
96
+ error: "#dc2626",
97
+ info: "#2563eb"
98
+ },
99
+ dark: {
100
+ bg: "#0f172a",
101
+ surface: "#1e293b",
102
+ surface_elevated: "#334155",
103
+ border: "rgba(255, 255, 255, 0.1)",
104
+ text: "#f1f5f9",
105
+ text_dim: "#94a3b8",
106
+ accent: "#2dd4bf",
107
+ node_a: "#2dd4bf",
108
+ node_b: "#818cf8",
109
+ node_c: "#f472b6",
110
+ success: "#22c55e",
111
+ warning: "#fbbf24",
112
+ error: "#f87171",
113
+ info: "#60a5fa"
114
+ }
115
+ }
116
+ }.freeze
117
+
118
+ # Warm preset: friendly rounded aesthetic with warm tones
119
+ # Nunito + Source Serif 4 + JetBrains Mono, Amber + warm gray palette
120
+ WARM = {
121
+ name: :warm,
122
+ label: "Warm",
123
+ description: "Friendly rounded aesthetic with warm tones",
124
+ fonts: {
125
+ display: "'Nunito', system-ui, sans-serif",
126
+ body: "'Source Serif 4', Georgia, serif",
127
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
128
+ },
129
+ google_fonts: [
130
+ "Nunito:wght@400;600;700;800",
131
+ "Source+Serif+4:wght@400;500;600",
132
+ "JetBrains+Mono:wght@400;500"
133
+ ],
134
+ colors: {
135
+ light: {
136
+ bg: "#fdf8f3",
137
+ surface: "#ffffff",
138
+ surface_elevated: "#faf3eb",
139
+ border: "#e8ddd0",
140
+ text: "#2d1f10",
141
+ text_dim: "#7a6b5d",
142
+ accent: "#d97706",
143
+ node_a: "#d97706",
144
+ node_b: "#059669",
145
+ node_c: "#9333ea",
146
+ success: "#16a34a",
147
+ warning: "#ea580c",
148
+ error: "#dc2626",
149
+ info: "#2563eb"
150
+ },
151
+ dark: {
152
+ bg: "#1c1714",
153
+ surface: "#2a2420",
154
+ surface_elevated: "#38302a",
155
+ border: "rgba(255, 255, 255, 0.1)",
156
+ text: "#f5ede4",
157
+ text_dim: "#b0a090",
158
+ accent: "#fbbf24",
159
+ node_a: "#fbbf24",
160
+ node_b: "#34d399",
161
+ node_c: "#c084fc",
162
+ success: "#22c55e",
163
+ warning: "#fb923c",
164
+ error: "#f87171",
165
+ info: "#60a5fa"
166
+ }
167
+ }
168
+ }.freeze
169
+
170
+ # Minimal preset: ultra-clean Swiss-inspired design
171
+ # Inter + Inter, monochrome with subtle accent
172
+ MINIMAL = {
173
+ name: :minimal,
174
+ label: "Minimal",
175
+ description: "Ultra-clean Swiss-inspired design",
176
+ fonts: {
177
+ display: "'Inter', system-ui, sans-serif",
178
+ body: "'Inter', system-ui, sans-serif",
179
+ mono: "'IBM Plex Mono', 'Menlo', monospace"
180
+ },
181
+ google_fonts: [
182
+ "Inter:wght@400;500;600;700",
183
+ "IBM+Plex+Mono:wght@400;500"
184
+ ],
185
+ colors: {
186
+ light: {
187
+ bg: "#ffffff",
188
+ surface: "#fafafa",
189
+ surface_elevated: "#f5f5f5",
190
+ border: "#e5e5e5",
191
+ text: "#171717",
192
+ text_dim: "#737373",
193
+ accent: "#171717",
194
+ node_a: "#171717",
195
+ node_b: "#525252",
196
+ node_c: "#a3a3a3",
197
+ success: "#16a34a",
198
+ warning: "#d97706",
199
+ error: "#dc2626",
200
+ info: "#2563eb"
201
+ },
202
+ dark: {
203
+ bg: "#0a0a0a",
204
+ surface: "#171717",
205
+ surface_elevated: "#262626",
206
+ border: "rgba(255, 255, 255, 0.1)",
207
+ text: "#fafafa",
208
+ text_dim: "#a3a3a3",
209
+ accent: "#fafafa",
210
+ node_a: "#fafafa",
211
+ node_b: "#d4d4d4",
212
+ node_c: "#737373",
213
+ success: "#22c55e",
214
+ warning: "#fbbf24",
215
+ error: "#f87171",
216
+ info: "#60a5fa"
217
+ }
218
+ }
219
+ }.freeze
220
+
221
+ # Terminal preset: retro terminal/hacker aesthetic
222
+ # JetBrains Mono everywhere, green-on-black palette
223
+ TERMINAL = {
224
+ name: :terminal,
225
+ label: "Terminal",
226
+ description: "Retro terminal aesthetic with monospace fonts",
227
+ fonts: {
228
+ display: "'JetBrains Mono', 'Fira Code', monospace",
229
+ body: "'JetBrains Mono', 'Fira Code', monospace",
230
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
231
+ },
232
+ google_fonts: [
233
+ "JetBrains+Mono:wght@400;500;600;700"
234
+ ],
235
+ colors: {
236
+ light: {
237
+ bg: "#f0f4f0",
238
+ surface: "#e8ede8",
239
+ surface_elevated: "#dde3dd",
240
+ border: "#c0ccc0",
241
+ text: "#1a2e1a",
242
+ text_dim: "#4a6a4a",
243
+ accent: "#16a34a",
244
+ node_a: "#16a34a",
245
+ node_b: "#0891b2",
246
+ node_c: "#a855f7",
247
+ success: "#16a34a",
248
+ warning: "#ca8a04",
249
+ error: "#dc2626",
250
+ info: "#0284c7"
251
+ },
252
+ dark: {
253
+ bg: "#0c0c0c",
254
+ surface: "#141414",
255
+ surface_elevated: "#1e1e1e",
256
+ border: "rgba(0, 255, 65, 0.15)",
257
+ text: "#00ff41",
258
+ text_dim: "#00b330",
259
+ accent: "#00ff41",
260
+ node_a: "#00ff41",
261
+ node_b: "#00d4ff",
262
+ node_c: "#d946ef",
263
+ success: "#00ff41",
264
+ warning: "#ffdd00",
265
+ error: "#ff3333",
266
+ info: "#00d4ff"
267
+ }
268
+ }
269
+ }.freeze
270
+
271
+ # Sketch preset: hand-drawn wireframe aesthetic
272
+ # Caveat (Google Fonts hand-drawn), rough.js borders via JS, Excalifont-style
273
+ # Special preset — renderer bypasses normal body-level font injection
274
+ # to keep non-wireframe content unaffected (C7).
275
+ SKETCH = {
276
+ name: :sketch,
277
+ label: "Sketch",
278
+ description: "Hand-drawn wireframe aesthetic with rough.js borders and hand-drawn font",
279
+ sketch: true,
280
+ fonts: {
281
+ display: "'Caveat', cursive",
282
+ body: "'Caveat', cursive",
283
+ mono: "monospace"
284
+ },
285
+ google_fonts: ["Caveat:wght@400;500;600;700"],
286
+ colors: {
287
+ light: {
288
+ bg: "#fafafa",
289
+ surface: "#ffffff",
290
+ surface_elevated: "#f5f5f5",
291
+ border: "#d1d5db",
292
+ text: "#1a1a2e",
293
+ text_dim: "#6b7280",
294
+ accent: "#3b82f6",
295
+ node_a: "#3b82f6",
296
+ node_b: "#10b981",
297
+ node_c: "#8b5cf6",
298
+ success: "#16a34a",
299
+ warning: "#d97706",
300
+ error: "#dc2626",
301
+ info: "#2563eb"
302
+ },
303
+ dark: {
304
+ bg: "#1a1a2e",
305
+ surface: "#16213e",
306
+ surface_elevated: "#0f3460",
307
+ border: "#374151",
308
+ text: "#f1f5f9",
309
+ text_dim: "#94a3b8",
310
+ accent: "#60a5fa",
311
+ node_a: "#60a5fa",
312
+ node_b: "#34d399",
313
+ node_c: "#a78bfa",
314
+ success: "#22c55e",
315
+ warning: "#fbbf24",
316
+ error: "#f87171",
317
+ info: "#60a5fa"
318
+ }
319
+ }
320
+ }.freeze
321
+
322
+ # Registry of all available presets
323
+ REGISTRY = {
324
+ editorial: EDITORIAL,
325
+ technical: TECHNICAL,
326
+ warm: WARM,
327
+ minimal: MINIMAL,
328
+ terminal: TERMINAL,
329
+ sketch: SKETCH
330
+ }.freeze
331
+
332
+ # Get a preset by name
333
+ #
334
+ # @param name [Symbol] Preset name
335
+ # @return [Hash, nil] Preset definition or nil
336
+ def self.get(name)
337
+ REGISTRY[name.to_sym]
338
+ end
339
+
340
+ # List all available preset names
341
+ #
342
+ # @return [Array<Symbol>]
343
+ def self.available
344
+ REGISTRY.keys
345
+ end
346
+
347
+ # Generate Google Fonts link URL for a preset
348
+ #
349
+ # @param preset [Hash] Preset definition
350
+ # @return [String] Google Fonts CSS URL
351
+ def self.google_fonts_url(preset)
352
+ families = preset[:google_fonts].map { |f| "family=#{f}" }.join("&")
353
+ "https://fonts.googleapis.com/css2?#{families}&display=swap"
354
+ end
355
+
356
+ # Generate CSS custom properties for a preset in the given mode
357
+ #
358
+ # @param preset [Hash] Preset definition
359
+ # @param mode [Symbol] :light or :dark
360
+ # @return [Hash] CSS variable name => value pairs (without -- prefix)
361
+ def self.css_variables(preset, mode: :light)
362
+ colors = preset[:colors][mode] || preset[:colors][:light]
363
+ fonts = preset[:fonts]
364
+
365
+ vars = {}
366
+ # Font variables
367
+ vars["--sw-font-display"] = fonts[:display]
368
+ vars["--sw-font-body"] = fonts[:body]
369
+ vars["--sw-font-mono"] = fonts[:mono]
370
+
371
+ # Color variables -- visual skills semantic tokens
372
+ vars["--sw-bg"] = colors[:bg]
373
+ vars["--sw-surface"] = colors[:surface]
374
+ vars["--sw-surface-elevated"] = colors[:surface_elevated]
375
+ vars["--sw-border"] = colors[:border]
376
+ vars["--sw-text"] = colors[:text]
377
+ vars["--sw-text-dim"] = colors[:text_dim]
378
+ vars["--sw-accent"] = colors[:accent]
379
+
380
+ # Node colors for diagrams
381
+ vars["--sw-node-a"] = colors[:node_a]
382
+ vars["--sw-node-b"] = colors[:node_b]
383
+ vars["--sw-node-c"] = colors[:node_c]
384
+
385
+ # Status colors
386
+ vars["--sw-success"] = colors[:success]
387
+ vars["--sw-warning"] = colors[:warning]
388
+ vars["--sw-error"] = colors[:error]
389
+ vars["--sw-info"] = colors[:info]
390
+
391
+ vars
392
+ end
393
+
394
+ # Generate a complete CSS block for a preset that applies to :root (light)
395
+ # and html.dark (dark mode). Also sets font-family on body elements.
396
+ #
397
+ # @param preset_name [Symbol] Preset name
398
+ # @return [String] CSS string with custom properties for both modes
399
+ def self.generate_preset_css(preset_name)
400
+ preset = get(preset_name)
401
+ return "" unless preset
402
+
403
+ light_vars = css_variables(preset, mode: :light)
404
+ dark_vars = css_variables(preset, mode: :dark)
405
+
406
+ light_block = light_vars.map { |k, v| " #{k}: #{v};" }.join("\n")
407
+ dark_block = dark_vars.map { |k, v| " #{k}: #{v};" }.join("\n")
408
+
409
+ fonts = preset[:fonts]
410
+
411
+ <<~CSS
412
+ /* Theme preset: #{preset[:label]} -- #{preset[:description]} */
413
+ :root {
414
+ #{light_block}
415
+ }
416
+ html.dark {
417
+ #{dark_block}
418
+ }
419
+ /* Apply preset fonts to body */
420
+ body {
421
+ font-family: #{fonts[:body]};
422
+ }
423
+ h1, h2, h3, h4, h5, h6 {
424
+ font-family: #{fonts[:display]};
425
+ }
426
+ code, pre, .sw-code-block {
427
+ font-family: #{fonts[:mono]};
428
+ }
429
+ CSS
430
+ end
431
+
432
+ # Generate CSS @keyframes and utility classes for animations.
433
+ # All classes use sw- prefix.
434
+ #
435
+ # @return [String] CSS with animation keyframes and utility classes
436
+ def self.animations_css
437
+ <<~CSS
438
+ /* ===========================================
439
+ StreamWeaver Animations (T15)
440
+ sw- prefixed animation utilities.
441
+ =========================================== */
442
+
443
+ /* Keyframes */
444
+ @keyframes sw-fadeIn {
445
+ from { opacity: 0; }
446
+ to { opacity: 1; }
447
+ }
448
+
449
+ @keyframes sw-slideUp {
450
+ from { opacity: 0; transform: translateY(20px); }
451
+ to { opacity: 1; transform: translateY(0); }
452
+ }
453
+
454
+ @keyframes sw-fadeScale {
455
+ from { opacity: 0; transform: scale(0.92); }
456
+ to { opacity: 1; transform: scale(1); }
457
+ }
458
+
459
+ @keyframes sw-shimmer {
460
+ 0% { background-position: -200% 0; }
461
+ 100% { background-position: 200% 0; }
462
+ }
463
+
464
+ @keyframes sw-slideDown {
465
+ from { opacity: 0; transform: translateY(-20px); }
466
+ to { opacity: 1; transform: translateY(0); }
467
+ }
468
+
469
+ /* Animation utility classes */
470
+ .sw-animate-fadeIn {
471
+ animation: sw-fadeIn 0.4s ease-out both;
472
+ }
473
+
474
+ .sw-animate-slideUp {
475
+ animation: sw-slideUp 0.5s ease-out both;
476
+ }
477
+
478
+ .sw-animate-fadeScale {
479
+ animation: sw-fadeScale 0.4s ease-out both;
480
+ }
481
+
482
+ .sw-animate-shimmer {
483
+ background: linear-gradient(
484
+ 90deg,
485
+ var(--sw-surface-elevated) 25%,
486
+ var(--sw-border) 50%,
487
+ var(--sw-surface-elevated) 75%
488
+ );
489
+ background-size: 200% 100%;
490
+ animation: sw-shimmer 1.5s ease-in-out infinite;
491
+ }
492
+
493
+ .sw-animate-slideDown {
494
+ animation: sw-slideDown 0.5s ease-out both;
495
+ }
496
+
497
+ /* Stagger delay helpers: apply to children for sequential reveal.
498
+ Usage: parent.sw-stagger > child elements get increasing delays.
499
+ Uses CSS custom property --sw-stagger-delay (default 80ms). */
500
+ .sw-stagger > :nth-child(1) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 0); }
501
+ .sw-stagger > :nth-child(2) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 1); }
502
+ .sw-stagger > :nth-child(3) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 2); }
503
+ .sw-stagger > :nth-child(4) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 3); }
504
+ .sw-stagger > :nth-child(5) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 4); }
505
+ .sw-stagger > :nth-child(6) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 5); }
506
+ .sw-stagger > :nth-child(7) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 6); }
507
+ .sw-stagger > :nth-child(8) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 7); }
508
+ .sw-stagger > :nth-child(9) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 8); }
509
+ .sw-stagger > :nth-child(10) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 9); }
510
+ .sw-stagger > :nth-child(11) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 10); }
511
+ .sw-stagger > :nth-child(12) { animation-delay: calc(var(--sw-stagger-delay, 80ms) * 11); }
512
+
513
+ /* Slide swap transitions */
514
+ .sw-slide-transition {
515
+ transition: opacity 0.3s ease-out, transform 0.3s ease-out;
516
+ }
517
+
518
+ .sw-slide-enter {
519
+ opacity: 0;
520
+ transform: translateX(20px);
521
+ }
522
+
523
+ .sw-slide-enter-active {
524
+ opacity: 1;
525
+ transform: translateX(0);
526
+ }
527
+
528
+ .sw-slide-exit {
529
+ opacity: 1;
530
+ transform: translateX(0);
531
+ }
532
+
533
+ .sw-slide-exit-active {
534
+ opacity: 0;
535
+ transform: translateX(-20px);
536
+ }
537
+
538
+ /* Reduce motion preference: disable all animations */
539
+ @media (prefers-reduced-motion: reduce) {
540
+ .sw-animate-fadeIn,
541
+ .sw-animate-slideUp,
542
+ .sw-animate-fadeScale,
543
+ .sw-animate-shimmer,
544
+ .sw-animate-slideDown {
545
+ animation: none !important;
546
+ }
547
+ .sw-slide-transition {
548
+ transition: none !important;
549
+ }
550
+ }
551
+ CSS
552
+ end
553
+ end
554
+ end
555
+ end