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,127 @@
|
|
|
1
|
+
# Canvas IPC Session Summary
|
|
2
|
+
|
|
3
|
+
**Date:** January 2025
|
|
4
|
+
**Branch:** `feature/canvas-ipc`
|
|
5
|
+
**Status:** OUTDATED - Canvas is now working and actively used
|
|
6
|
+
|
|
7
|
+
> **Note:** This doc is historical. Canvas IPC is now fully functional.
|
|
8
|
+
> See `docs/canvas-panel-workflow.md` for current documentation.
|
|
9
|
+
|
|
10
|
+
## What We Attempted
|
|
11
|
+
|
|
12
|
+
Implement two-way IPC similar to [claude-canvas](https://github.com/BEARLY-HODLING/claude-canvas):
|
|
13
|
+
- Unix socket for Claude CLI ↔ Bridge communication
|
|
14
|
+
- WebSocket mode for Bridge ↔ Browser (partially implemented)
|
|
15
|
+
- Commands: `canvas`, `canvas-push`, `canvas-wait`, `canvas-close`, `pick`, `confirm`
|
|
16
|
+
|
|
17
|
+
## Overlap with Template Approach
|
|
18
|
+
|
|
19
|
+
Both solve the same problem: **Push UI → Wait for response → Get JSON**
|
|
20
|
+
|
|
21
|
+
| Feature | Canvas (this session) | Templates (other thread) |
|
|
22
|
+
|---------|----------------------|-------------------------|
|
|
23
|
+
| Push UI | `canvas-push` via Unix socket | `push` via HTTP |
|
|
24
|
+
| Wait for response | `canvas-wait` (Unix socket, broken) | `wait` (HTTP polling, working) |
|
|
25
|
+
| Confirm dialog | `streamweaver confirm` | `streamweaver template confirm` |
|
|
26
|
+
| Pick/choices | `streamweaver pick` | `streamweaver template choices` |
|
|
27
|
+
|
|
28
|
+
**The template approach won** - simpler architecture, working code.
|
|
29
|
+
|
|
30
|
+
## Dead Code (if going with templates)
|
|
31
|
+
|
|
32
|
+
### Files to Delete (~1023 lines)
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
lib/stream_weaver/canvas/
|
|
36
|
+
protocol.rb # 69 lines - Unix socket message encoding
|
|
37
|
+
session.rb # 66 lines - Session with websocket tracking
|
|
38
|
+
bridge.rb # 161 lines - Message routing
|
|
39
|
+
client.rb # 205 lines - CLI to Unix socket communication
|
|
40
|
+
bridge_server.rb # 413 lines - Sinatra + Unix socket server
|
|
41
|
+
helpers.rb # 109 lines - DSL generators (overlaps with templates)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### CLI Commands to Remove (cli.rb lines 58-73)
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
when 'canvas' # line 58
|
|
48
|
+
when 'canvas-push' # line 60
|
|
49
|
+
when 'canvas-wait' # line 62
|
|
50
|
+
when 'canvas-close' # line 64
|
|
51
|
+
when 'canvas-list' # line 66
|
|
52
|
+
when 'canvas-stop' # line 68
|
|
53
|
+
when 'pick' # line 71 (use `template choices` instead)
|
|
54
|
+
when 'confirm' # line 73 (use `template confirm` instead)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Plus the method implementations (~300 lines):
|
|
58
|
+
- `canvas_session`
|
|
59
|
+
- `canvas_push`
|
|
60
|
+
- `canvas_wait`
|
|
61
|
+
- `canvas_close`
|
|
62
|
+
- `canvas_list`
|
|
63
|
+
- `canvas_stop`
|
|
64
|
+
- `canvas_pick`
|
|
65
|
+
- `canvas_confirm`
|
|
66
|
+
|
|
67
|
+
### Dead Code in alpinejs.rb
|
|
68
|
+
|
|
69
|
+
WebSocket mode code (~100 lines) only used by canvas:
|
|
70
|
+
- Line 25-34: `mode` parameter and `websocket_mode?` method
|
|
71
|
+
- Line 317-335: WebSocket mode in `render_radio_group`
|
|
72
|
+
- Line 451-458: WebSocket mode in `render_button`
|
|
73
|
+
- Line 499-505: WebSocket mode in `container_attributes`
|
|
74
|
+
- Line 570-665: `websocket_init_script` method (sendEvent, getFormState, WebSocket connection)
|
|
75
|
+
|
|
76
|
+
## What's NOT Dead Code
|
|
77
|
+
|
|
78
|
+
### In alpinejs.rb - Keep These
|
|
79
|
+
|
|
80
|
+
The HTTP fallback for `sendEvent` and visual feedback are useful but currently embedded in websocket_init_script. If removing websocket mode, these would be lost.
|
|
81
|
+
|
|
82
|
+
### Templates Already Cover
|
|
83
|
+
|
|
84
|
+
- `templates/confirm.rb` - Better than `canvas/helpers.rb` confirm
|
|
85
|
+
- `templates/choices.rb` - Better than `pick` command
|
|
86
|
+
- `templates/wizard.rb` - Multi-step forms (no canvas equivalent)
|
|
87
|
+
- `templates/table.rb`, `code.rb`, `diff.rb`, `info.rb` - No canvas equivalents
|
|
88
|
+
|
|
89
|
+
## Recommendation
|
|
90
|
+
|
|
91
|
+
### Option A: Full Cleanup (Recommended)
|
|
92
|
+
|
|
93
|
+
1. Delete entire `lib/stream_weaver/canvas/` directory
|
|
94
|
+
2. Remove canvas-* and pick/confirm commands from CLI
|
|
95
|
+
3. Remove websocket mode from alpinejs.rb
|
|
96
|
+
4. Keep templates as the solution
|
|
97
|
+
|
|
98
|
+
**Effort:** ~1400 lines to remove
|
|
99
|
+
|
|
100
|
+
### Option B: Keep Canvas, Fix Later
|
|
101
|
+
|
|
102
|
+
1. Leave canvas code dormant
|
|
103
|
+
2. Document it as "experimental, use templates instead"
|
|
104
|
+
3. Maybe fix the socket forwarding someday
|
|
105
|
+
|
|
106
|
+
**Risk:** Confusion about which approach to use
|
|
107
|
+
|
|
108
|
+
### Option C: Salvage Pieces
|
|
109
|
+
|
|
110
|
+
1. Port visual feedback to templates
|
|
111
|
+
2. Port helpers.rb parsing fixes to templates
|
|
112
|
+
3. Then do Option A
|
|
113
|
+
|
|
114
|
+
## Files Changed Summary
|
|
115
|
+
|
|
116
|
+
| File | Change Type | Dead if using templates? |
|
|
117
|
+
|------|-------------|-------------------------|
|
|
118
|
+
| `lib/stream_weaver/canvas/*` | Created | YES - delete all |
|
|
119
|
+
| `lib/stream_weaver/cli.rb` | Modified | Partial - remove canvas commands |
|
|
120
|
+
| `lib/stream_weaver/adapter/alpinejs.rb` | Modified | Partial - remove websocket mode |
|
|
121
|
+
| `stream_weaver.gemspec` | Modified | Check if sinatra-contrib still needed |
|
|
122
|
+
| `docs/plans/2026-01-10-canvas-ipc-design.md` | Created | Archive or delete |
|
|
123
|
+
|
|
124
|
+
## Testing Note
|
|
125
|
+
|
|
126
|
+
No spec files were created for canvas (checked `spec/*canvas*` - empty).
|
|
127
|
+
Templates have their own tests in the other thread.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Canvas Panel Workflow
|
|
2
|
+
|
|
3
|
+
Two-way IPC for Claude Code integration. Open a side panel, push content, wait for user interaction, repeat.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Open panel (creates iTerm2 split with browser)
|
|
9
|
+
streamweaver panel myapp --fresh
|
|
10
|
+
|
|
11
|
+
# Push content
|
|
12
|
+
streamweaver canvas-push myapp <<'RUBY'
|
|
13
|
+
header1 "Pick an option"
|
|
14
|
+
radio_group :choice, ["A", "B", "C"]
|
|
15
|
+
button "Submit"
|
|
16
|
+
RUBY
|
|
17
|
+
|
|
18
|
+
# Wait for user interaction (returns JSON)
|
|
19
|
+
streamweaver canvas-wait myapp
|
|
20
|
+
# => {"choice": "B"}
|
|
21
|
+
|
|
22
|
+
# Close panel (also closes browser pane)
|
|
23
|
+
streamweaver canvas-close myapp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
| Command | Description |
|
|
29
|
+
|---------|-------------|
|
|
30
|
+
| `panel <name> [--fresh]` | Open split pane with browser. `--fresh` closes existing session first |
|
|
31
|
+
| `canvas-push <name>` | Push DSL content from stdin |
|
|
32
|
+
| `canvas-wait <name>` | Block until user clicks a button, returns form state as JSON |
|
|
33
|
+
| `canvas-toast <name> <msg>` | Show toast notification overlay |
|
|
34
|
+
| `canvas-close <name>` | Close session and browser pane |
|
|
35
|
+
| `canvas-raise <name>` | Surface an already-open session without opening a second pane: activates its tracked iTerm pane, or opens its URL in the default browser if there is none to reuse |
|
|
36
|
+
| `canvas-reset <name>` | Reset session state (keep connections) |
|
|
37
|
+
| `canvas-list` | List all canvas sessions |
|
|
38
|
+
|
|
39
|
+
## Multi-Step Workflows
|
|
40
|
+
|
|
41
|
+
Use `canvas_continue` to show a spinner after submit instead of "You can close this window":
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
streamweaver canvas-push myapp <<'RUBY'
|
|
45
|
+
card do
|
|
46
|
+
header1 "Step 1"
|
|
47
|
+
text_field :name, label: "Name"
|
|
48
|
+
button "Next"
|
|
49
|
+
end
|
|
50
|
+
canvas_continue message: "Processing..."
|
|
51
|
+
RUBY
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
After user clicks "Next", they see "Processing..." spinner until you push the next page.
|
|
55
|
+
|
|
56
|
+
**Final page** (no `canvas_continue`): Shows "Submitted - You can close this window"
|
|
57
|
+
|
|
58
|
+
## Panel Features
|
|
59
|
+
|
|
60
|
+
### Automatic Pane Tracking
|
|
61
|
+
|
|
62
|
+
When you open a panel, StreamWeaver tracks the iTerm2 pane ID. When you call `canvas-close`, it automatically closes the browser pane. `panel` always opens a NEW pane -- calling it a second time on a session that already has one duplicates it. To bring an existing session's pane back to the front instead (a push you made after the user's attention moved elsewhere, for example), use `canvas-raise <name>`.
|
|
63
|
+
|
|
64
|
+
### URL Fallback
|
|
65
|
+
|
|
66
|
+
If the browser doesn't auto-open, the panel command shows a URL you can paste manually:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Canvas 'myapp' ready
|
|
70
|
+
Browser opened in split pane
|
|
71
|
+
|
|
72
|
+
URL (if browser didn't open): http://localhost:4570/canvas/myapp
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## DSL Components
|
|
76
|
+
|
|
77
|
+
All standard StreamWeaver DSL components work in canvas mode:
|
|
78
|
+
|
|
79
|
+
- `header1`, `header2`, `header3` - Headings
|
|
80
|
+
- `md "text"` - Markdown content
|
|
81
|
+
- `text_field :key, label: "...", placeholder: "..."` - Text input
|
|
82
|
+
- `radio_group :key, ["opt1", "opt2"]` - Radio buttons
|
|
83
|
+
- `select :key, ["opt1", "opt2"]` - Dropdown
|
|
84
|
+
- `checkbox :key, label: "..."` - Checkbox
|
|
85
|
+
- `button "Label", id: "btn_id", style: :primary` - Submit button
|
|
86
|
+
- `card { ... }` - Card container
|
|
87
|
+
- `status_dot status: :green, pulse: true, label: "OK"` - Status indicator
|
|
88
|
+
- `badge "TEXT", variant: :success` - Badge/tag
|
|
89
|
+
- `table headers: [...], rows: [...]` - Data table
|
|
90
|
+
|
|
91
|
+
## Example: Verification Flow
|
|
92
|
+
|
|
93
|
+
See `examples/claude_code/verification_flow/` for a complete multi-step workflow:
|
|
94
|
+
|
|
95
|
+
1. Sign-up form with `canvas_continue`
|
|
96
|
+
2. Verification page with toast notification
|
|
97
|
+
3. Welcome page (final, no `canvas_continue`)
|
|
98
|
+
|
|
99
|
+
## Claude Code Integration
|
|
100
|
+
|
|
101
|
+
### Permissions
|
|
102
|
+
|
|
103
|
+
Add to `.claude/settings.local.json`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"permissions": {
|
|
108
|
+
"allow": ["Bash(streamweaver *)"]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Slash Command Pattern
|
|
114
|
+
|
|
115
|
+
Create `.claude/commands/myflow.md`:
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
# My Flow
|
|
119
|
+
|
|
120
|
+
## Instructions
|
|
121
|
+
|
|
122
|
+
### Phase 1: Open Panel
|
|
123
|
+
\`\`\`bash
|
|
124
|
+
streamweaver panel myflow --fresh
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
### Phase 2: First Page
|
|
128
|
+
\`\`\`bash
|
|
129
|
+
streamweaver canvas-push myflow <<'RUBY'
|
|
130
|
+
# DSL content here
|
|
131
|
+
canvas_continue message: "Loading..."
|
|
132
|
+
RUBY
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
Wait for input:
|
|
136
|
+
\`\`\`bash
|
|
137
|
+
streamweaver canvas-wait myflow
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
### Phase 3: Final Page
|
|
141
|
+
\`\`\`bash
|
|
142
|
+
streamweaver canvas-push myflow <<'RUBY'
|
|
143
|
+
# Final page - no canvas_continue
|
|
144
|
+
RUBY
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
### Cleanup
|
|
148
|
+
\`\`\`bash
|
|
149
|
+
streamweaver canvas-close myflow
|
|
150
|
+
\`\`\`
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Architecture
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
Claude Code CLI
|
|
157
|
+
│
|
|
158
|
+
▼
|
|
159
|
+
┌─────────────────┐
|
|
160
|
+
│ Unix Socket IPC │
|
|
161
|
+
└────────┬────────┘
|
|
162
|
+
│
|
|
163
|
+
▼
|
|
164
|
+
┌─────────────────┐ WebSocket ┌─────────────┐
|
|
165
|
+
│ Canvas Bridge │◄──────────────────►│ Browser │
|
|
166
|
+
│ (background) │ │ (iTerm2) │
|
|
167
|
+
└─────────────────┘ └─────────────┘
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- **Unix Socket**: CLI ↔ Bridge communication
|
|
171
|
+
- **WebSocket**: Bridge ↔ Browser real-time updates
|
|
172
|
+
- **Bridge**: Renders DSL to HTML, manages sessions, routes events
|
data/docs/canvas-read.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# canvas-read: the document shelf
|
|
2
|
+
|
|
3
|
+
The most portable way to read a StreamWeaver doc. No iTerm2, no Chrome extension, no
|
|
4
|
+
`gh` — just a local web server and a URL.
|
|
5
|
+
|
|
6
|
+
## What it is
|
|
7
|
+
|
|
8
|
+
`streamweaver canvas-read` starts a small local web server that renders one or more
|
|
9
|
+
StreamWeaver DSL/Org files with full styling: sidebar navigation, a per-doc table of
|
|
10
|
+
contents, callouts, cards, tables, live Mermaid diagrams, images. Point it at a file,
|
|
11
|
+
a directory, or nothing (it finds your docs automatically) and it prints a URL.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
streamweaver canvas-read notes.org
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
canvas-read 1 file(s) → http://127.0.0.1:4800/?file=0
|
|
19
|
+
Ctrl-C to stop
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Never assume the port.** StreamWeaver auto-finds an available one starting near 4800
|
|
23
|
+
and prints the real URL every time — read it from the command's own output.
|
|
24
|
+
|
|
25
|
+
## The happy path (tested: macOS + iTerm2)
|
|
26
|
+
|
|
27
|
+
1. Save or author a StreamWeaver doc (`.rb` or `.org` — see below).
|
|
28
|
+
2. Run `streamweaver canvas-read <file>`.
|
|
29
|
+
3. A browser tab opens automatically at the printed URL (iTerm2 users can instead pop
|
|
30
|
+
it into a split pane — see [canvas-panel-workflow.md](canvas-panel-workflow.md)).
|
|
31
|
+
4. Read, navigate the table of contents, click through Mermaid diagrams.
|
|
32
|
+
5. Ctrl-C the process when done.
|
|
33
|
+
|
|
34
|
+
## Authoring Org docs
|
|
35
|
+
|
|
36
|
+
Org is the portable, human-readable source format. Every StreamWeaver Org doc starts
|
|
37
|
+
with:
|
|
38
|
+
|
|
39
|
+
```org
|
|
40
|
+
#+STREAMWEAVER_DSL: 1
|
|
41
|
+
#+TITLE: Document Title
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Numbered headings with `CUSTOM_ID` properties become sections and drive the sidebar
|
|
45
|
+
table of contents. Ordinary prose, lists, tables, quotes, and source blocks read as
|
|
46
|
+
plain Org. Components with no native Org form (anything outside the recognized set
|
|
47
|
+
below) use a passthrough block:
|
|
48
|
+
|
|
49
|
+
```org
|
|
50
|
+
#+begin_src ruby :streamweaver-raw t
|
|
51
|
+
image_block File.join(__dir__, "assets/example.png"), base64: true,
|
|
52
|
+
alt: "Description"
|
|
53
|
+
#+end_src
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`.rb` (the DSL source) is the other option — canonical, always lossless, and what
|
|
57
|
+
`org-export`/`org-render` convert to and from.
|
|
58
|
+
|
|
59
|
+
## Opening one document
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
streamweaver canvas-read path/to/doc.org
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Works for both `.rb` and `.org` files.
|
|
66
|
+
|
|
67
|
+
## Opening a shelf
|
|
68
|
+
|
|
69
|
+
Pass multiple files, or a directory, and canvas-read turns them into a shelf: every
|
|
70
|
+
doc listed in a left rail, one click to switch between them.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
streamweaver canvas-read docs/proposals/
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
With no arguments at all, canvas-read scans your usual docs roots (this repo, if
|
|
77
|
+
you're in one, plus `~/.streamweaver`) and builds the shelf from whatever it finds —
|
|
78
|
+
handy for a quick `streamweaver canvas-read` with nothing else typed.
|
|
79
|
+
|
|
80
|
+
## Comparing versions
|
|
81
|
+
|
|
82
|
+
The left rail lists every document in the shelf; click any entry to switch. Inside a
|
|
83
|
+
document, **Previous/Next** buttons step through the shelf in order, and each
|
|
84
|
+
document's own generated table of contents lets you jump to a section directly. This
|
|
85
|
+
is the pattern from the [DiDX case study](case-studies/2026-09-03-didx-canvas-read-shelf.md):
|
|
86
|
+
keep a neutral version, a personal-voice version, and a technical version side by
|
|
87
|
+
side, and compare them without leaving the shelf.
|
|
88
|
+
|
|
89
|
+
## Working with images
|
|
90
|
+
|
|
91
|
+
Ordinary relative image paths don't have a backing asset route in canvas-read.
|
|
92
|
+
Use `image_block` with `base64: true` so the image is embedded directly:
|
|
93
|
+
|
|
94
|
+
```org
|
|
95
|
+
#+begin_src ruby :streamweaver-raw t
|
|
96
|
+
image_block File.join(__dir__, "assets/diagram.png"), base64: true, alt: "Architecture"
|
|
97
|
+
#+end_src
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Without `base64: true`, the image won't resolve — this is the one gotcha worth
|
|
101
|
+
knowing before you build a doc full of screenshots.
|
|
102
|
+
|
|
103
|
+
## Exporting or packaging
|
|
104
|
+
|
|
105
|
+
- `streamweaver export file.rb` writes a saved DSL doc out as standalone HTML
|
|
106
|
+
(`--inline-images` to embed local images, `--offline` to inline the Mermaid
|
|
107
|
+
library for viewers with a strict CSP).
|
|
108
|
+
- `.rb` and `.org` docs checked into a GitHub repo or Gist render with full
|
|
109
|
+
StreamWeaver styling via the [browser extension](../extension/README.md) — no
|
|
110
|
+
install, no Ruby, no server required for the reader.
|
|
111
|
+
|
|
112
|
+
See the known gap below for `streamweaver export` on `.org` files specifically.
|
|
113
|
+
|
|
114
|
+
## Platform support
|
|
115
|
+
|
|
116
|
+
canvas-read is the most portable piece of StreamWeaver — see the
|
|
117
|
+
[Platform support matrix](../README.md#platform-support) in the README. In short: it's
|
|
118
|
+
a plain local web server, so it's expected to work anywhere Ruby and a browser do,
|
|
119
|
+
independent of iTerm2, Chrome, or `gh`.
|
|
120
|
+
|
|
121
|
+
## No-iTerm degraded demo
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
SW_NO_OPEN=1 streamweaver canvas-read docs/
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`SW_NO_OPEN=1` skips the auto-open — the command prints its URL and exits into the
|
|
128
|
+
running server; open that URL in any browser yourself. Expect the shelf to list every
|
|
129
|
+
Org and Ruby doc under `docs/`, with navigation, table of contents, images, diagrams,
|
|
130
|
+
and reading mode all working, no iTerm2 required.
|
|
131
|
+
|
|
132
|
+
## Known gaps
|
|
133
|
+
|
|
134
|
+
- **disc-175 — `streamweaver export` doesn't accept `.org` files first-class.**
|
|
135
|
+
`canvas-read` handles Org source directly; `export` still tries to eval the raw Org
|
|
136
|
+
text as Ruby and fails. The workaround (`Org::Reader.to_dsl` → `App` →
|
|
137
|
+
`HtmlExporter`) is documented in the
|
|
138
|
+
[case study](case-studies/2026-09-03-didx-canvas-read-shelf.md#important-export-gap).
|
|
139
|
+
- **disc-176 — canvas-read doesn't rewrite cross-document links.** Same-document Org
|
|
140
|
+
anchors work; a relative link from one Org doc to another in the same shelf isn't
|
|
141
|
+
rewritten into a canvas-read navigation URL. The shelf's left rail is the workaround
|
|
142
|
+
today — MarkyMark has prior art for rewriting relative links into reader routes.
|
|
143
|
+
|
|
144
|
+
## Case study
|
|
145
|
+
|
|
146
|
+
This guide's structure follows the write-up from a real multi-document session:
|
|
147
|
+
[Case study: the Org + canvas-read document shelf (DiDX proposal session)](case-studies/2026-09-03-didx-canvas-read-shelf.md).
|