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.
- checksums.yaml +7 -0
- data/.beads/.gitignore +77 -0
- data/.beads/README.md +81 -0
- data/.beads/config.yaml +54 -0
- data/.beads/metadata.json +7 -0
- data/.rspec +3 -0
- data/AGENTS.md +91 -0
- data/CHANGELOG.md +294 -0
- data/CLAUDE.md +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +565 -0
- data/Rakefile +13 -0
- data/assets/streamweaver-hero.jpg +0 -0
- data/bench/baselines/ledger.rb +58 -0
- data/bench/baselines/warroom.rb +51 -0
- data/bench/fixtures/ledger.rb +76 -0
- data/bench/fixtures/warroom.rb +60 -0
- data/bench/results/6daf8b8.md +102 -0
- data/bench/results/c8d749b.md +102 -0
- data/bench/results/eb06ab9.md +102 -0
- data/bench/run.rb +151 -0
- data/bench/support.rb +84 -0
- data/copy_this/dto_run_sample_run_7631.html +220 -0
- data/docs/SERVICE_MODE.md +302 -0
- data/docs/architecture/how_streamweaver_works.md +772 -0
- data/docs/blog/2026-01-16-streamweaver-introduction.md +515 -0
- data/docs/bug-2026-08-31-canvas-bridge-socket-collision.md +83 -0
- data/docs/canvas-ipc-session-summary.md +127 -0
- data/docs/canvas-panel-workflow.md +172 -0
- data/docs/canvas-read.md +147 -0
- data/docs/canvas-roadmap.md +275 -0
- data/docs/case-studies/2026-09-03-didx-canvas-read-shelf.md +147 -0
- data/docs/claude-code-companion-skill-spec.md +567 -0
- data/docs/components_reference.md +1223 -0
- data/docs/crud-patterns.md +265 -0
- data/docs/endpoints.md +122 -0
- data/docs/for_llms.md +1 -0
- data/docs/form-patterns.md +165 -0
- data/docs/frontend-only.md +169 -0
- data/docs/html-artifact-audit.md +238 -0
- data/docs/ideas/2025-01-01-as-a-service.md +203 -0
- data/docs/ideas/2026-01-16-charm-tui-exploration.md +542 -0
- data/docs/ideas/2026-08-27-static-doc-shelf-export.md +153 -0
- data/docs/ideas/dhh-review-future-refactors.md +142 -0
- data/docs/opal-jamstack.md +47 -0
- data/docs/opal-npm-direction.md +184 -0
- data/docs/opal-spike-findings.md +194 -0
- data/docs/plans/2025-12-16-form-blocks-design.md +124 -0
- data/docs/plans/2025-12-30-examples-browser-design.md +152 -0
- data/docs/plans/2026-01-02-charts-design.md +288 -0
- data/docs/plans/2026-01-10-canvas-ipc-design.md +247 -0
- data/docs/plans/2026-01-19-cabinet-control-components.md +176 -0
- data/docs/plans/2026-01-26-gem-release-and-panel.md +140 -0
- data/docs/plans/canvas-claude-project-design.md +238 -0
- data/docs/plans/canvas-doc-location-and-discovery.md +32 -0
- data/docs/plans/org-doc-preview-surfaces.md +293 -0
- data/docs/plans/shadcn-polish-plan.md +417 -0
- data/docs/porting-artifacts.md +252 -0
- data/docs/reference/agent-skills-comparison.md +369 -0
- data/docs/reference/travel-state-prd.artifact.html +780 -0
- data/docs/research/2026-08-17-hotwire-alike-landscape.md +268 -0
- data/docs/research/2026-08-17-hotwire-concept-map.md +404 -0
- data/docs/research/2026-08-22-lazy-fragments-trigger-decision.md +246 -0
- data/docs/research/2026-08-22-learnhotwire-syllabus-coverage.md +239 -0
- data/docs/research/frontend-only-matrix.md +278 -0
- data/docs/research/streamweaver-way-spike-findings.md +529 -0
- data/docs/resource-dsl.md +342 -0
- data/docs/routing.md +302 -0
- data/docs/ruby-ui-comparison.md +319 -0
- data/docs/shared-dsl-fragments.md +356 -0
- data/docs/streamweaver-for-ai-agents.md +401 -0
- data/docs/streamweaver-frontend-vision.md +123 -0
- data/docs/streamweaver_canvas/glimmer_initial_final_layer.rb +77 -0
- data/docs/streamweaver_canvas/save_example.rb +9 -0
- data/docs/templates.md +213 -0
- data/docs/testing.md +155 -0
- data/docs/theming-hooks.md +281 -0
- data/docs/tutorials/the-streamweaver-way.md +882 -0
- data/docs/university/capability-inventory.md +137 -0
- data/docs/university/dependency-survey.md +114 -0
- data/docs/university/design-spec.md +217 -0
- data/docs/university/mockups/code-block-doc-theme-dark.png +0 -0
- data/docs/university/mockups/code-block-doc-theme-light.png +0 -0
- data/docs/university/mockups/course-list-dark.png +0 -0
- data/docs/university/mockups/course-list-light.png +0 -0
- data/docs/university/mockups/course_canvas_mockup.rb +741 -0
- data/docs/university/mockups/step-screen-dark.png +0 -0
- data/docs/university/mockups/step-screen-light.png +0 -0
- data/docs/university/roadmap.md +72 -0
- data/docs/university/send-to-coworker.md +77 -0
- data/docs/university/worker-session-mining.md +109 -0
- data/docs/visual/browser-rendering-spike.md +173 -0
- data/docs/visual/builder-visual-plan-analysis.md +378 -0
- data/docs/visual/sw-plan-format-exploration.md +511 -0
- data/docs/visual/sw-plan-rendering-deep-dive.md +453 -0
- data/docs/visual-skills/PROGRESS.md +60 -0
- data/docs/visual-skills/SESSION-CONTEXT.md +207 -0
- data/docs/visual-skills/analysis/components.md +317 -0
- data/docs/visual-skills/analysis/overlap.md +360 -0
- data/docs/visual-skills/analysis/pi-design-deck.md +1102 -0
- data/docs/visual-skills/analysis/streamweaver-inventory.md +93 -0
- data/docs/visual-skills/analysis/unified-specs.feature +1003 -0
- data/docs/visual-skills/analysis/visual-explainer.md +964 -0
- data/docs/visual-skills/blog/blog-series-outline.md +39 -0
- data/docs/visual-skills/blog/token-efficiency.md +73 -0
- data/docs/visual-skills/design/architecture.md +1725 -0
- data/docs/visual-skills/design/codex-review.md +340 -0
- data/docs/visual-skills/design/dhh-review.md +209 -0
- data/docs/visual-skills/design/evolution.md +100 -0
- data/docs/visual-skills/design/gemini-review.md +55 -0
- data/docs/visual-skills/design/review-synthesis.md +149 -0
- data/docs/visual-skills/implementation/STATE.md +22 -0
- data/docs/visual-skills/implementation/plan.md +347 -0
- data/docs/visual-skills/implementation/spike-findings.md +237 -0
- data/docs/visual-skills/implementation/tasks.md +702 -0
- data/docs/visual-skills/lessons-learned/process.md +145 -0
- data/examples/README.md +96 -0
- data/examples/advanced/all_components.rb +177 -0
- data/examples/advanced/examples_browser.rb +394 -0
- data/examples/advanced/teachables_browser.rb +261 -0
- data/examples/advanced/theme_tweaker.rb +366 -0
- data/examples/advanced/tutorial.rb +1528 -0
- data/examples/agentic/agentic_form.rb +30 -0
- data/examples/agentic/agentic_form_autoclose.rb +30 -0
- data/examples/agentic/cultivation_tracker.rb +69 -0
- data/examples/basic/hello_world.rb +22 -0
- data/examples/basic/opal_tabs_table.rb +44 -0
- data/examples/basic/todo_list.rb +39 -0
- data/examples/button_loading_test.rb +36 -0
- data/examples/canvas/mermaid_canvas_demo.sh +151 -0
- data/examples/charts/bar_chart_demo.rb +57 -0
- data/examples/charts/line_chart_demo.rb +73 -0
- data/examples/charts/pie_area_demo.rb +87 -0
- data/examples/charts/stacked_bar_chart_demo.rb +69 -0
- data/examples/claude_code/README.md +85 -0
- data/examples/claude_code/codebreaker/.claude/commands/infiltrate.md +632 -0
- data/examples/claude_code/codebreaker/.claude/settings.json +11 -0
- data/examples/claude_code/codebreaker/.claude/settings.local.json +17 -0
- data/examples/claude_code/codebreaker/.claude/skills/infiltrate.md +0 -0
- data/examples/claude_code/codebreaker/README.md +213 -0
- data/examples/claude_code/tutorial/.claude/commands/learn.md +453 -0
- data/examples/claude_code/tutorial/README.md +102 -0
- data/examples/claude_code/verification_flow/.claude/commands/verify.md +171 -0
- data/examples/claude_code/verification_flow/README.md +126 -0
- data/examples/components/annotated_code_demo.rb +54 -0
- data/examples/components/callout_demo.rb +33 -0
- data/examples/components/checkbox_group_demo.rb +46 -0
- data/examples/components/design_review.css +468 -0
- data/examples/components/design_review_demo.rb +44 -0
- data/examples/components/design_review_dsl.rb +300 -0
- data/examples/components/diff_block_demo.rb +112 -0
- data/examples/components/events_demo.rb +184 -0
- data/examples/components/form_demo.rb +62 -0
- data/examples/components/lesson_demo.rb +53 -0
- data/examples/components/markdown_demo.rb +110 -0
- data/examples/components/mermaid_demo.rb +166 -0
- data/examples/components/pareto_set.rb +64 -0
- data/examples/components/prd_demo.rb +21 -0
- data/examples/components/prd_dsl.rb +385 -0
- data/examples/components/quiz_demo.rb +47 -0
- data/examples/components/run_viewer_demo.rb +100 -0
- data/examples/components/score_and_collapsible_demo.rb +82 -0
- data/examples/components/select_stale_value_smoke_test.rb +39 -0
- data/examples/components/table_demo.rb +247 -0
- data/examples/components/timer_with_state_demo.rb +58 -0
- data/examples/components/todo_due_dates.rb +63 -0
- data/examples/components/uat_gaps_demo.rb +112 -0
- data/examples/dashboard/feed_simulator.rb +60 -0
- data/examples/dashboard/live_dashboard.rb +80 -0
- data/examples/dashboard_components.rb +108 -0
- data/examples/deferred_fragments_demo.rb +62 -0
- data/examples/generate_more_spike/README.md +63 -0
- data/examples/generate_more_spike/app.rb +441 -0
- data/examples/git_health.sh +401 -0
- data/examples/layout/layout_components_demo.rb +174 -0
- data/examples/layout/modal_demo.rb +215 -0
- data/examples/layout/navigation_demo.rb +227 -0
- data/examples/layout/route_tabs_demo.rb +52 -0
- data/examples/layout/routing_demo.rb +52 -0
- data/examples/layout/scroll_box_demo.rb +154 -0
- data/examples/lazy_fragments_demo.rb +151 -0
- data/examples/my_todos/README.md +29 -0
- data/examples/my_todos/my_todos.rb +312 -0
- data/examples/my_todos/store.rb +86 -0
- data/examples/opal/reactive_demo.rb +62 -0
- data/examples/opal/scenarios/s1_counter.rb +15 -0
- data/examples/opal/scenarios/s2_search_filter.rb +17 -0
- data/examples/opal/scenarios/s3_sibling_tabs.rb +25 -0
- data/examples/opal/scenarios/s4_shopping_cart.rb +34 -0
- data/examples/opal/scenarios/s5_watch.rb +39 -0
- data/examples/opal/scenarios/s6_on_start.rb +20 -0
- data/examples/opal/scenarios/s7_wizard.rb +33 -0
- data/examples/opal/scenarios/s8_loan_calculator.rb +21 -0
- data/examples/opal/scenarios/s9_dashboard.rb +27 -0
- data/examples/operations_dashboard_demo.rb +167 -0
- data/examples/panel_demo.sh +447 -0
- data/examples/parity/assets/tyrion_slice.css +86 -0
- data/examples/parity/rivet_people_slice.rb +182 -0
- data/examples/parity/tyrion_components.css +777 -0
- data/examples/parity/tyrion_warroom_components.rb +414 -0
- data/examples/parity/tyrion_warroom_slice.rb +549 -0
- data/examples/puma_dev/README.md +124 -0
- data/examples/puma_dev/config.ru +34 -0
- data/examples/puma_dev/standalone_app.rb +34 -0
- data/examples/scaffolding/blog.rb +49 -0
- data/examples/scaffolding/utf_lite.rb +105 -0
- data/examples/styling/feedback_demo.rb +229 -0
- data/examples/styling/style_showcase.rb +172 -0
- data/examples/styling/theme_demo.rb +508 -0
- data/examples/timer_health_checker.rb +111 -0
- data/examples/timer_showcase.rb +131 -0
- data/examples/tutorials/render_markdown.rb +112 -0
- data/examples/tutorials/streamweaver_way_tutorial.rb +44 -0
- data/examples/tutorials/tutorial_content.rb +1082 -0
- data/examples/visual_skills/design_deck_demo.rb +314 -0
- data/examples/visual_skills/explainer_demo.rb +499 -0
- data/exe/streamweaver +9 -0
- data/gsd/ROADMAP-1.0.md +167 -0
- data/gsd/STATE.md +13 -0
- data/gsd/research/market-positioning-research.md +139 -0
- data/gsd/research/production-patterns-research.md +270 -0
- data/gsd/research/repo-audit-1.0.md +274 -0
- data/lib/stream_weaver/action_token.rb +58 -0
- data/lib/stream_weaver/adapter/alpinejs.rb +8249 -0
- data/lib/stream_weaver/adapter/base.rb +591 -0
- data/lib/stream_weaver/adapter/opal.rb +334 -0
- data/lib/stream_weaver/adapter/static.rb +1118 -0
- data/lib/stream_weaver/admin.rb +176 -0
- data/lib/stream_weaver/app.rb +1821 -0
- data/lib/stream_weaver/assets/js/sw-copy.js +50 -0
- data/lib/stream_weaver/assets/js/sw-heredoc-rewrite.js +68 -0
- data/lib/stream_weaver/assets/js/sw-keyboard.js +165 -0
- data/lib/stream_weaver/assets/js/sw-mermaid-zoom.js +621 -0
- data/lib/stream_weaver/assets/js/sw-route-tabs.js +53 -0
- data/lib/stream_weaver/assets/js/sw-sidebar-toc.js +116 -0
- data/lib/stream_weaver/assets/js/sw-slide-nav.js +103 -0
- data/lib/stream_weaver/canvas/bridge.rb +239 -0
- data/lib/stream_weaver/canvas/bridge_server.rb +646 -0
- data/lib/stream_weaver/canvas/client.rb +298 -0
- data/lib/stream_weaver/canvas/doc_roots.rb +233 -0
- data/lib/stream_weaver/canvas/doc_store.rb +252 -0
- data/lib/stream_weaver/canvas/gist_publisher.rb +264 -0
- data/lib/stream_weaver/canvas/gist_save_handler.rb +89 -0
- data/lib/stream_weaver/canvas/gist_store.rb +135 -0
- data/lib/stream_weaver/canvas/helpers.rb +109 -0
- data/lib/stream_weaver/canvas/history.rb +90 -0
- data/lib/stream_weaver/canvas/protocol.rb +86 -0
- data/lib/stream_weaver/canvas/reader.rb +853 -0
- data/lib/stream_weaver/canvas/save_doc_widget.rb +457 -0
- data/lib/stream_weaver/canvas/scroll_top_hint.rb +21 -0
- data/lib/stream_weaver/canvas/session.rb +132 -0
- data/lib/stream_weaver/cli.rb +3235 -0
- data/lib/stream_weaver/component_assets.rb +70 -0
- data/lib/stream_weaver/component_registry.rb +67 -0
- data/lib/stream_weaver/component_renderer.rb +48 -0
- data/lib/stream_weaver/components/annotated_code.rb +53 -0
- data/lib/stream_weaver/components/api_endpoint.rb +42 -0
- data/lib/stream_weaver/components/callout.rb +59 -0
- data/lib/stream_weaver/components/chart.rb +84 -0
- data/lib/stream_weaver/components/code_block.rb +77 -0
- data/lib/stream_weaver/components/comparison.rb +39 -0
- data/lib/stream_weaver/components/decision.rb +38 -0
- data/lib/stream_weaver/components/deck/close_overlay.rb +84 -0
- data/lib/stream_weaver/components/deck/confirmation_bar.rb +60 -0
- data/lib/stream_weaver/components/deck/deck_option.rb +61 -0
- data/lib/stream_weaver/components/deck/deck_slide.rb +77 -0
- data/lib/stream_weaver/components/deck/deck_state.rb +469 -0
- data/lib/stream_weaver/components/deck/deck_summary.rb +73 -0
- data/lib/stream_weaver/components/deck/design_deck.rb +60 -0
- data/lib/stream_weaver/components/deck/generate_more_controls.rb +84 -0
- data/lib/stream_weaver/components/deck/model_selector.rb +84 -0
- data/lib/stream_weaver/components/deck/skeleton_placeholder.rb +36 -0
- data/lib/stream_weaver/components/diff_block.rb +125 -0
- data/lib/stream_weaver/components/doc_header.rb +57 -0
- data/lib/stream_weaver/components/image_block.rb +70 -0
- data/lib/stream_weaver/components/implementation_map.rb +33 -0
- data/lib/stream_weaver/components/keyboard_shortcuts.rb +94 -0
- data/lib/stream_weaver/components/kpi_dashboard.rb +78 -0
- data/lib/stream_weaver/components/mermaid.rb +79 -0
- data/lib/stream_weaver/components/pipeline.rb +63 -0
- data/lib/stream_weaver/components/sidebar_toc.rb +46 -0
- data/lib/stream_weaver/components/slide_container.rb +141 -0
- data/lib/stream_weaver/components/timeline_event.rb +58 -0
- data/lib/stream_weaver/components/wireframe.rb +29 -0
- data/lib/stream_weaver/components/wireframe_block.rb +34 -0
- data/lib/stream_weaver/components.rb +2711 -0
- data/lib/stream_weaver/css.rb +230 -0
- data/lib/stream_weaver/dev_fallback_overlay.rb +61 -0
- data/lib/stream_weaver/display_dsl.rb +1004 -0
- data/lib/stream_weaver/export/html_exporter.rb +478 -0
- data/lib/stream_weaver/feed.rb +34 -0
- data/lib/stream_weaver/feed_builder.rb +31 -0
- data/lib/stream_weaver/fonts.rb +33 -0
- data/lib/stream_weaver/interaction_runner.rb +487 -0
- data/lib/stream_weaver/iterm.rb +460 -0
- data/lib/stream_weaver/layout_registry.rb +92 -0
- data/lib/stream_weaver/opal/bridge.rb +52 -0
- data/lib/stream_weaver/opal/builder.rb +193 -0
- data/lib/stream_weaver/opal/env.rb +29 -0
- data/lib/stream_weaver/opal/reactive_state.rb +75 -0
- data/lib/stream_weaver/opal/regexp_anchor_patch.rb +62 -0
- data/lib/stream_weaver/opal/renderer.rb +77 -0
- data/lib/stream_weaver/opal/runtime.rb +250 -0
- data/lib/stream_weaver/opal/shell.rb +145 -0
- data/lib/stream_weaver/opal/string_bridge.rb +50 -0
- data/lib/stream_weaver/opal/stubs/diff.min.js +1 -0
- data/lib/stream_weaver/opal/stubs/digest.rb +15 -0
- data/lib/stream_weaver/opal/stubs/marked.umd.js +79 -0
- data/lib/stream_weaver/opal/stubs/md5.rb +3 -0
- data/lib/stream_weaver/opal/stubs/morphdom.min.js +775 -0
- data/lib/stream_weaver/opal/stubs/prism-tomorrow.min.css +1 -0
- data/lib/stream_weaver/opal/stubs/prism.min.js +1967 -0
- data/lib/stream_weaver/opal_entry.rb +136 -0
- data/lib/stream_weaver/org/inline.rb +95 -0
- data/lib/stream_weaver/org/reader.rb +561 -0
- data/lib/stream_weaver/org/recording_context.rb +86 -0
- data/lib/stream_weaver/org/source_splitter.rb +63 -0
- data/lib/stream_weaver/org/writer.rb +300 -0
- data/lib/stream_weaver/page_shell.rb +530 -0
- data/lib/stream_weaver/portfile.rb +79 -0
- data/lib/stream_weaver/pushable.rb +42 -0
- data/lib/stream_weaver/resource/default_views.rb +111 -0
- data/lib/stream_weaver/resource/field_input.rb +25 -0
- data/lib/stream_weaver/resource/state_keys.rb +16 -0
- data/lib/stream_weaver/resource/store.rb +18 -0
- data/lib/stream_weaver/resource.rb +104 -0
- data/lib/stream_weaver/server.rb +1471 -0
- data/lib/stream_weaver/service.rb +1240 -0
- data/lib/stream_weaver/service_client.rb +104 -0
- data/lib/stream_weaver/session_store.rb +186 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/SKILL.md +66 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/examples/canvas-safe-showcase.rb +98 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/actions-and-buttons.md +47 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/charts-and-diagrams.md +38 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/deck.md +32 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/inputs-and-forms.md +65 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/tabs-and-navigation.md +53 -0
- data/lib/stream_weaver/skills/streamweaver-doc-builder/SKILL.md +298 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/SKILL.md +130 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.css +468 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.rb +39 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example_dsl.rb +300 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example.rb +24 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example_dsl.rb +385 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/checkpoints-and-forms.md +28 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/cleanup-and-panel.md +44 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/example-gallery.md +8 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/persistence.md +58 -0
- data/lib/stream_weaver/skills/streamweaver-way/SKILL.md +396 -0
- data/lib/stream_weaver/skills/visual-plan/SKILL.md +201 -0
- data/lib/stream_weaver/skills/visual-recap/SKILL.md +244 -0
- data/lib/stream_weaver/streamer.rb +63 -0
- data/lib/stream_weaver/templates/choices.rb +149 -0
- data/lib/stream_weaver/templates/code.rb +157 -0
- data/lib/stream_weaver/templates/confirm.rb +110 -0
- data/lib/stream_weaver/templates/diff.rb +195 -0
- data/lib/stream_weaver/templates/info.rb +142 -0
- data/lib/stream_weaver/templates/table.rb +169 -0
- data/lib/stream_weaver/templates/wizard.rb +271 -0
- data/lib/stream_weaver/theme/auto_mode.rb +116 -0
- data/lib/stream_weaver/theme/presets.rb +555 -0
- data/lib/stream_weaver/theme.rb +639 -0
- data/lib/stream_weaver/university/canvas.rb +924 -0
- data/lib/stream_weaver/university/course.rb +699 -0
- data/lib/stream_weaver/university/demos/counter.rb +33 -0
- data/lib/stream_weaver/university/demos/dashboard.rb +147 -0
- data/lib/stream_weaver/university/demos/decision_form.rb +143 -0
- data/lib/stream_weaver/university/demos.rb +50 -0
- data/lib/stream_weaver/university/listener.rb +467 -0
- data/lib/stream_weaver/university/progress.rb +201 -0
- data/lib/stream_weaver/university/runner.rb +138 -0
- data/lib/stream_weaver/university/scripts/growing_doc.rb +609 -0
- data/lib/stream_weaver/university/scripts/growing_doc_state.rb +91 -0
- data/lib/stream_weaver/utils.rb +31 -0
- data/lib/stream_weaver/version.rb +5 -0
- data/lib/stream_weaver/views/canvas/reader_layout.erb +800 -0
- data/lib/stream_weaver/views.rb +3940 -0
- data/lib/stream_weaver.rb +122 -0
- data/llms.txt +1269 -0
- data/sig/stream_weaver.rbs +4 -0
- metadata +598 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StreamWeaver
|
|
4
|
+
# Shared CSS for StreamWeaver themes and components
|
|
5
|
+
# Used by both AppView (standalone) and live session pages
|
|
6
|
+
module CSS
|
|
7
|
+
# Every framework-emitted style block (master theme, theme presets/
|
|
8
|
+
# overrides, component inject_*_css) is wrapped in this single named
|
|
9
|
+
# layer so any unlayered user stylesheet -- regardless of selector
|
|
10
|
+
# specificity or document order -- always wins the cascade
|
|
11
|
+
# (stream_weaver-oeo). User-authored CSS (App.new stylesheets:, and the
|
|
12
|
+
# `css`/`css_path` class macros a custom Component subclass can declare
|
|
13
|
+
# for itself) is deliberately left unlayered.
|
|
14
|
+
LAYER_NAME = "stream-weaver"
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Wraps framework CSS in the shared @layer so user CSS always wins
|
|
18
|
+
# the cascade regardless of specificity or document order.
|
|
19
|
+
# @param css [String] framework-emitted CSS
|
|
20
|
+
# @return [String] the CSS wrapped in `@layer stream-weaver { ... }`
|
|
21
|
+
def layer_wrap(css)
|
|
22
|
+
return css if css.nil? || css.strip.empty?
|
|
23
|
+
|
|
24
|
+
"@layer #{LAYER_NAME} {\n#{css}\n}"
|
|
25
|
+
end
|
|
26
|
+
# Returns the full StreamWeaver CSS (themes + components)
|
|
27
|
+
# @return [String] CSS content
|
|
28
|
+
def full_stylesheet
|
|
29
|
+
@full_stylesheet ||= begin
|
|
30
|
+
# Read from views.rb and extract the CSS heredoc
|
|
31
|
+
views_path = File.expand_path('views.rb', __dir__)
|
|
32
|
+
content = File.read(views_path)
|
|
33
|
+
|
|
34
|
+
# Extract CSS between the heredoc markers
|
|
35
|
+
# Pattern: raw(safe(<<~CSS)) ... CSS
|
|
36
|
+
if content =~ /raw\(safe\(<<~CSS\)\)(.*?)^\s*CSS$/m
|
|
37
|
+
# Remove the 16-space indentation from the original
|
|
38
|
+
$1.gsub(/^ /, '')
|
|
39
|
+
else
|
|
40
|
+
# Fallback: return minimal CSS
|
|
41
|
+
minimal_css
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# The framework stylesheet, or the best available substitute.
|
|
47
|
+
#
|
|
48
|
+
# full_stylesheet reads views.rb off disk. A compiled Opal bundle has no
|
|
49
|
+
# disk to read it from, so callers that run in both hosts -- notably the
|
|
50
|
+
# DOM-free render-to-string path -- ask for this instead and get the
|
|
51
|
+
# minimal token set rather than an exception when the file is out of
|
|
52
|
+
# reach.
|
|
53
|
+
# @return [String] CSS content
|
|
54
|
+
def base_stylesheet
|
|
55
|
+
full_stylesheet
|
|
56
|
+
rescue StandardError, NotImplementedError
|
|
57
|
+
minimal_css
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Minimal CSS for fallback
|
|
61
|
+
def minimal_css
|
|
62
|
+
<<~CSS
|
|
63
|
+
:root {
|
|
64
|
+
--sw-transition-fast: 120ms ease-out;
|
|
65
|
+
--sw-transition: 200ms ease-out;
|
|
66
|
+
--sw-color-primary: #c2410c;
|
|
67
|
+
--sw-color-text: #111111;
|
|
68
|
+
--sw-color-bg: #f8f8f8;
|
|
69
|
+
--sw-color-bg-card: #ffffff;
|
|
70
|
+
--sw-color-border: #e0e0e0;
|
|
71
|
+
--sw-spacing-md: 1.25rem;
|
|
72
|
+
--sw-radius-md: 6px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
body {
|
|
76
|
+
font-family: 'Source Sans 3', system-ui, sans-serif;
|
|
77
|
+
background: var(--sw-color-bg);
|
|
78
|
+
color: var(--sw-color-text);
|
|
79
|
+
padding: 1rem;
|
|
80
|
+
}
|
|
81
|
+
CSS
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Google Fonts link tags
|
|
85
|
+
def google_fonts_html
|
|
86
|
+
<<~HTML
|
|
87
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
88
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
89
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;500;600&family=Source+Sans+3:wght@400;500;600;700&display=swap">
|
|
90
|
+
HTML
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# CDN scripts for HTMX and Alpine.js
|
|
94
|
+
def cdn_scripts_html
|
|
95
|
+
<<~HTML
|
|
96
|
+
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
|
97
|
+
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
98
|
+
HTML
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Content update animation CSS
|
|
102
|
+
def animation_css
|
|
103
|
+
<<~CSS
|
|
104
|
+
/* Content update animations */
|
|
105
|
+
.sw-fade-in {
|
|
106
|
+
animation: sw-fade-in 350ms ease-out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@keyframes sw-fade-in {
|
|
110
|
+
from {
|
|
111
|
+
opacity: 0;
|
|
112
|
+
transform: translateY(-12px) scale(0.98);
|
|
113
|
+
}
|
|
114
|
+
to {
|
|
115
|
+
opacity: 1;
|
|
116
|
+
transform: translateY(0) scale(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.sw-slide-in {
|
|
121
|
+
animation: sw-slide-in 250ms ease-out;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@keyframes sw-slide-in {
|
|
125
|
+
from {
|
|
126
|
+
opacity: 0;
|
|
127
|
+
transform: translateX(-8px);
|
|
128
|
+
}
|
|
129
|
+
to {
|
|
130
|
+
opacity: 1;
|
|
131
|
+
transform: translateX(0);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Swap-target busy treatment during in-flight requests (FAC-P1.5).
|
|
136
|
+
Delay-in via transition-delay so fast responses never flicker;
|
|
137
|
+
undimming (class removed) is immediate. */
|
|
138
|
+
#app-container {
|
|
139
|
+
transition: opacity var(--sw-transition-fast, 120ms) ease-out;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#app-container.htmx-request {
|
|
143
|
+
opacity: 0.85;
|
|
144
|
+
transition-delay: 150ms;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Table styles */
|
|
148
|
+
.sw-table {
|
|
149
|
+
width: 100%;
|
|
150
|
+
border-collapse: collapse;
|
|
151
|
+
}
|
|
152
|
+
.sw-row-striped {
|
|
153
|
+
background: var(--sw-color-bg-muted, #f9fafb);
|
|
154
|
+
}
|
|
155
|
+
.sw-row-hoverable:hover {
|
|
156
|
+
background: var(--sw-color-bg-hover, #f0f0f0) !important;
|
|
157
|
+
}
|
|
158
|
+
.sw-table-bordered td,
|
|
159
|
+
.sw-table-bordered th {
|
|
160
|
+
border: 1px solid var(--sw-color-border, #e0e0e0);
|
|
161
|
+
}
|
|
162
|
+
CSS
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Dev-only "content missing" overlay (dev-loud-failure-overlay).
|
|
166
|
+
# Always emitted -- inert in production since DevFallbackOverlay only
|
|
167
|
+
# ever renders the `.sw-dev-fallback` markup these rules target when
|
|
168
|
+
# RACK_ENV=development. Styleable via the --sw-dev-fallback-* tokens;
|
|
169
|
+
# authors can also override the `.sw-dev-fallback` class hook directly.
|
|
170
|
+
def dev_fallback_css
|
|
171
|
+
<<~CSS
|
|
172
|
+
.sw-dev-fallback {
|
|
173
|
+
--sw-dev-fallback-bg: #fff7ed;
|
|
174
|
+
--sw-dev-fallback-border: #f59e0b;
|
|
175
|
+
--sw-dev-fallback-text: #7c2d12;
|
|
176
|
+
--sw-dev-fallback-accent: #b45309;
|
|
177
|
+
margin: 0 0 var(--sw-spacing-md, 1.25rem);
|
|
178
|
+
font-family: 'Source Sans 3', system-ui, sans-serif;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.sw-dev-fallback__dismiss:checked ~ .sw-dev-fallback__panel {
|
|
182
|
+
display: none;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.sw-dev-fallback__panel {
|
|
186
|
+
position: relative;
|
|
187
|
+
background: var(--sw-dev-fallback-bg);
|
|
188
|
+
border: 1px solid var(--sw-dev-fallback-border);
|
|
189
|
+
border-left: 4px solid var(--sw-dev-fallback-accent);
|
|
190
|
+
border-radius: var(--sw-radius-md, 6px);
|
|
191
|
+
padding: 0.75rem 2rem 0.75rem 1rem;
|
|
192
|
+
color: var(--sw-dev-fallback-text);
|
|
193
|
+
font-size: 0.875rem;
|
|
194
|
+
line-height: 1.5;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.sw-dev-fallback__panel > p {
|
|
198
|
+
margin: 0.25rem 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.sw-dev-fallback__title {
|
|
202
|
+
font-weight: 600;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.sw-dev-fallback__target code,
|
|
206
|
+
.sw-dev-fallback__cause code {
|
|
207
|
+
background: rgba(0, 0, 0, 0.06);
|
|
208
|
+
border-radius: 3px;
|
|
209
|
+
padding: 0.05rem 0.3rem;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.sw-dev-fallback__note {
|
|
213
|
+
font-size: 0.8rem;
|
|
214
|
+
opacity: 0.8;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.sw-dev-fallback__close {
|
|
218
|
+
position: absolute;
|
|
219
|
+
top: 0.5rem;
|
|
220
|
+
right: 0.6rem;
|
|
221
|
+
cursor: pointer;
|
|
222
|
+
font-size: 1.1rem;
|
|
223
|
+
line-height: 1;
|
|
224
|
+
color: var(--sw-dev-fallback-accent);
|
|
225
|
+
}
|
|
226
|
+
CSS
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'rack/utils'
|
|
5
|
+
|
|
6
|
+
module StreamWeaver
|
|
7
|
+
# Development-only "content missing" analog (dev-loud-failure-overlay,
|
|
8
|
+
# streamweaver-way epic). Hotwire treats a missing/stale Turbo Frame
|
|
9
|
+
# target as its single best debugging aid; StreamWeaver's fallback path
|
|
10
|
+
# (server.rb's `rescue StaleActionDefinition`) instead self-heals with a
|
|
11
|
+
# silent full-container swap so production users never see broken wiring.
|
|
12
|
+
# That silence is deliberate in production (see docs/for_llms.md, "Dev
|
|
13
|
+
# loud, prod self-heal") but costs the author a debugging signal in dev --
|
|
14
|
+
# this module renders the loud version for RACK_ENV=development only.
|
|
15
|
+
#
|
|
16
|
+
# Framework-emitted only: app code stays zero-JS. The dismiss control is a
|
|
17
|
+
# pure CSS checkbox/label pattern (see CSS.dev_fallback_css) -- no inline
|
|
18
|
+
# `onclick`, no script tag.
|
|
19
|
+
module DevFallbackOverlay
|
|
20
|
+
CAUSES = {
|
|
21
|
+
definition_changed: "action token stale — the app's registered actions changed since this " \
|
|
22
|
+
"token was issued (code reload). Interaction fell back to a full re-render.",
|
|
23
|
+
generation_changed: "action token stale — the server session's action generation changed " \
|
|
24
|
+
"(restart or session reset) since this token was issued. Interaction " \
|
|
25
|
+
"fell back to a full re-render."
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
DEFAULT_CAUSE = "action token stale after code reload — interaction fell back to a full re-render."
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
# @param action [Symbol, String, nil] the named action the stale token was minted for
|
|
32
|
+
# @param fragment [String, nil] the scoped fragment id the token declared as its swap target
|
|
33
|
+
# @param cause [Symbol, nil] :definition_changed or :generation_changed
|
|
34
|
+
# @return [String] HTML for the `.sw-dev-fallback` overlay, meant to be prepended to the
|
|
35
|
+
# fallback response body so it lands inside the retargeted #app-container swap
|
|
36
|
+
def render(action: nil, fragment: nil, cause: nil)
|
|
37
|
+
dismiss_id = "sw-dev-fallback-dismiss-#{SecureRandom.hex(4)}"
|
|
38
|
+
target_label = fragment ? "##{fragment}" : (action ? "action #{action}" : "#app-container")
|
|
39
|
+
|
|
40
|
+
<<~HTML
|
|
41
|
+
<div class="sw-dev-fallback" role="alert">
|
|
42
|
+
<input type="checkbox" id="#{dismiss_id}" class="sw-dev-fallback__dismiss" hidden>
|
|
43
|
+
<div class="sw-dev-fallback__panel">
|
|
44
|
+
<label for="#{dismiss_id}" class="sw-dev-fallback__close" aria-label="Dismiss">×</label>
|
|
45
|
+
<p class="sw-dev-fallback__title">StreamWeaver dev warning — full re-render fallback</p>
|
|
46
|
+
<p class="sw-dev-fallback__target">Target: <code>#{escape(target_label)}</code> (swapped as <code>#app-container</code> instead)</p>
|
|
47
|
+
<p class="sw-dev-fallback__cause">#{escape(CAUSES.fetch(cause, DEFAULT_CAUSE))}</p>
|
|
48
|
+
<p class="sw-dev-fallback__note">Dev-only — production silently self-heals the same way. See docs/for_llms.md, "Dev loud, prod self-heal".</p>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
HTML
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def escape(str)
|
|
57
|
+
Rack::Utils.escape_html(str.to_s)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|