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,468 @@
1
+ /* Design Review — component-parity port of a claude.ai-hosted Artifact
2
+ * (an editorial "design review" document: numbered sections, option cards
3
+ * with chips, a comparison matrix, and a verified/unverified checklist
4
+ * split). See docs/porting-artifacts.md for the general porting process
5
+ * this file is an example of.
6
+ *
7
+ * ONE stylesheet, targeting ONLY stable sw- hooks (the structural set is
8
+ * documented in docs/theming-hooks.md; the doc-component hooks used here
9
+ * are stable but not yet documented there -- stream_weaver-d11) plus this file's own ad- prefixed classes for
10
+ * the handful of elements with no dedicated component (chips, checklist
11
+ * tiles, meta-row, legend, footer, sources). No specificity workaround
12
+ * anywhere -- every framework rule lives in @layer stream-weaver, so this
13
+ * plain unlayered stylesheet always wins regardless of document order.
14
+ *
15
+ * Palette/type values transcribed directly from the source artifact's own
16
+ * <style> block (both light and dark custom-property sets). Renamed to an
17
+ * ad- prefix so these custom properties can never collide with
18
+ * StreamWeaver's own --sw-* tokens.
19
+ */
20
+
21
+ :root {
22
+ --ad-bg: #eef2f2;
23
+ --ad-surface: #ffffff;
24
+ --ad-surface-2: #e4eaea;
25
+ --ad-border: #d3dcdb;
26
+ --ad-ink: #14191b;
27
+ --ad-body: #333b3d;
28
+ --ad-muted: #677375;
29
+ --ad-accent: #2b6c7a;
30
+ --ad-accent-ink: #ffffff;
31
+ --ad-accent-soft: #dcedee;
32
+ --ad-accent-soft-border: #b7d6d9;
33
+ --ad-good: #3f7d4f;
34
+ --ad-good-soft: #e4f1e6;
35
+ --ad-mid: #9a6c17;
36
+ --ad-mid-soft: #f5ecd8;
37
+ --ad-weak: #b0503e;
38
+ --ad-weak-soft: #f6e4e0;
39
+ --ad-code-bg: #e7edec;
40
+ --ad-shadow: 0 1px 2px rgba(20, 25, 27, .06), 0 6px 16px -8px rgba(20, 25, 27, .12);
41
+ --ad-serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Charter, Georgia, serif;
42
+ --ad-mono: ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Menlo, Consolas, monospace;
43
+ }
44
+
45
+ /* OS-level dark preference -- fallback when no explicit toggle has run. */
46
+ @media (prefers-color-scheme: dark) {
47
+ :root {
48
+ --ad-bg: #14181a;
49
+ --ad-surface: #1b2123;
50
+ --ad-surface-2: #20282a;
51
+ --ad-border: #2c3639;
52
+ --ad-ink: #eef2f1;
53
+ --ad-body: #c6cdcc;
54
+ --ad-muted: #8b9a9a;
55
+ --ad-accent: #6fb8c4;
56
+ --ad-accent-ink: #0d2226;
57
+ --ad-accent-soft: #1c3437;
58
+ --ad-accent-soft-border: #2d5459;
59
+ --ad-good: #7fc190;
60
+ --ad-good-soft: #1c2f22;
61
+ --ad-mid: #d9ab5c;
62
+ --ad-mid-soft: #332a18;
63
+ --ad-weak: #e08670;
64
+ --ad-weak-soft: #33221e;
65
+ --ad-code-bg: #20282a;
66
+ --ad-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 24px -10px rgba(0, 0, 0, .5);
67
+ }
68
+ }
69
+
70
+ /* StreamWeaver's own manual toggle (theme_toggle) sets html.dark, not
71
+ the artifact's original data-theme attribute -- higher specificity
72
+ than :root, so it always wins over the media-query fallback above. */
73
+ html.dark {
74
+ --ad-bg: #14181a;
75
+ --ad-surface: #1b2123;
76
+ --ad-surface-2: #20282a;
77
+ --ad-border: #2c3639;
78
+ --ad-ink: #eef2f1;
79
+ --ad-body: #c6cdcc;
80
+ --ad-muted: #8b9a9a;
81
+ --ad-accent: #6fb8c4;
82
+ --ad-accent-ink: #0d2226;
83
+ --ad-accent-soft: #1c3437;
84
+ --ad-accent-soft-border: #2d5459;
85
+ --ad-good: #7fc190;
86
+ --ad-good-soft: #1c2f22;
87
+ --ad-mid: #d9ab5c;
88
+ --ad-mid-soft: #332a18;
89
+ --ad-weak: #e08670;
90
+ --ad-weak-soft: #33221e;
91
+ --ad-code-bg: #20282a;
92
+ --ad-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 24px -10px rgba(0, 0, 0, .5);
93
+ }
94
+
95
+ body {
96
+ background: var(--ad-bg);
97
+ color: var(--ad-body);
98
+ font-family: var(--ad-serif);
99
+ font-size: 16.5px;
100
+ line-height: 1.65;
101
+ }
102
+
103
+ /* Neutralize the app chrome StreamWeaver normally wraps content in --
104
+ * `body.sw-layout-default` caps width/adds padding, and its `#app-container`
105
+ * child gets its OWN background/border/shadow (from --sw-color-bg-card,
106
+ * still keyed to the :doc theme's beige-light/warm-charcoal-dark palette,
107
+ * not this app's cool teal one) -- both would otherwise show through as a
108
+ * visible "card within a card" boundary around .ad-doc. .ad-doc becomes the
109
+ * sole layout/background authority so the page reads as one continuous
110
+ * edge-to-edge surface, matching the artifact. */
111
+ body[class*="sw-layout-"] {
112
+ max-width: none;
113
+ padding: 0;
114
+ background: var(--ad-bg);
115
+ }
116
+ #app-container {
117
+ background: transparent;
118
+ padding: 0;
119
+ margin: 0;
120
+ border: none;
121
+ box-shadow: none;
122
+ border-radius: 0;
123
+ max-width: none;
124
+ }
125
+
126
+ .ad-doc {
127
+ max-width: 860px;
128
+ margin: 0 auto;
129
+ padding: 2rem 1.5rem 6rem;
130
+ }
131
+
132
+ .ad-doc ::selection { background: var(--ad-accent-soft); color: var(--ad-ink); }
133
+
134
+ .ad-doc code {
135
+ font-family: var(--ad-mono);
136
+ background: var(--ad-code-bg);
137
+ border: 1px solid var(--ad-border);
138
+ border-radius: 3px;
139
+ padding: .08em .38em;
140
+ font-size: .87em;
141
+ color: var(--ad-ink);
142
+ }
143
+
144
+ .ad-doc a { color: var(--ad-accent); text-underline-offset: 3px; }
145
+ .ad-doc a:focus-visible { outline: 2px solid var(--ad-accent); outline-offset: 2px; border-radius: 2px; }
146
+
147
+ .ad-doc p,
148
+ .ad-doc .sw-markdown p { margin: .85rem 0; max-width: 65ch; color: var(--ad-body); }
149
+
150
+ /* ---------- Header (doc_header + hand-rolled dek/meta-row) ---------- */
151
+ .ad-doc .sw-doc-header {
152
+ padding: 0;
153
+ border: none;
154
+ box-shadow: none;
155
+ background: transparent;
156
+ }
157
+ .ad-doc .sw-doc-header__eyebrow {
158
+ font-family: var(--ad-mono);
159
+ font-size: .72rem;
160
+ letter-spacing: .14em;
161
+ text-transform: uppercase;
162
+ color: var(--ad-accent);
163
+ display: flex;
164
+ align-items: center;
165
+ gap: .6em;
166
+ }
167
+ .ad-doc .sw-doc-header__eyebrow::before {
168
+ content: "";
169
+ width: 1.4em;
170
+ height: 1px;
171
+ background: var(--ad-accent);
172
+ display: inline-block;
173
+ opacity: .55;
174
+ }
175
+ .ad-doc .sw-doc-header__title {
176
+ font-family: var(--ad-serif);
177
+ font-weight: 600;
178
+ font-size: clamp(1.8rem, 1.35rem + 1.9vw, 2.7rem);
179
+ line-height: 1.12;
180
+ letter-spacing: -.01em;
181
+ color: var(--ad-ink);
182
+ margin: .5rem 0 .6rem;
183
+ text-wrap: balance;
184
+ }
185
+ .ad-dek { font-size: 1.1rem; color: var(--ad-body); max-width: 62ch; margin: 0 0 1.6rem; }
186
+ .ad-meta-row {
187
+ display: flex;
188
+ flex-wrap: wrap;
189
+ gap: .5rem 1.4rem;
190
+ font-family: var(--ad-mono);
191
+ font-size: .78rem;
192
+ color: var(--ad-muted);
193
+ border-top: 1px solid var(--ad-border);
194
+ border-bottom: 1px solid var(--ad-border);
195
+ padding: .75rem 0;
196
+ margin-bottom: 1rem;
197
+ }
198
+ .ad-meta-label { color: var(--ad-body); font-weight: 600; margin-right: .3em; }
199
+
200
+ /* ---------- Section numbering ---------- */
201
+ .ad-doc .sw-doc-section-header { margin-top: 3.4rem; margin-bottom: 0; }
202
+ .ad-doc .sw-doc-section-header__eyebrow {
203
+ font-family: var(--ad-mono);
204
+ font-size: .72rem;
205
+ letter-spacing: .1em;
206
+ color: var(--ad-muted);
207
+ text-transform: uppercase;
208
+ }
209
+ /* The framework's own DocSectionHeader draws an extending horizontal rule
210
+ after the eyebrow label (a deliberate feature of that component) -- the
211
+ artifact's own section-num label is bare text with no rule. */
212
+ .ad-doc .sw-doc-section-header__eyebrow::after { display: none; content: none; }
213
+ .ad-doc .sw-doc-section-header__title {
214
+ font-family: var(--ad-serif);
215
+ font-size: 1.5rem;
216
+ font-weight: 600;
217
+ color: var(--ad-ink);
218
+ letter-spacing: -.005em;
219
+ text-wrap: balance;
220
+ margin: .3rem 0 0;
221
+ }
222
+ /* Sections 01/05 have only an eyebrow line, no second headline. */
223
+ .ad-doc .sw-doc-section-header__title:empty { display: none; }
224
+
225
+ /* ---------- Callout (section 01 framing box) ---------- */
226
+ .ad-doc .sw-callout {
227
+ background: var(--ad-surface);
228
+ border: 1px solid var(--ad-border);
229
+ border-left: 3px solid var(--ad-accent);
230
+ border-radius: 4px;
231
+ padding: 1.1rem 1.3rem;
232
+ box-shadow: var(--ad-shadow);
233
+ }
234
+ .ad-doc .sw-callout__icon { display: none; }
235
+ .ad-doc .sw-callout__title {
236
+ color: var(--ad-accent);
237
+ font-size: .75rem;
238
+ letter-spacing: .12em;
239
+ text-transform: uppercase;
240
+ font-family: var(--ad-mono);
241
+ margin-bottom: .5rem;
242
+ }
243
+ .ad-doc .sw-callout__content p { margin: .4rem 0; }
244
+
245
+ /* Recommendation panel -- stronger accent-soft version of the same idiom. */
246
+ .ad-reco .sw-callout {
247
+ background: var(--ad-accent-soft);
248
+ border: 1px solid var(--ad-accent-soft-border);
249
+ border-left: 4px solid var(--ad-accent);
250
+ border-radius: 5px;
251
+ padding: 1.4rem 1.6rem;
252
+ }
253
+ .ad-reco .sw-callout__title { color: var(--ad-accent); }
254
+ .ad-reco h3 {
255
+ font-family: var(--ad-serif);
256
+ color: var(--ad-ink);
257
+ font-size: 1.15rem;
258
+ font-weight: 600;
259
+ margin: .9rem 0 .3rem;
260
+ }
261
+
262
+ /* Dashed secondary aside -- deliberately quieter than .ad-reco. */
263
+ .ad-aside .sw-callout {
264
+ border: 1px dashed var(--ad-border);
265
+ border-radius: 5px;
266
+ padding: 1rem 1.2rem;
267
+ background: var(--ad-surface);
268
+ font-size: .95rem;
269
+ box-shadow: none;
270
+ }
271
+ .ad-aside .sw-callout__title { color: var(--ad-mid); }
272
+
273
+ /* ---------- Tables ---------- */
274
+ .ad-tbl-scroll { overflow-x: auto; border: 1px solid var(--ad-border); border-radius: 5px; box-shadow: var(--ad-shadow); }
275
+ .ad-doc .sw-table {
276
+ width: 100%;
277
+ border-collapse: collapse;
278
+ background: var(--ad-surface);
279
+ min-width: 640px;
280
+ font-family: var(--ad-serif);
281
+ }
282
+ .ad-doc .sw-table.mono { font-family: var(--ad-mono); }
283
+ .ad-doc .sw-table thead th {
284
+ text-align: left;
285
+ font-family: var(--ad-mono);
286
+ font-size: .72rem;
287
+ letter-spacing: .08em;
288
+ text-transform: uppercase;
289
+ color: var(--ad-muted);
290
+ background: var(--ad-surface-2);
291
+ padding: .7rem .9rem;
292
+ border-bottom: 1px solid var(--ad-border);
293
+ white-space: nowrap;
294
+ }
295
+ .ad-doc .sw-table tbody td {
296
+ padding: .75rem .9rem;
297
+ border-bottom: 1px solid var(--ad-border);
298
+ font-size: .92rem;
299
+ vertical-align: top;
300
+ color: var(--ad-body);
301
+ }
302
+ .ad-doc .sw-table tbody tr:last-child td { border-bottom: none; }
303
+ .ad-doc .sw-table tbody td:first-child { font-weight: 600; color: var(--ad-ink); white-space: nowrap; }
304
+
305
+ /* Comparison-matrix "pick" row (Option F is always the last row). */
306
+ .ad-matrix-table tbody tr:last-child { background: var(--ad-accent-soft); }
307
+ .ad-matrix-table tbody tr:last-child td:first-child { color: var(--ad-accent); }
308
+
309
+ .ad-cell-rating { display: flex; align-items: baseline; gap: .5em; }
310
+
311
+ /* ---------- Option cards ---------- */
312
+ .ad-option.sw-card {
313
+ background: var(--ad-surface);
314
+ border: 1px solid var(--ad-border);
315
+ border-radius: 6px;
316
+ box-shadow: var(--ad-shadow);
317
+ padding: 1.5rem 1.6rem 1.7rem;
318
+ margin-top: 1.4rem;
319
+ }
320
+ .ad-option--pick.sw-card {
321
+ border-color: var(--ad-accent-soft-border);
322
+ background: linear-gradient(var(--ad-accent-soft), var(--ad-accent-soft)), var(--ad-surface);
323
+ }
324
+ .ad-option .sw-card-header,
325
+ .ad-option .card-header {
326
+ display: grid;
327
+ grid-template-columns: 2.1rem 1fr auto;
328
+ column-gap: .9rem;
329
+ align-items: start;
330
+ /* Framework's .card-header--badged paints a shaded band (--sw-surface-elevated,
331
+ falls back to a hardcoded beige) behind badge/title/subtitle -- the artifact's
332
+ option-card header sits directly on the plain white card surface. */
333
+ background: transparent;
334
+ border-bottom: none;
335
+ }
336
+ .ad-option .card-header__badge {
337
+ grid-column: 1;
338
+ grid-row: 1 / 3;
339
+ width: 2.1rem;
340
+ height: 2.1rem;
341
+ border: 1.5px solid var(--ad-border);
342
+ border-radius: 4px;
343
+ display: flex;
344
+ align-items: center;
345
+ justify-content: center;
346
+ font-family: var(--ad-mono);
347
+ font-weight: 700;
348
+ font-size: 1rem;
349
+ color: var(--ad-muted);
350
+ /* Framework default tints this with --sw-accent at 12% -- the artifact's
351
+ .opt-badge has no fill of its own, just a border on the plain card surface. */
352
+ background: transparent;
353
+ margin-top: .1rem;
354
+ }
355
+ .ad-option--pick .card-header__badge { border-color: var(--ad-accent); color: var(--ad-accent); }
356
+ .ad-option .card-header__title {
357
+ grid-column: 2;
358
+ grid-row: 1;
359
+ font-family: var(--ad-serif);
360
+ font-size: 1.22rem;
361
+ font-weight: 600;
362
+ color: var(--ad-ink);
363
+ margin: 0;
364
+ text-wrap: balance;
365
+ }
366
+ .ad-option .card-header__meta,
367
+ .ad-option .ad-option-mech {
368
+ grid-column: 2;
369
+ grid-row: 2;
370
+ margin: .15rem 0 0;
371
+ color: var(--ad-muted);
372
+ font-size: .94rem;
373
+ font-family: var(--ad-serif);
374
+ }
375
+ .ad-option .ad-option-mech p { margin: 0; }
376
+ .ad-option .ad-option-mech code { font-size: .87em; }
377
+ .ad-option .sw-badge {
378
+ grid-column: 3;
379
+ grid-row: 1 / 3;
380
+ align-self: start;
381
+ justify-self: end;
382
+ font-family: var(--ad-mono);
383
+ font-size: .68rem;
384
+ letter-spacing: .1em;
385
+ text-transform: uppercase;
386
+ color: var(--ad-accent-ink);
387
+ background: var(--ad-accent);
388
+ padding: .22em .55em;
389
+ border-radius: 3px;
390
+ white-space: nowrap;
391
+ }
392
+
393
+ .ad-chips { display: flex; flex-wrap: wrap; gap: .45rem .5rem; margin: 1.05rem 0 .2rem; }
394
+ .ad-chip {
395
+ display: inline-flex;
396
+ align-items: center;
397
+ gap: .4em;
398
+ font-family: var(--ad-mono);
399
+ font-size: .74rem;
400
+ padding: .28em .6em .28em .5em;
401
+ border-radius: 3px;
402
+ border: 1px solid var(--ad-border);
403
+ background: var(--ad-surface-2);
404
+ color: var(--ad-body);
405
+ line-height: 1.3;
406
+ }
407
+ .ad-chip-dim { color: var(--ad-muted); text-transform: uppercase; letter-spacing: .05em; font-size: .9em; }
408
+ .ad-chip .sw-status-dot { width: .5em; height: .5em; }
409
+
410
+ .ad-option .sw-card-body p { margin: .9rem 0 0; font-size: .98rem; }
411
+
412
+ /* Semantic status-dot color mapping (good/mid/weak), reused in chips,
413
+ the legend, and the matrix table's rating cells. */
414
+ .ad-doc .sw-status-dot-green { background: var(--ad-good); }
415
+ .ad-doc .sw-status-dot-yellow { background: var(--ad-mid); }
416
+ .ad-doc .sw-status-dot-red { background: var(--ad-weak); }
417
+
418
+ /* ---------- Legend (section 04) ---------- */
419
+ .ad-legend { display: flex; flex-wrap: wrap; gap: 1.2rem; margin: .6rem 0 1rem; font-family: var(--ad-mono); font-size: .76rem; color: var(--ad-muted); }
420
+ .ad-legend-item { display: inline-flex; align-items: center; gap: .4em; }
421
+ .ad-legend-item .sw-status-dot { width: .55em; height: .55em; }
422
+
423
+ /* ---------- Split grid + checklist tiles (section 06) ---------- */
424
+ .ad-split.sw-columns { gap: 1.2rem; margin-top: 1rem; }
425
+ @media (max-width: 700px) {
426
+ .ad-split.sw-columns { flex-direction: column; }
427
+ }
428
+ .ad-col-h { font-family: var(--ad-mono); font-size: .72rem; letter-spacing: .09em; text-transform: uppercase; margin-bottom: .6rem; display: block; }
429
+ .ad-col-h--v { color: var(--ad-good); }
430
+ .ad-col-h--u { color: var(--ad-mid); }
431
+
432
+ .ad-checklist { display: flex; flex-direction: column; gap: .6rem; }
433
+ .ad-check-item {
434
+ background: var(--ad-surface);
435
+ border: 1px solid var(--ad-border);
436
+ border-radius: 5px;
437
+ padding: .7rem .85rem;
438
+ font-size: .89rem;
439
+ display: flex;
440
+ gap: .6rem;
441
+ box-shadow: var(--ad-shadow);
442
+ color: var(--ad-body);
443
+ }
444
+ .ad-check-item p { margin: 0; }
445
+ .ad-check-mark { flex: none; width: 1.1rem; text-align: center; font-family: var(--ad-mono); font-weight: 700; }
446
+ .ad-checklist--verified .ad-check-mark { color: var(--ad-good); }
447
+ .ad-checklist--unverified .ad-check-mark { color: var(--ad-mid); }
448
+
449
+ /* ---------- Sources / footer ---------- */
450
+ .ad-sources { margin-top: 1rem; font-family: var(--ad-mono); font-size: .78rem; line-height: 1.9; color: var(--ad-muted); word-break: break-word; }
451
+ /* The shared `.ad-doc p { max-width: 65ch }` prose rule was truncating this
452
+ block to a narrow column, wrapping every URL -- the artifact's own
453
+ .sources div has no <p> inside it at all (bare text), so it never hit
454
+ that rule; ours goes through `md`, which always wraps in <p>. */
455
+ .ad-sources p { margin: 0; max-width: none; }
456
+
457
+ .ad-footer {
458
+ margin-top: 4rem;
459
+ padding-top: 1.4rem;
460
+ border-top: 1px solid var(--ad-border);
461
+ font-family: var(--ad-mono);
462
+ font-size: .76rem;
463
+ color: var(--ad-muted);
464
+ display: flex;
465
+ justify-content: space-between;
466
+ flex-wrap: wrap;
467
+ gap: .5rem;
468
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Bundled copy of the design-review proof example (see canonical source at
5
+ # examples/components/design_review_demo.rb + design_review_dsl.rb +
6
+ # design_review.css). Duplicated here -- rather than referenced by relative
7
+ # path -- so the skill stays self-contained when installed as a gem or
8
+ # copied in isolation from the rest of the repo.
9
+ #
10
+ # Demonstrates: a full bespoke re-skin (one unlayered CSS file targeting
11
+ # only stable sw- hooks; doc-component hook documentation is tracked in
12
+ # stream_weaver-d11) reaching 1:1 visual parity with a claude.ai-
13
+ # hosted Artifact for the "editorial design review" genre -- option cards
14
+ # with status-dot chips, a picked/winning state reused across both a card
15
+ # and a table row, and checklist tiles with no dedicated component. See
16
+ # docs/porting-artifacts.md for the process this was built through.
17
+ #
18
+ # Run: ruby design-review-example.rb
19
+
20
+ require_relative "../../../../stream_weaver"
21
+
22
+ DSL_PATH = File.join(__dir__, "design-review-example_dsl.rb")
23
+ CSS_PATH = File.join(__dir__, "design-review-example.css")
24
+
25
+ # Uses StreamWeaver::App.new directly (not the top-level `app` helper) --
26
+ # the helper's fixed kwarg list has no assets_dirs:, and App#script_dir is
27
+ # derived from its *direct* caller's file, which resolves wrong when routed
28
+ # through the helper. See docs/porting-artifacts.md, step (d).
29
+ DesignReviewExample = StreamWeaver::App.new(
30
+ "Design Review — Wayfinder & Beacon",
31
+ theme: :doc,
32
+ stylesheets: [CSS_PATH],
33
+ assets_dirs: [__dir__]
34
+ ) do
35
+ theme_toggle mode: :auto
36
+ instance_eval(File.read(DSL_PATH), DSL_PATH)
37
+ end.generate
38
+
39
+ DesignReviewExample.run! if __FILE__ == $0