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,385 @@
1
+ # frozen_string_literal: true
2
+ # Inner DSL for the Calendar-Driven Travel State PRD.
3
+ # Intended for canvas-push: streamweaver canvas-push <session> < examples/components/prd_dsl.rb
4
+ # For standalone app with theme: ruby examples/components/prd_demo.rb
5
+
6
+ sidebar_toc sections: [
7
+ { id: "problem", label: "Problem Statement" },
8
+ { id: "principle", label: "Design Principle" },
9
+ { id: "architecture", label: "Architecture" },
10
+ { id: "c1", label: "Component 1: Enforcement" },
11
+ { id: "c2", label: "Component 2: Sync Script" },
12
+ { id: "c3", label: "Component 3: Checkin Gate" },
13
+ { id: "data-model", label: "Data Model" },
14
+ { id: "integrations", label: "Integration Points" },
15
+ { id: "scope", label: "Scope" },
16
+ { id: "success", label: "Success Criteria" },
17
+ { id: "open", label: "Open Questions" }
18
+ ]
19
+
20
+ doc_header(
21
+ eyebrow: "aria · Personal OS",
22
+ title: "Calendar-Driven Travel State",
23
+ pills: [
24
+ { text: "Draft" },
25
+ "June 25, 2026",
26
+ "Author: Maya Chen",
27
+ "Owner: scheduler secretary + aria_dev"
28
+ ]
29
+ )
30
+
31
+ # 01 — Problem Statement
32
+ doc_section_header "01", "Problem Statement", id: "problem"
33
+ md <<~MD
34
+ During the June 24 daily checkin, the grandmaster analysis fabricated "Austin, Texas"
35
+ as Maya's location throughout — she was in Frederick, Maryland. The cause was a
36
+ two-part failure:
37
+
38
+ 1. `current-state.yaml` didn't exist at checkin time, so Claude had no ground truth
39
+ 2. Claude pattern-matched "the Rio" (a Maryland venue) against prior journal context
40
+ that had mentioned Austin, and confabulated a coherent but entirely wrong narrative
41
+ MD
42
+ callout(variant: :warning, title: "Root cause:") do
43
+ text "Stale or absent location context causes Claude to infer location from indirect signals. " \
44
+ "Confident wrong inferences propagate silently through analysis — they don't look uncertain, " \
45
+ "they look authoritative."
46
+ end
47
+ md "The immediate fix (creating `current-state.yaml` and adding the Ask-Don't-Fabricate directive) " \
48
+ "addresses the symptom. This PRD addresses the cause: `current-state.yaml` was created as a " \
49
+ "manually-maintained file, which will inevitably go stale when juggling 20+ concurrent " \
50
+ "sessions with no bandwidth to remember to update a doc."
51
+
52
+ # 02 — Design Principle
53
+ doc_section_header "02", "Design Principle: Calendar Is Truth", id: "principle"
54
+ md "Maya already maintains two calendars — Outlook (work PTO, flights, meetings) and Google " \
55
+ "(family events). These are the existing ground truth for where she is and what she's doing. " \
56
+ "Rather than maintaining a parallel file, the system should read from what already exists."
57
+ mermaid <<~MERMAID
58
+ graph LR
59
+ A["Calendar<br/>Outlook + Google<br/><i>ground truth</i>"]
60
+ B["bin/sync-travel-state<br/>daily derivation"]
61
+ C["current-state.yaml<br/>read-only cache"]
62
+ D["Claude sessions<br/>consume, never write"]
63
+ A --> B --> C --> D
64
+ style A fill:#EEF2FF,stroke:#1E4ED8,color:#1E4ED8
65
+ MERMAID
66
+ callout(variant: :info, title: "Process change required:") do
67
+ text "Driving trips (e.g., Austin) have no flights to detect. The convention is: all travel — " \
68
+ "personal or work, driving or flying — must have an Outlook PTO block before the system " \
69
+ "will track it. The cabinet enforces this rather than relying on memory."
70
+ end
71
+
72
+ # 03 — Architecture
73
+ doc_section_header "03", "Architecture Overview", id: "architecture"
74
+ md "Three components work together. Each has a single responsibility."
75
+ table(
76
+ headers: ["Component", "Responsibility", "Owner", "Trigger"],
77
+ rows: [
78
+ ["Enforcement", "Require calendar entry before travel is acknowledged", "scheduler secretary", "Any travel mention"],
79
+ ["bin/sync-travel-state", "Read calendars → write current-state.yaml", "launchd / morning brief","Daily 6am + post-checkin"],
80
+ ["Checkin gate", "Human confirms derived state is accurate", "aria-checkin Step 0", "Every daily checkin"]
81
+ ]
82
+ )
83
+
84
+ # 04 — Component 1
85
+ doc_section_header "04", "Component 1: Calendar Entry Enforcement", id: "c1"
86
+ card do
87
+ card_header "Scheduler Secretary Behavior", badge: "C1", meta: "secretary work cycle + direct requests"
88
+ card_body do
89
+ md <<~MD
90
+ When travel is mentioned in any context — daily checkin narrative, voicenote, direct
91
+ message to scheduler — the secretary checks for a corresponding calendar entry before
92
+ acknowledging or routing the trip.
93
+
94
+ ### Detection Triggers
95
+
96
+ - User says "I'm going to X" / "we're traveling to X" / "trip to X"
97
+ - Voicenote mentions destination + date range
98
+ - Checkin narrative references upcoming travel not in calendar
99
+
100
+ ### Behavior: entry exists
101
+
102
+ Acknowledge and flag for sync script to pick up at next run. No further action.
103
+
104
+ ### Behavior: no entry found
105
+
106
+ Create the calendar entry via `aria-outlook` or `aria-google`, confirm with user,
107
+ then acknowledge. Secretary does _not_ write to `current-state.yaml` — that is
108
+ exclusively the sync script's domain.
109
+
110
+ #### Entry format (Outlook PTO)
111
+ MD
112
+ code_block(<<~TXT, lang: "text")
113
+ Title: Maya – PTO [Destination]
114
+ e.g., "Maya – PTO Maryland"
115
+ "Maya – PTO Austin"
116
+ Type: All-day event, multi-day
117
+ Calendar: Outlook personal
118
+ TXT
119
+ md <<~MD
120
+ #### Entry format (work travel)
121
+ MD
122
+ code_block(<<~TXT, lang: "text")
123
+ Title: [Trip name] e.g., "Meridian Analytics summer trip 2026"
124
+ Flight events are detected separately; PTO block still required
125
+ Type: All-day event
126
+ Calendar: Outlook work
127
+ TXT
128
+ md "### Type Inference Rules"
129
+ table(
130
+ headers: ["Title pattern", "Inferred type"],
131
+ rows: [
132
+ ["contains \"Meridian\" / \"work\" / trip name from work context", "work"],
133
+ ["\"Maya – PTO [Destination]\" with no work keywords", "vacation"],
134
+ ["Flight pair without PTO block (day trip)", "work"],
135
+ ["Google family calendar multi-day event", "vacation"]
136
+ ]
137
+ )
138
+ end
139
+ end
140
+
141
+ # 05 — Component 2
142
+ doc_section_header "05", "Component 2: bin/sync-travel-state", id: "c2"
143
+ card do
144
+ card_header "Calendar Sync Script", badge: "C2", meta: "bin/sync-travel-state · Ruby"
145
+ card_body do
146
+ md <<~MD
147
+ Reads both calendars, derives travel state, overwrites `current-state.yaml`.
148
+ Idempotent — safe to run multiple times per day.
149
+
150
+ ### Calendar Sources
151
+
152
+ - **Outlook** — via `aria-outlook calendar list`. Reads 60-day window. Detects: PTO
153
+ all-day events, flight events (title contains "flight" / airline names / airport codes).
154
+ - **Google** — via `aria-google calendar list`. Reads Maya's primary calendar + Sam's
155
+ shared calendar. Detects: multi-day events (family trips, shared PTO).
156
+
157
+ ### Detection Logic
158
+
159
+ - **Active travel:** any PTO event (Outlook) or multi-day non-recurring family event
160
+ (Google) that spans today's date
161
+ - **Upcoming trips:** PTO events or flight pairs within the next 60 days, grouped by
162
+ date proximity (±2 days = same trip)
163
+ - **Trip end date:** last day of PTO block or last flight's arrival date, whichever is later
164
+ - **Destination:** parsed from PTO event title suffix or location field, falling back to
165
+ flight arrival airport city
166
+
167
+ ### Schedule
168
+
169
+ - Daily at 6:00am via launchd (runs before any sessions likely to start)
170
+ - After daily checkin completes (hooked into checkin flow)
171
+ - Manual: `bin/sync-travel-state --force`
172
+
173
+ ### Staleness guard
174
+
175
+ If `aria-outlook` or `aria-google` returns an auth error (OAuth expired), the script
176
+ logs the failure and exits without overwriting the existing file. It emits a warning to
177
+ the COS inbox. It never writes a stale derivation.
178
+ MD
179
+ code_block(<<~SH, lang: "bash")
180
+ bin/sync-travel-state # normal run
181
+ bin/sync-travel-state --dry-run # print derived state, don't write
182
+ bin/sync-travel-state --force # run even if synced_at is recent
183
+ SH
184
+ end
185
+ end
186
+
187
+ # 06 — Component 3
188
+ doc_section_header "06", "Component 3: Checkin Verification Gate", id: "c3"
189
+ card do
190
+ card_header "Daily Checkin — Step 0", badge: "C3", meta: "bin/aria-checkin · before form opens"
191
+ card_body do
192
+ md <<~MD
193
+ A brief confirmation step added before the StreamWeaver form opens. Shows derived state
194
+ and asks for a binary confirm. Catches calendar errors before they flow into analysis.
195
+
196
+ ### When to show
197
+
198
+ - `travel.active: true` — confirm travel is still ongoing
199
+ - `travel.ends` is today or yesterday — confirm return status
200
+ - `synced_at` is >24h old — warn and offer to re-sync
201
+ - Upcoming trip starts within 3 days — surface it for awareness
202
+
203
+ ### When to skip
204
+
205
+ - `travel.active: false` and no trip starting within 3 days — no confirmation needed,
206
+ proceed directly to form
207
+
208
+ ### UI behavior
209
+
210
+ Single yes/no question added to the StreamWeaver form as a pre-flight card. Displayed
211
+ above the main form sections. Estimated time: 5 seconds.
212
+ MD
213
+ code_block(<<~TXT, lang: "text")
214
+ "Derived from calendar: traveling in Maryland through Jun 28.
215
+ Still accurate?"
216
+ → [Yes, continue] [No, something's wrong]
217
+ TXT
218
+ md "If the user selects \"No\": display a correction prompt, update the calendar entry " \
219
+ "(not the yaml directly), trigger `bin/sync-travel-state --force`, then proceed to the " \
220
+ "main form with updated context."
221
+ end
222
+ end
223
+
224
+ # 07 — Data Model
225
+ doc_section_header "07", "Data Model", id: "data-model"
226
+ callout(variant: :warning, title: "Do not hand-edit this file.") do
227
+ text "It is written exclusively by bin/sync-travel-state. Manual edits will be overwritten " \
228
+ "at next sync. For urgent corrections, update the source calendar entry and run " \
229
+ "bin/sync-travel-state --force."
230
+ end
231
+ md "### current-state.yaml schema"
232
+ code_block(<<~YAML, lang: "yaml")
233
+ # ~/aria-os/current-state.yaml
234
+ # DERIVED FROM CALENDAR — do not hand-edit.
235
+ # Run bin/sync-travel-state to refresh.
236
+
237
+ synced_at: "2026-06-25T06:00:00-07:00" # ISO8601, written by sync script
238
+
239
+ location:
240
+ current: "Frederick, MD" # from PTO event location or title suffix
241
+ home: "Ashland, OR" # static — set once in script config
242
+
243
+ # travel.active is the primary flag all Claude sessions check.
244
+ # true = away from home, any type. Repeating calendar events do not occur.
245
+ travel:
246
+ active: true
247
+ type: vacation # vacation | work | mixed
248
+ destination: "Maryland" # parsed from calendar
249
+ ends: "2026-06-28" # PTO end date
250
+ source_event_id: "AAMkADk1..." # Outlook/Google event ID for traceability
251
+ source_calendar: outlook # outlook | google
252
+
253
+ mode: vacation # normal | vacation | work-travel | deadline-crunch
254
+ # Note: deadline-crunch is the only mode not derivable from calendar.
255
+ # It must be set manually via: aria-cabinet cos-state set mode deadline-crunch
256
+
257
+ mode_implications:
258
+ hobby_teaching: skip # auto: true when travel.active is true
259
+ hobby_training: skip # auto: true when travel.type is vacation
260
+ calendar_note: >
261
+ Repeating events (volunteer tutoring, weekend pottery class, etc.) appear
262
+ on calendar but do not occur during travel. Do not log absences.
263
+
264
+ travel_schedule:
265
+ - destination: "Austin, TX"
266
+ start: "2026-07-11"
267
+ end: "2026-07-18"
268
+ type: vacation
269
+ source: outlook_pto
270
+ source_event_id: "BBMkADk2..."
271
+
272
+ - destination: "Denver, CO"
273
+ start: "2026-07-20"
274
+ end: null # return flight not yet booked
275
+ type: work
276
+ source: flight_pair
277
+ flight_departure: "2026-07-20T06:00-04:00"
278
+ flight_return: null
279
+ YAML
280
+ md <<~MD
281
+ ### Non-calendar context (separate file)
282
+
283
+ Data that cannot be derived from calendar — active work deadlines, upcoming notes —
284
+ lives in a separate file read by relevant secretaries:
285
+ MD
286
+ code_block(<<~YAML, lang: "yaml")
287
+ # ~/aria-os/cabinet/secretaries/cos/context.yaml
288
+ # Hand-maintained by COS secretary. Not overwritten by sync.
289
+
290
+ deadline_crunch_status:
291
+ status: "Board deck due Friday — deprioritizing non-essential secretary work"
292
+ review_meeting_planned: "2026-06-27"
293
+ YAML
294
+
295
+ # 08 — Integrations
296
+ doc_section_header "08", "Integration Points", id: "integrations"
297
+ md "### Systems that read current-state.yaml"
298
+ table(
299
+ headers: ["Consumer", "What it reads", "Purpose"],
300
+ rows: [
301
+ ["bin/aria-checkin", "travel, mode", "Step 0 verification gate; grandmaster analysis context"],
302
+ ["SessionStart hook", "synced_at, travel.ends", "Staleness warning before any session"],
303
+ ["CLAUDE.md directive", "location.current, travel.active", "Ground truth for location-sensitive reasoning"],
304
+ ["Hobby schedule reasoning", "travel.active, travel.type","Skip training/teaching when traveling"],
305
+ ["Scheduler secretary", "travel_schedule", "Plan-ahead awareness, avoid scheduling conflicts"]
306
+ ]
307
+ )
308
+ md <<~MD
309
+ ### SessionStart staleness check
310
+
311
+ Add to the SessionStart hook (alongside `bin/aria-session-nudge`):
312
+ MD
313
+ code_block(<<~'RUBY', lang: "ruby")
314
+ ruby -ryaml -rdate -e '
315
+ f = File.expand_path("~/aria-os/current-state.yaml")
316
+ exit unless File.exist?(f)
317
+ s = YAML.load_file(f)
318
+ synced = Date.parse(s["synced_at"].to_s.split("T").first) rescue nil
319
+ if synced && Date.today - synced > 1
320
+ puts "⚠️ current-state.yaml is stale (#{Date.today - synced}d) — run bin/sync-travel-state"
321
+ end
322
+ ends_str = s.dig("travel", "ends")
323
+ if ends_str && s.dig("travel", "active") && Date.parse(ends_str) < Date.today
324
+ puts "⚠️ travel.ends (#{ends_str}) is past but travel.active is true — run bin/sync-travel-state"
325
+ end
326
+ '
327
+ RUBY
328
+
329
+ # 09 — Scope
330
+ doc_section_header "09", "Scope", id: "scope"
331
+ comparison(before_label: "In Scope", after_label: "Out of Scope") do
332
+ before do
333
+ md <<~MD
334
+ - Outlook PTO event detection
335
+ - Google family calendar detection
336
+ - Outlook flight event detection
337
+ - Trip type inference from event titles
338
+ - Destination extraction from title/location field
339
+ - Checkin verification step
340
+ - Scheduler enforcement (require calendar entry)
341
+ - SessionStart staleness warning
342
+ - launchd schedule (6am daily)
343
+ MD
344
+ end
345
+ after do
346
+ md <<~MD
347
+ - Sub-day location tracking
348
+ - Multi-timezone handling
349
+ - Historical travel reconstruction
350
+ - Automatic deadline-crunch mode detection
351
+ - Seattle trip (not yet booked — tracks once calendar entry exists)
352
+ - Drive trip detection without PTO block (process rule: add PTO)
353
+ MD
354
+ end
355
+ end
356
+
357
+ # 10 — Success Criteria
358
+ doc_section_header "10", "Success Criteria", id: "success"
359
+ table(
360
+ headers: ["#", "Criterion"],
361
+ rows: [
362
+ ["SC1", "Zero location fabrications in grandmaster analysis after build — Claude reads ground truth or asks, never infers from indirect signals"],
363
+ ["SC2", "`current-state.yaml` reflects accurate travel state without manual updates on ≥90% of travel days"],
364
+ ["SC3", "Checkin verification gate catches any remaining discrepancies within 24h"],
365
+ ["SC4", "New travel appears in `current-state.yaml` within 24h of calendar entry creation"],
366
+ ["SC5", "Auth failures (OAuth expired) emit a COS inbox warning rather than silently writing stale data"],
367
+ ["SC6", "Hobby absence during travel is not logged — no false 'missed training' entries accumulate"]
368
+ ]
369
+ )
370
+
371
+ # 11 — Open Questions
372
+ doc_section_header "11", "Open Questions", id: "open"
373
+ table(
374
+ headers: ["#", "Question", "Context"],
375
+ rows: [
376
+ ["Q1", "aria-google headless auth",
377
+ "The sync script runs via launchd (non-interactive). Confirm that aria-google's OAuth token refresh works headlessly. If not, the Google calendar read will silently fail — the script must detect this and fall back to Outlook-only with a warning rather than writing incomplete state."],
378
+ ["Q2", "Destination parsing from event title",
379
+ "PTO events may not have a location field set. Title parsing needs a convention: \"Maya – PTO Maryland\" works; \"Maya – PTO\" alone does not yield a destination. Worth establishing the naming convention and adding it to the scheduler secretary's entry template."],
380
+ ["Q3", "Sam's Google calendar access",
381
+ "The script needs read access to Sam's shared family calendar to detect joint trips. Confirm aria-google has the correct scope and that the calendar is shared with Maya's Google account."],
382
+ ["Q4", "Work trip hobby implications",
383
+ "Work travel (Denver) is different from vacation — Maya may or may not train depending on the trip. Currently the model sets hobby_training: skip only for vacation type. Confirm whether work trips should also skip or leave as ambiguous (requiring checkin verification to clarify)."]
384
+ ]
385
+ )
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../../lib/stream_weaver'
5
+
6
+ # Demonstrates the new radio_group and card components for quiz-style UIs
7
+ QuizApp = app "Quiz Demo" do
8
+ header2 "Test your knowledge"
9
+ text "Answer the questions below using the radio buttons."
10
+
11
+ card do
12
+ header3 "1. What does GIP stand for?"
13
+ radio_group :q1, [
14
+ "Growth, Income, Profit",
15
+ "Growth, Inflation, Policy",
16
+ "Gains, Interest, Prices",
17
+ "GDP, Interest rates, Profits"
18
+ ]
19
+ end
20
+
21
+ card do
22
+ header3 "2. Which programming language is this app built with?"
23
+ radio_group :q2, [
24
+ "Python",
25
+ "Ruby",
26
+ "JavaScript",
27
+ "Go"
28
+ ]
29
+ end
30
+
31
+ card do
32
+ header3 "3. True or False: StreamWeaver uses Alpine.js"
33
+ radio_group :q3, ["True", "False"]
34
+ end
35
+
36
+ # Show answers when all questions are answered
37
+ if state[:q1] && state[:q2] && state[:q3]
38
+ card class: "results-card" do
39
+ header2 "Your Answers"
40
+ text "Q1: #{state[:q1]}"
41
+ text "Q2: #{state[:q2]}"
42
+ text "Q3: #{state[:q3]}"
43
+ end
44
+ end
45
+ end
46
+
47
+ QuizApp.run! if __FILE__ == $0
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Run Viewer Timeline
5
+ # Replicates the DTO Run Viewer event log using the TimelineEvent component.
6
+ # Run with: ruby examples/components/run_viewer_demo.rb
7
+
8
+ require_relative "../../lib/stream_weaver"
9
+
10
+ RunViewerApp = app "Run Viewer — abc-123", theme: :dark do
11
+ # Header metadata
12
+ header1 "Run Viewer"
13
+ hstack spacing: :lg do
14
+ text "run_id: abc-123"
15
+ text "target: codex"
16
+ text "duration: 60.0s"
17
+ text "events: 11"
18
+ end
19
+ hstack spacing: :lg do
20
+ text "interventions: 2"
21
+ text "timeouts: 0"
22
+ text "snapshots: 2"
23
+ end
24
+ text "source: demo/sample_run.jsonl"
25
+
26
+ # Timeline events
27
+ vstack spacing: :none do
28
+ timeline_event index: 0, event_type: :phase, timestamp: "10:00:00",
29
+ label: "launch",
30
+ fields: { run_id: "abc-123", phase: "launch", target: "codex",
31
+ baseline_files: "lib/app.rb", step_id: "launch",
32
+ target_socket_name: "dto-codex", target_session_name: "run-1" }
33
+
34
+ timeline_event index: 1, event_type: :phase, timestamp: "10:00:05",
35
+ label: "settle step=1",
36
+ fields: { run_id: "abc-123", phase: "settle", step: 1, step_id: "step-1" }
37
+
38
+ timeline_event index: 2, event_type: :phase, timestamp: "10:00:15",
39
+ label: "observe step=1",
40
+ fields: { run_id: "abc-123", phase: "observe", step: 1, step_id: "step-1" }
41
+
42
+ timeline_event index: 3, event_type: :snapshot, timestamp: "10:00:16",
43
+ label: "state=working verification_ok=false step=1",
44
+ fields: { run_id: "abc-123", step: 1, step_id: "step-1", state: "working",
45
+ waiting_for_input: false, busy: true, likely_complete: false,
46
+ signals_found: "[]", signals_missing: "test passes",
47
+ verification_ok: false, changed_files: "lib/app.rb",
48
+ last_assistant_lines: "Writing the initial implementation..." }
49
+
50
+ timeline_event index: 4, event_type: :phase, timestamp: "10:00:17",
51
+ label: "decide step=1",
52
+ fields: { run_id: "abc-123", phase: "decide", step: 1, step_id: "step-1",
53
+ driver: "ClaudeDriverBackend" }
54
+
55
+ timeline_event index: 5, event_type: :intervention, timestamp: "10:00:22",
56
+ label: "action=question terminal=false step=1",
57
+ fields: { run_id: "abc-123", step: 1, step_id: "step-1", action: "question",
58
+ intent: "Clarify scope",
59
+ why: "Worker jumped into coding without asking about interface shape",
60
+ next_step: "List the product choices before writing code",
61
+ stop_if: "Worker starts asking clarifying questions",
62
+ rendered_message: "INTENT: Clarify scope\nWHY: You started coding without clarifying the interface shape.\nNEXT: List the product choices first.\nSTOP IF: You start asking clarifying questions.",
63
+ terminal: false }
64
+
65
+ timeline_event index: 6, event_type: :phase, timestamp: "10:00:23",
66
+ label: "send step=1",
67
+ fields: { run_id: "abc-123", phase: "send", step: 1, step_id: "step-1" }
68
+
69
+ timeline_event index: 7, event_type: :phase, timestamp: "10:00:35",
70
+ label: "settle step=2",
71
+ fields: { run_id: "abc-123", phase: "settle", step: 2, step_id: "step-2" }
72
+
73
+ timeline_event index: 8, event_type: :snapshot, timestamp: "10:00:45",
74
+ label: "state=waiting verification_ok=true step=2",
75
+ fields: { run_id: "abc-123", step: 2, step_id: "step-2", state: "waiting",
76
+ waiting_for_input: true, busy: false, likely_complete: false,
77
+ signals_found: "test passes", signals_missing: "[]",
78
+ verification_ok: true,
79
+ changed_files: "lib/app.rb, test/test_app.rb",
80
+ last_assistant_lines: "All tests pass. Here is the summary..." }
81
+
82
+ timeline_event index: 9, event_type: :intervention, timestamp: "10:00:50",
83
+ label: "action=verify terminal=true step=2",
84
+ fields: { run_id: "abc-123", step: 2, step_id: "step-2", action: "verify",
85
+ intent: "Confirm completion",
86
+ why: "Signals met and verification passes",
87
+ next_step: "Summarize what changed",
88
+ stop_if: "nil",
89
+ rendered_message: "INTENT: Confirm completion\nWHY: All signals met.\nNEXT: Summarize.\nSTOP IF: n/a",
90
+ terminal: true }
91
+
92
+ timeline_event index: 10, event_type: :final, timestamp: "10:01:00",
93
+ label: "interventions=2",
94
+ fields: { run_id: "abc-123", interventions: 2,
95
+ final_transcript_tail: "Done. All tests pass.",
96
+ step_id: "final" }
97
+ end
98
+ end
99
+
100
+ RunViewerApp.run! if __FILE__ == $0
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Demo of ScoreTable and Collapsible components
4
+ # Run: ruby examples/score_and_collapsible_demo.rb
5
+ # Open: http://localhost:4567
6
+
7
+ require_relative '../../lib/stream_weaver'
8
+
9
+ app "Review Dashboard" do
10
+ header "Teachable Moment Review"
11
+
12
+ card do
13
+ header3 "Item 1: Debugging Race Conditions"
14
+
15
+ # Score table with color-coded metrics
16
+ score_table scores: [
17
+ { label: "Novelty", value: 8, max: 10 },
18
+ { label: "Struggle→Solution", value: 7, max: 10 },
19
+ { label: "Reusability", value: 9, max: 10 }
20
+ ]
21
+
22
+ text "Themes: debugging, concurrency, testing"
23
+
24
+ # Collapsible context section
25
+ collapsible "View Context (127 words)" do
26
+ text "The developer was working on a payment processing system when they encountered intermittent test failures. After investigation, they discovered a race condition in the async checkout flow. The key insight was using condition-based waiting instead of arbitrary sleep timeouts. This pattern proved highly reusable across other async tests in the codebase."
27
+ end
28
+
29
+ checkbox :item_1, "Include in export"
30
+ end
31
+
32
+ card do
33
+ header3 "Item 2: API Rate Limiting Strategy"
34
+
35
+ score_table scores: [
36
+ { label: "Novelty", value: 5, max: 10 },
37
+ { label: "Struggle→Solution", value: 4, max: 10 },
38
+ { label: "Reusability", value: 6, max: 10 }
39
+ ]
40
+
41
+ text "Themes: API design, performance"
42
+
43
+ collapsible "View Context (89 words)" do
44
+ text "Standard implementation of exponential backoff with jitter for API rate limiting. While not novel, the specific configuration values were tuned based on production metrics."
45
+ end
46
+
47
+ checkbox :item_2, "Include in export"
48
+ end
49
+
50
+ card do
51
+ header3 "Item 3: Memory Leak Detection"
52
+
53
+ score_table scores: [
54
+ { label: "Novelty", value: 3, max: 10 },
55
+ { label: "Struggle→Solution", value: 2, max: 10 },
56
+ { label: "Reusability", value: 3, max: 10 }
57
+ ]
58
+
59
+ text "Themes: performance, debugging"
60
+
61
+ collapsible "View Context (45 words)", expanded: true do
62
+ text "Basic memory profiling using standard Ruby tools. No novel insights."
63
+ end
64
+
65
+ checkbox :item_3, "Include in export"
66
+ end
67
+
68
+ # Summary
69
+ div class: "summary" do
70
+ text "---"
71
+ selected = [state[:item_1], state[:item_2], state[:item_3]].count { |v| v }
72
+ text "Selected: #{selected} of 3 items"
73
+
74
+ if selected > 0
75
+ button "Export Selected" do |s|
76
+ s[:exported] = true
77
+ end
78
+ end
79
+
80
+ text "Exported successfully!" if state[:exported]
81
+ end
82
+ end.run!
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Smoke test: browser-cached select value should NOT override server default
4
+ #
5
+ # Steps to reproduce the bug (before fix):
6
+ # 1. Run this app, open in Brave/Chrome
7
+ # 2. Change the select to "banana" or "cherry"
8
+ # 3. Navigate away (e.g. open a different URL)
9
+ # 4. Navigate back — WITHOUT the fix, you'll see the stale "banana"/"cherry"
10
+ # instead of the server default "orange"
11
+ #
12
+ # Expected after fix: always shows "orange" on fresh load
13
+ #
14
+ # Run with: ruby examples/components/select_stale_value_smoke_test.rb
15
+
16
+ require_relative "../../lib/stream_weaver"
17
+
18
+ app = StreamWeaver.app "Select Stale Value Smoke Test" do
19
+ header1 "Select Stale Value Smoke Test"
20
+
21
+ md "**Expected:** the select always shows **orange** after a page refresh or navigate-away-and-back."
22
+ md "**Bug symptom:** Brave/Chrome restores the previous selection instead of the server-rendered default."
23
+
24
+ # Default is "orange" — intentionally NOT the first option
25
+ state[:fruit] ||= "orange"
26
+
27
+ select :fruit, %w[apple orange banana cherry], submit: false
28
+
29
+ card do
30
+ text "Server sees: #{state[:fruit]}"
31
+ end
32
+
33
+ md "---"
34
+ button "Reset to orange", style: :secondary do |s|
35
+ s[:fruit] = "orange"
36
+ end
37
+ end
38
+
39
+ app.run!