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,567 @@
|
|
|
1
|
+
# Skill Specification: `streamweaver-claude-code-companion`
|
|
2
|
+
|
|
3
|
+
**Author:** Forrest Chang
|
|
4
|
+
**Date:** May 2026
|
|
5
|
+
**Status:** Specification — Not Yet Implemented as SKILL.md
|
|
6
|
+
**Purpose:** Define the behavior, templates, and guidance for a Hermes skill that enables Claude Code to use StreamWeaver's canvas as a live visual companion during coding sessions.
|
|
7
|
+
|
|
8
|
+
> **Note:** This document is the spec. The actual `SKILL.md` for the `streamweaver-claude-code-companion` skill gets written after this spec is validated through real use.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
When developers use Claude Code for complex work — explaining architectures, refactoring code, visualizing data flows, building step-by-step tutorials — a live visual pane alongside the terminal makes the experience dramatically richer. This skill teaches Claude Code to use StreamWeaver's canvas as that visual companion, pushing DSL-based renderings in real time.
|
|
15
|
+
|
|
16
|
+
The result feels like a Claude HTML artifact, but it's live, reactive, and persistent across the entire coding session.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## How the Setup Works
|
|
21
|
+
|
|
22
|
+
### The iTerm2 Split Panel
|
|
23
|
+
|
|
24
|
+
StreamWeaver's `iterm.rb` uses the `iterm2_ruby` gem to:
|
|
25
|
+
1. Split the current iTerm2 pane vertically
|
|
26
|
+
2. Open a browser (or `webview` pane) pointing at the canvas URL
|
|
27
|
+
3. Keep that pane persistent across the session
|
|
28
|
+
|
|
29
|
+
**Command:**
|
|
30
|
+
```bash
|
|
31
|
+
streamweaver panel <session_name>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This splits iTerm, opens the browser in the new pane, and the canvas is ready to receive pushes.
|
|
35
|
+
|
|
36
|
+
### Pushing Updates
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
streamweaver canvas-push <session_name> path/to/canvas.rb
|
|
40
|
+
# OR via inline DSL:
|
|
41
|
+
streamweaver canvas-push <session_name> --dsl "$(cat << 'EOF'
|
|
42
|
+
header1 "Hello World"
|
|
43
|
+
md "This is **live** content"
|
|
44
|
+
EOF
|
|
45
|
+
)"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Every push replaces the canvas content — no page refresh, morphdom-patched in place.
|
|
49
|
+
|
|
50
|
+
### Session Flow
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
1. User starts session: streamweaver panel my-session
|
|
54
|
+
2. Browser pane opens: http://localhost:4567/canvas/my-session
|
|
55
|
+
3. Claude Code works: writes code, explains concepts
|
|
56
|
+
4. Claude Code pushes: streamweaver canvas-push my-session <dsl>
|
|
57
|
+
5. Browser updates live: user sees visual companion update
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## When to Activate
|
|
63
|
+
|
|
64
|
+
Claude Code should proactively use the canvas companion (once a panel session is established) when:
|
|
65
|
+
|
|
66
|
+
### Automatic Triggers
|
|
67
|
+
- User asks to **explain something complex** — algorithm, architecture pattern, data flow
|
|
68
|
+
- User asks to **compare approaches** — "what's better, X or Y?"
|
|
69
|
+
- User asks to **show architecture** — system design, module dependencies, call flows
|
|
70
|
+
- User asks to **visualize data** — metrics, datasets, before/after comparisons
|
|
71
|
+
- User asks to **walk through step by step** — tutorial, onboarding, migration guide
|
|
72
|
+
- Any time a **diagram or mockup** would communicate better than text alone
|
|
73
|
+
- When **refactoring** — show the before/after side by side
|
|
74
|
+
- When **explaining a data model** — table schemas, relationship diagrams
|
|
75
|
+
|
|
76
|
+
### Passive Triggers
|
|
77
|
+
- When an explanation runs longer than ~4 paragraphs of text — "let me show you this visually"
|
|
78
|
+
- When the user seems confused and is asking follow-up questions
|
|
79
|
+
- When comparing more than 2 options (a comparison visual helps)
|
|
80
|
+
- When explaining something with multiple sequential steps
|
|
81
|
+
|
|
82
|
+
### Do NOT Activate For
|
|
83
|
+
- Simple one-line answers
|
|
84
|
+
- File editing operations
|
|
85
|
+
- Git commands
|
|
86
|
+
- Package installs
|
|
87
|
+
- Anything where a visual would be gratuitous
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Setup Steps (First Time in a Session)
|
|
92
|
+
|
|
93
|
+
### Step 1: Start the Panel
|
|
94
|
+
```bash
|
|
95
|
+
streamweaver panel <session_name>
|
|
96
|
+
# Suggested naming: use the project or topic, e.g.:
|
|
97
|
+
streamweaver panel auth-refactor
|
|
98
|
+
streamweaver panel neural-net-explainer
|
|
99
|
+
streamweaver panel api-design-review
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Step 2: Verify the Canvas is Live
|
|
103
|
+
```bash
|
|
104
|
+
# The panel command outputs the URL — export it:
|
|
105
|
+
export SW_CANVAS_URL="http://localhost:4567/canvas/<session_name>"
|
|
106
|
+
export SW_CANVAS_SESSION="<session_name>"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Step 3: Push an Orientation Header
|
|
110
|
+
```bash
|
|
111
|
+
streamweaver canvas-push $SW_CANVAS_SESSION --dsl "$(cat << 'EOF'
|
|
112
|
+
theme_preset :technical
|
|
113
|
+
hero do
|
|
114
|
+
header1 "Session: Auth Refactor"
|
|
115
|
+
md "Visual companion for this coding session"
|
|
116
|
+
end
|
|
117
|
+
EOF
|
|
118
|
+
)"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Step 4: Use canvas-push for Every Visual
|
|
122
|
+
From here, every explanation, diagram, or dashboard gets pushed to this persistent pane.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## The "Explain" Pattern
|
|
127
|
+
|
|
128
|
+
The canonical composite template for rich explanations. Chains components in this order:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
callout (the key insight, what to remember)
|
|
132
|
+
↓
|
|
133
|
+
code_block (the implementation, the "how")
|
|
134
|
+
↓
|
|
135
|
+
comparison OR pipeline (before/after OR the flow)
|
|
136
|
+
↓
|
|
137
|
+
mermaid (architecture, if relevant)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This mirrors what people love about Claude HTML artifacts — layered context with visual rhythm — but in the StreamWeaver DSL, which means it's live and reactive, not static HTML.
|
|
141
|
+
|
|
142
|
+
### Why This Order
|
|
143
|
+
1. **Callout first** — leads with the "aha" moment. User immediately knows the key takeaway.
|
|
144
|
+
2. **Code second** — shows the concrete implementation after the concept is framed.
|
|
145
|
+
3. **Comparison/pipeline** — shows where this fits (before/after or in a flow).
|
|
146
|
+
4. **Mermaid last** — architecture diagrams make more sense after you've seen the code.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Aesthetic Guidance: The "Premium Dark Artifact" Look
|
|
151
|
+
|
|
152
|
+
### Recommended Theme
|
|
153
|
+
```ruby
|
|
154
|
+
theme_preset :technical
|
|
155
|
+
```
|
|
156
|
+
`:technical` gives a dark, dense look. Pair with targeted inline styles for the full gradient aesthetic.
|
|
157
|
+
|
|
158
|
+
### Gradient Text Headings
|
|
159
|
+
No native gradient heading component yet (it's on the roadmap). Do it with an inline-styled `div`:
|
|
160
|
+
```ruby
|
|
161
|
+
div(style: "font-size: 2.5rem; font-weight: 800; background: linear-gradient(135deg, #a78bfa, #60a5fa, #34d399); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1rem;") do
|
|
162
|
+
text "Your Heading"
|
|
163
|
+
end
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Glassmorphism Card
|
|
167
|
+
```ruby
|
|
168
|
+
card(style: "background: rgba(255,255,255,0.05); backdrop-filter: blur(20px); border: 1px solid rgba(255,255,255,0.1); border-radius: 16px; padding: 24px;") do
|
|
169
|
+
# content
|
|
170
|
+
end
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Dark Background Container
|
|
174
|
+
```ruby
|
|
175
|
+
div(style: "background: #0f0f23; min-height: 100vh; padding: 40px;") do
|
|
176
|
+
# all content here
|
|
177
|
+
end
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Accent Borders
|
|
181
|
+
```ruby
|
|
182
|
+
div(style: "border-left: 3px solid #a78bfa; padding-left: 16px; margin: 16px 0;") do
|
|
183
|
+
md "Key insight highlighted with a purple accent bar"
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Full "Artifact" Wrapper (Combine It All)
|
|
188
|
+
```ruby
|
|
189
|
+
theme_preset :technical
|
|
190
|
+
div(style: "background: linear-gradient(135deg, #0a0a1a 0%, #1a1a2e 50%, #0f0f23 100%); min-height: 100vh; padding: 40px; font-family: 'Inter', system-ui, sans-serif;") do
|
|
191
|
+
# your content — cards, headers, code, charts
|
|
192
|
+
end
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Quick-Copy DSL Templates
|
|
198
|
+
|
|
199
|
+
### 1. Concept Explainer
|
|
200
|
+
```ruby
|
|
201
|
+
theme_preset :technical
|
|
202
|
+
|
|
203
|
+
div(style: "background: #0f0f23; padding: 40px; min-height: 100vh;") do
|
|
204
|
+
div(style: "font-size: 2rem; font-weight: 800; background: linear-gradient(135deg, #a78bfa, #60a5fa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 24px;") do
|
|
205
|
+
text "Concept: [NAME]"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
callout(:tip) do
|
|
209
|
+
md "**Key insight:** [One sentence that captures the core idea]"
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
div(style: "height: 16px;") # spacer — no spacer component yet
|
|
213
|
+
|
|
214
|
+
code_block(language: :ruby) do
|
|
215
|
+
<<~RUBY
|
|
216
|
+
# The implementation
|
|
217
|
+
def example
|
|
218
|
+
"put real code here"
|
|
219
|
+
end
|
|
220
|
+
RUBY
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
div(style: "height: 16px;")
|
|
224
|
+
|
|
225
|
+
comparison do
|
|
226
|
+
slot(:before) do
|
|
227
|
+
header4 "Before"
|
|
228
|
+
code_block(language: :ruby) { "old_approach()" }
|
|
229
|
+
end
|
|
230
|
+
slot(:after) do
|
|
231
|
+
header4 "After"
|
|
232
|
+
code_block(language: :ruby) { "new_approach()" }
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 2. Architecture Diagram
|
|
239
|
+
```ruby
|
|
240
|
+
theme_preset :technical
|
|
241
|
+
|
|
242
|
+
div(style: "background: #0f0f23; padding: 40px;") do
|
|
243
|
+
div(style: "font-size: 2rem; font-weight: 800; background: linear-gradient(135deg, #a78bfa, #60a5fa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 24px;") do
|
|
244
|
+
text "Architecture: [SYSTEM NAME]"
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
callout(:info) do
|
|
248
|
+
md "**Design principle:** [Why this architecture makes sense]"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
div(style: "height: 16px;")
|
|
252
|
+
|
|
253
|
+
mermaid(zoom: true) do
|
|
254
|
+
<<~MERMAID
|
|
255
|
+
graph TB
|
|
256
|
+
A[Client] --> B[API Gateway]
|
|
257
|
+
B --> C[Auth Service]
|
|
258
|
+
B --> D[Core Service]
|
|
259
|
+
D --> E[(Database)]
|
|
260
|
+
C --> E
|
|
261
|
+
MERMAID
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
div(style: "height: 16px;")
|
|
265
|
+
|
|
266
|
+
callout(:warning) do
|
|
267
|
+
md "**Watch out for:** [Tradeoffs or gotchas]"
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 3. Step-by-Step Tutorial
|
|
273
|
+
```ruby
|
|
274
|
+
theme_preset :technical
|
|
275
|
+
|
|
276
|
+
div(style: "background: #0f0f23; padding: 40px;") do
|
|
277
|
+
header2 "Tutorial: [TOPIC]"
|
|
278
|
+
|
|
279
|
+
div(style: "height: 16px;")
|
|
280
|
+
|
|
281
|
+
progress_bar(value: 33, label: "Step 1 of 3", animated: true,
|
|
282
|
+
style: "accent-color: #a78bfa;")
|
|
283
|
+
|
|
284
|
+
div(style: "height: 16px;")
|
|
285
|
+
|
|
286
|
+
slide_container(mode: :swap) do
|
|
287
|
+
slide do
|
|
288
|
+
card(style: "background: rgba(255,255,255,0.05); border-radius: 12px; padding: 24px; border: 1px solid rgba(167,139,250,0.3);") do
|
|
289
|
+
header3 "Step 1: [Title]"
|
|
290
|
+
md "[Explanation of step 1]"
|
|
291
|
+
code_block(language: :ruby) { "# step 1 code" }
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
slide do
|
|
296
|
+
card(style: "background: rgba(255,255,255,0.05); border-radius: 12px; padding: 24px; border: 1px solid rgba(96,165,250,0.3);") do
|
|
297
|
+
header3 "Step 2: [Title]"
|
|
298
|
+
md "[Explanation of step 2]"
|
|
299
|
+
code_block(language: :ruby) { "# step 2 code" }
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
slide do
|
|
304
|
+
card(style: "background: rgba(255,255,255,0.05); border-radius: 12px; padding: 24px; border: 1px solid rgba(52,211,153,0.3);") do
|
|
305
|
+
header3 "Step 3: [Title]"
|
|
306
|
+
md "[Explanation of step 3]"
|
|
307
|
+
code_block(language: :ruby) { "# step 3 code" }
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
keyboard_shortcuts # enables left/right arrow navigation
|
|
313
|
+
end
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### 4. Dashboard / Metrics
|
|
317
|
+
```ruby
|
|
318
|
+
theme_preset :technical
|
|
319
|
+
|
|
320
|
+
div(style: "background: #0f0f23; padding: 40px;") do
|
|
321
|
+
header2 "Metrics: [SYSTEM NAME]"
|
|
322
|
+
div(style: "height: 16px;")
|
|
323
|
+
|
|
324
|
+
kpi_dashboard(metrics: [
|
|
325
|
+
{ label: "Total Requests", value: "1.2M", trend: "+12%", trend_direction: :up },
|
|
326
|
+
{ label: "Error Rate", value: "0.03%", trend: "-0.01%", trend_direction: :down },
|
|
327
|
+
{ label: "Avg Latency", value: "42ms", trend: "+2ms", trend_direction: :neutral },
|
|
328
|
+
{ label: "Uptime", value: "99.97%", trend: "30d", trend_direction: :up }
|
|
329
|
+
])
|
|
330
|
+
|
|
331
|
+
div(style: "height: 24px;")
|
|
332
|
+
|
|
333
|
+
hstack do
|
|
334
|
+
chart(type: :line, data: {
|
|
335
|
+
labels: ["Jan", "Feb", "Mar", "Apr", "May"],
|
|
336
|
+
datasets: [{ label: "Requests", data: [800, 950, 1100, 1050, 1200] }]
|
|
337
|
+
}, style: "flex: 1;")
|
|
338
|
+
|
|
339
|
+
div(style: "width: 24px;") # gap
|
|
340
|
+
|
|
341
|
+
chart(type: :doughnut, data: {
|
|
342
|
+
labels: ["2xx", "4xx", "5xx"],
|
|
343
|
+
datasets: [{ data: [94, 5, 1] }]
|
|
344
|
+
}, style: "flex: 1; max-width: 300px;")
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
div(style: "height: 24px;")
|
|
348
|
+
|
|
349
|
+
table(headers: ["Endpoint", "Calls", "P99 Latency", "Errors"],
|
|
350
|
+
rows: [
|
|
351
|
+
["/api/users", "420K", "38ms", "0.02%"],
|
|
352
|
+
["/api/orders", "380K", "55ms", "0.04%"],
|
|
353
|
+
["/api/search", "400K", "120ms", "0.01%"]
|
|
354
|
+
])
|
|
355
|
+
end
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 5. Before/After Refactor
|
|
359
|
+
```ruby
|
|
360
|
+
theme_preset :technical
|
|
361
|
+
|
|
362
|
+
div(style: "background: #0f0f23; padding: 40px;") do
|
|
363
|
+
div(style: "font-size: 2rem; font-weight: 800; background: linear-gradient(135deg, #f87171, #a78bfa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 8px;") do
|
|
364
|
+
text "Refactor: [WHAT CHANGED]"
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
callout(:tip) do
|
|
368
|
+
md "**Why this change:** [The motivation — performance, readability, correctness]"
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
div(style: "height: 24px;")
|
|
372
|
+
|
|
373
|
+
comparison do
|
|
374
|
+
slot(:before) do
|
|
375
|
+
card(style: "background: rgba(248,113,113,0.05); border: 1px solid rgba(248,113,113,0.2); border-radius: 12px; padding: 20px;") do
|
|
376
|
+
header4 "❌ Before"
|
|
377
|
+
code_block(language: :ruby) do
|
|
378
|
+
<<~RUBY
|
|
379
|
+
# The old way
|
|
380
|
+
# problems: [list them]
|
|
381
|
+
def old_method
|
|
382
|
+
"old implementation"
|
|
383
|
+
end
|
|
384
|
+
RUBY
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
slot(:after) do
|
|
390
|
+
card(style: "background: rgba(52,211,153,0.05); border: 1px solid rgba(52,211,153,0.2); border-radius: 12px; padding: 20px;") do
|
|
391
|
+
header4 "✅ After"
|
|
392
|
+
code_block(language: :ruby) do
|
|
393
|
+
<<~RUBY
|
|
394
|
+
# The new way
|
|
395
|
+
# benefits: [list them]
|
|
396
|
+
def new_method
|
|
397
|
+
"new implementation"
|
|
398
|
+
end
|
|
399
|
+
RUBY
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
div(style: "height: 16px;")
|
|
406
|
+
|
|
407
|
+
callout(:success) do
|
|
408
|
+
md "**Result:** [Measurable improvement — faster, cleaner, safer]"
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## Gotchas and Rules
|
|
416
|
+
|
|
417
|
+
These are hard-won lessons — follow them or things break:
|
|
418
|
+
|
|
419
|
+
### ⚠️ No `spacer` or `divider` Component
|
|
420
|
+
They don't exist. For vertical spacing, use:
|
|
421
|
+
```ruby
|
|
422
|
+
div(style: "height: 16px;") # or 8px, 24px, 32px
|
|
423
|
+
```
|
|
424
|
+
For horizontal rules / dividers:
|
|
425
|
+
```ruby
|
|
426
|
+
div(style: "border-top: 1px solid rgba(255,255,255,0.1); margin: 24px 0;")
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### ⚠️ Use `md` Not `text` for Markdown Content
|
|
430
|
+
`text` renders plain text. `md` (or `markdown`) renders Markdown with bold, italic, links, lists, etc.
|
|
431
|
+
```ruby
|
|
432
|
+
# WRONG:
|
|
433
|
+
text "This has **bold** that won't render"
|
|
434
|
+
|
|
435
|
+
# RIGHT:
|
|
436
|
+
md "This has **bold** that renders correctly"
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### ⚠️ Never Launch a Standalone Server
|
|
440
|
+
Don't generate DSL that includes:
|
|
441
|
+
- `StreamWeaver::Server.start`
|
|
442
|
+
- `Sinatra::Application.run!`
|
|
443
|
+
- Any `require 'webrick'` or direct server-start code
|
|
444
|
+
|
|
445
|
+
The canvas server is already running. Use `canvas-push` to update it.
|
|
446
|
+
|
|
447
|
+
### ⚠️ `canvas-push` Only — No File-Based Serving
|
|
448
|
+
Always push to the persistent canvas session:
|
|
449
|
+
```bash
|
|
450
|
+
streamweaver canvas-push <session> <dsl_file>
|
|
451
|
+
```
|
|
452
|
+
Don't try to open new browser windows, don't serve files directly, don't assume the user wants to navigate away from the panel pane.
|
|
453
|
+
|
|
454
|
+
### ⚠️ `theme_preset` Must Be at the Top
|
|
455
|
+
```ruby
|
|
456
|
+
# RIGHT — theme_preset is the first thing:
|
|
457
|
+
theme_preset :technical
|
|
458
|
+
div do
|
|
459
|
+
# content
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# WRONG — theme_preset after content may not apply correctly:
|
|
463
|
+
div do
|
|
464
|
+
theme_preset :technical # too late
|
|
465
|
+
# content
|
|
466
|
+
end
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### ⚠️ Inline `style:` Strings Must Be Valid CSS
|
|
470
|
+
The `style:` param on any component passes through directly to the HTML `style` attribute. A syntax error will silently fail to apply. Double-check property names and semicolons.
|
|
471
|
+
|
|
472
|
+
### ⚠️ `comparison` Slots Are Named `:before` / `:after`
|
|
473
|
+
```ruby
|
|
474
|
+
comparison do
|
|
475
|
+
slot(:before) { ... } # correct
|
|
476
|
+
slot(:after) { ... } # correct
|
|
477
|
+
# NOT: slot(:left), slot(:right), slot(:one), slot(:two)
|
|
478
|
+
end
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### ⚠️ `slide_container` Needs `keyboard_shortcuts` for Arrow Nav
|
|
482
|
+
```ruby
|
|
483
|
+
slide_container(mode: :swap) do
|
|
484
|
+
slide { ... }
|
|
485
|
+
slide { ... }
|
|
486
|
+
end
|
|
487
|
+
keyboard_shortcuts # add this! otherwise no keyboard navigation
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Example: Full Session Script
|
|
493
|
+
|
|
494
|
+
Here's what a Claude Code session might look like when the skill is active:
|
|
495
|
+
|
|
496
|
+
```
|
|
497
|
+
User: "Explain how our auth middleware chain works"
|
|
498
|
+
|
|
499
|
+
Claude Code:
|
|
500
|
+
1. Reads the middleware files
|
|
501
|
+
2. Pushes this to canvas:
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
```ruby
|
|
505
|
+
theme_preset :technical
|
|
506
|
+
div(style: "background: #0f0f23; padding: 40px;") do
|
|
507
|
+
div(style: "font-size: 2rem; font-weight: 800; background: linear-gradient(135deg, #a78bfa, #60a5fa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 24px;") do
|
|
508
|
+
text "Auth Middleware Chain"
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
callout(:info) do
|
|
512
|
+
md "**How it works:** Each request passes through 3 middleware layers before hitting your controller. Each layer can halt the chain by returning early."
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
div(style: "height: 16px;")
|
|
516
|
+
|
|
517
|
+
mermaid(zoom: true) do
|
|
518
|
+
<<~MERMAID
|
|
519
|
+
sequenceDiagram
|
|
520
|
+
participant C as Client
|
|
521
|
+
participant T as TokenValidator
|
|
522
|
+
participant P as PermissionCheck
|
|
523
|
+
participant R as RateLimiter
|
|
524
|
+
participant Ctrl as Controller
|
|
525
|
+
|
|
526
|
+
C->>T: Request + Bearer token
|
|
527
|
+
T-->>C: 401 if invalid
|
|
528
|
+
T->>P: Validated identity
|
|
529
|
+
P-->>C: 403 if insufficient role
|
|
530
|
+
P->>R: Authorized user
|
|
531
|
+
R-->>C: 429 if rate exceeded
|
|
532
|
+
R->>Ctrl: Clean request
|
|
533
|
+
Ctrl-->>C: Response
|
|
534
|
+
MERMAID
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
div(style: "height: 16px;")
|
|
538
|
+
|
|
539
|
+
code_block(language: :ruby) do
|
|
540
|
+
<<~RUBY
|
|
541
|
+
# config/middleware.rb
|
|
542
|
+
use TokenValidator # Layer 1: Is this token real?
|
|
543
|
+
use PermissionCheck # Layer 2: Can this user do this?
|
|
544
|
+
use RateLimiter # Layer 3: Are they hitting us too fast?
|
|
545
|
+
RUBY
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
```
|
|
551
|
+
3. Continues the text explanation in the terminal, pointing to the visual
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
## Skill Identity (For Future SKILL.md)
|
|
557
|
+
|
|
558
|
+
When this spec is validated and ready to be formalized:
|
|
559
|
+
|
|
560
|
+
- **Skill name:** `streamweaver-claude-code-companion`
|
|
561
|
+
- **Trigger phrases:** "explain", "show me", "visualize", "diagram", "architecture", "compare", "step by step", "walk me through"
|
|
562
|
+
- **Required context:** `SW_CANVAS_SESSION` env var set, `streamweaver panel` running
|
|
563
|
+
- **Primary tool:** `streamweaver canvas-push`
|
|
564
|
+
- **Templates to include:** All five quick-copy templates from this spec
|
|
565
|
+
- **Aesthetic default:** `theme_preset :technical` + dark gradient wrapper
|
|
566
|
+
|
|
567
|
+
The SKILL.md will be written by converting this specification into the Hermes skill format, with the templates as literal snippet blocks Claude Code can emit directly.
|