pixelweaver 0.1.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.
- package/.env.development +1 -0
- package/.github/workflows/ci.yml +22 -0
- package/.github/workflows/publish.yml +18 -0
- package/.prettierignore +5 -0
- package/.prettierrc +16 -0
- package/.python-version +1 -0
- package/.rlsbl/bases/.github/workflows/ci.yml +21 -0
- package/.rlsbl/bases/.github/workflows/publish.yml +18 -0
- package/.rlsbl/bases/.rlsbl/changes/unreleased.jsonl +0 -0
- package/.rlsbl/bases/.rlsbl/hooks/post-release.sh +8 -0
- package/.rlsbl/bases/.rlsbl/hooks/pre-checks.sh +5 -0
- package/.rlsbl/bases/.rlsbl/hooks/pre-release.sh +8 -0
- package/.rlsbl/bases/.rlsbl/lint/go.toml +17 -0
- package/.rlsbl/bases/.rlsbl/lint/npm.toml +19 -0
- package/.rlsbl/bases/.rlsbl/lint/python.toml +25 -0
- package/.rlsbl/bases/CHANGELOG.md +5 -0
- package/.rlsbl/bases/LICENSE +21 -0
- package/.rlsbl/changes/.validated +1 -0
- package/.rlsbl/changes/0.1.0.jsonl +85 -0
- package/.rlsbl/changes/0.1.0.md +13 -0
- package/.rlsbl/changes/unreleased.jsonl +0 -0
- package/.rlsbl/config.json +6 -0
- package/.rlsbl/hashes.json +14 -0
- package/.rlsbl/hooks/post-release.sh +8 -0
- package/.rlsbl/hooks/pre-checks.sh +5 -0
- package/.rlsbl/hooks/pre-release.sh +8 -0
- package/.rlsbl/lint/go.toml +17 -0
- package/.rlsbl/lint/npm.toml +19 -0
- package/.rlsbl/lint/python.toml +25 -0
- package/.rlsbl/releases/unreleased.toml +0 -0
- package/.rlsbl/releases/v0.1.0.toml +3 -0
- package/.rlsbl/version +1 -0
- package/.selfdoc/hashes/hashes.json +146 -0
- package/.strictcli/schema.json +227 -0
- package/CHANGELOG.md +17 -0
- package/CLAUDE.md +100 -0
- package/LICENSE +21 -0
- package/README.md +116 -0
- package/assets/icon.png +0 -0
- package/docs/_README.md +117 -0
- package/docs/cli-config.md +35 -0
- package/docs/cli-dev.md +21 -0
- package/docs/cli-diagnose.md +12 -0
- package/docs/cli-index.md +30 -0
- package/docs/cli-list.md +18 -0
- package/docs/cli-mcp.md +18 -0
- package/docs/cli-new.md +26 -0
- package/docs/cli-open.md +21 -0
- package/docs/cli-serve.md +21 -0
- package/docs/cli-stop.md +12 -0
- package/docs/gen-index.md +36 -0
- package/docs/index.md +13 -0
- package/docs/server-src-pixelweaver-__main__.md +12 -0
- package/docs/server-src-pixelweaver-autosave.md +12 -0
- package/docs/server-src-pixelweaver-bridge.md +12 -0
- package/docs/server-src-pixelweaver-cli.md +12 -0
- package/docs/server-src-pixelweaver-config.md +12 -0
- package/docs/server-src-pixelweaver-connections.md +12 -0
- package/docs/server-src-pixelweaver-main.md +12 -0
- package/docs/server-src-pixelweaver-mcp_bridge.md +12 -0
- package/docs/server-src-pixelweaver-mcp_drawing_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_export_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_frame_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_history_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_layer_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_lock.md +12 -0
- package/docs/server-src-pixelweaver-mcp_project_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_read_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_registry.md +12 -0
- package/docs/server-src-pixelweaver-mcp_resources.md +12 -0
- package/docs/server-src-pixelweaver-mcp_server.md +12 -0
- package/docs/server-src-pixelweaver-protocol.md +12 -0
- package/docs/server-src-pixelweaver-state.md +12 -0
- package/docs/server-src-pixelweaver-storage.md +12 -0
- package/docs/server-src-pixelweaver-websocket.md +12 -0
- package/docs/server-src-pixelweaver.md +12 -0
- package/e2e/app-launch.test.ts +35 -0
- package/e2e/menus.test.ts +26 -0
- package/e2e/tools.test.ts +27 -0
- package/e2e/undo-redo.test.ts +11 -0
- package/eslint.config.js +62 -0
- package/index.html +13 -0
- package/package.json +48 -0
- package/playwright.config.ts +19 -0
- package/plugins/builtin/.gitkeep +0 -0
- package/plugins/builtin/advanced-fill-tool.ts +146 -0
- package/plugins/builtin/circle-tool.ts +186 -0
- package/plugins/builtin/diamond-tool.ts +182 -0
- package/plugins/builtin/dither-tool.ts +186 -0
- package/plugins/builtin/drawing-primitives-plugin.ts +362 -0
- package/plugins/builtin/drawing-utils.test.ts +495 -0
- package/plugins/builtin/drawing-utils.ts +431 -0
- package/plugins/builtin/effects/blur.ts +97 -0
- package/plugins/builtin/effects/color-effects.ts +278 -0
- package/plugins/builtin/effects/flip.ts +83 -0
- package/plugins/builtin/effects/glow.ts +118 -0
- package/plugins/builtin/effects/outline.ts +110 -0
- package/plugins/builtin/effects/rotate.ts +357 -0
- package/plugins/builtin/effects/scale.ts +258 -0
- package/plugins/builtin/effects/shadow.ts +111 -0
- package/plugins/builtin/effects/sharpen.ts +102 -0
- package/plugins/builtin/effects.test.ts +715 -0
- package/plugins/builtin/eraser-tool.ts +23 -0
- package/plugins/builtin/eyedropper-tool.ts +83 -0
- package/plugins/builtin/fill-tool.ts +93 -0
- package/plugins/builtin/gradient-tool.ts +204 -0
- package/plugins/builtin/gradient.test.ts +142 -0
- package/plugins/builtin/importers/aseprite-importer-plugin.ts +174 -0
- package/plugins/builtin/importers/aseprite-parser.ts +497 -0
- package/plugins/builtin/importers/piskel-importer-plugin.ts +222 -0
- package/plugins/builtin/importers/sky-spec-plugin.ts +409 -0
- package/plugins/builtin/line-tool.ts +267 -0
- package/plugins/builtin/make-stroke-tool.ts +271 -0
- package/plugins/builtin/noise-dither.test.ts +151 -0
- package/plugins/builtin/noise-tool.ts +131 -0
- package/plugins/builtin/pattern-stamp-tool.ts +162 -0
- package/plugins/builtin/pencil-tool.ts +25 -0
- package/plugins/builtin/rect-tool.ts +179 -0
- package/plugins/builtin/selection-tool.ts +388 -0
- package/plugins/builtin/selection.test.ts +195 -0
- package/plugins/builtin/tool-plugins.test.ts +529 -0
- package/public/favicon.svg +7 -0
- package/public/sw.js +91 -0
- package/pyproject.toml +49 -0
- package/scripts/eslint-wave-a-list.sh +24 -0
- package/scripts/eslint-wave-a-status.sh +25 -0
- package/scripts/fix-index-signature-access.py +127 -0
- package/scripts/fix-unchecked-index.py +128 -0
- package/scripts/fix-unchecked-vars.py +127 -0
- package/scripts/fix-wave-a-bangs.py +36 -0
- package/scripts/fix-wave-a-templates.py +108 -0
- package/scripts/fix-wave-b-void-expr.py +167 -0
- package/scripts/generate-command-params.py +540 -0
- package/scripts/migrate-single-frame-to-multi.py +171 -0
- package/scripts/smoke-test.sh +77 -0
- package/selfdoc.json +10 -0
- package/server/README.md +0 -0
- package/server/src/pixelweaver/__init__.py +1 -0
- package/server/src/pixelweaver/__main__.py +4 -0
- package/server/src/pixelweaver/autosave.py +114 -0
- package/server/src/pixelweaver/bridge.py +127 -0
- package/server/src/pixelweaver/cli.py +199 -0
- package/server/src/pixelweaver/config.py +24 -0
- package/server/src/pixelweaver/connections.py +54 -0
- package/server/src/pixelweaver/main.py +271 -0
- package/server/src/pixelweaver/mcp_bridge.py +189 -0
- package/server/src/pixelweaver/mcp_drawing_tools.py +178 -0
- package/server/src/pixelweaver/mcp_export_tools.py +291 -0
- package/server/src/pixelweaver/mcp_frame_tools.py +423 -0
- package/server/src/pixelweaver/mcp_history_tools.py +106 -0
- package/server/src/pixelweaver/mcp_layer_tools.py +64 -0
- package/server/src/pixelweaver/mcp_lock.py +37 -0
- package/server/src/pixelweaver/mcp_project_tools.py +302 -0
- package/server/src/pixelweaver/mcp_read_tools.py +163 -0
- package/server/src/pixelweaver/mcp_registry.py +247 -0
- package/server/src/pixelweaver/mcp_resources.py +312 -0
- package/server/src/pixelweaver/mcp_server.py +234 -0
- package/server/src/pixelweaver/protocol.py +219 -0
- package/server/src/pixelweaver/state.py +267 -0
- package/server/src/pixelweaver/storage.py +293 -0
- package/server/src/pixelweaver/websocket.py +282 -0
- package/server/tests/__init__.py +0 -0
- package/server/tests/conftest.py +17 -0
- package/server/tests/test_api.py +96 -0
- package/server/tests/test_bridge.py +161 -0
- package/server/tests/test_health.py +9 -0
- package/server/tests/test_integration.py +86 -0
- package/server/tests/test_mcp_bridge.py +293 -0
- package/server/tests/test_mcp_lock.py +34 -0
- package/server/tests/test_mcp_registry.py +679 -0
- package/server/tests/test_mcp_resources.py +648 -0
- package/server/tests/test_protocol.py +125 -0
- package/server/tests/test_state.py +87 -0
- package/server/tests/test_storage.py +306 -0
- package/server/tests/test_websocket.py +275 -0
- package/src/App.svelte +107 -0
- package/src/app.css +215 -0
- package/src/lib/animation/AnimationPreviewPanel.svelte +667 -0
- package/src/lib/animation/animation-commands.test.ts +228 -0
- package/src/lib/animation/animation-commands.ts +540 -0
- package/src/lib/animation/animation-preview-panel-plugin.ts +25 -0
- package/src/lib/animation/animation-preview.svelte.ts +151 -0
- package/src/lib/animation/clipboard.ts +134 -0
- package/src/lib/animation/frame-model.svelte.ts +437 -0
- package/src/lib/animation/frame-model.test.ts +314 -0
- package/src/lib/animation/frame-selection.svelte.ts +77 -0
- package/src/lib/animation/frame-tags.svelte.ts +238 -0
- package/src/lib/animation/frame-tags.test.ts +136 -0
- package/src/lib/animation/import.test.ts +141 -0
- package/src/lib/animation/import.ts +112 -0
- package/src/lib/animation/spritesheet-export.test.ts +239 -0
- package/src/lib/animation/spritesheet-export.ts +314 -0
- package/src/lib/canvas/CanvasViewport.svelte +216 -0
- package/src/lib/canvas/canvas-init-plugin.ts +178 -0
- package/src/lib/canvas/canvas-renderer.ts +408 -0
- package/src/lib/canvas/canvas-state.svelte.ts +232 -0
- package/src/lib/canvas/canvas-state.test.ts +139 -0
- package/src/lib/canvas/input-handler.ts +221 -0
- package/src/lib/canvas/input-plugin.ts +150 -0
- package/src/lib/canvas/onion-skin.ts +94 -0
- package/src/lib/canvas/pixel-buffer.test.ts +249 -0
- package/src/lib/canvas/pixel-buffer.ts +151 -0
- package/src/lib/canvas/render-state.svelte.ts +18 -0
- package/src/lib/canvas/shape-preview-state.svelte.ts +36 -0
- package/src/lib/canvas/tile-mode.test.ts +53 -0
- package/src/lib/canvas/tile-mode.ts +92 -0
- package/src/lib/canvas/viewport-utils.ts +24 -0
- package/src/lib/canvas/zoom-utils.ts +31 -0
- package/src/lib/color/.gitkeep +0 -0
- package/src/lib/color/color-commands.ts +87 -0
- package/src/lib/color/color-state.svelte.ts +98 -0
- package/src/lib/color/color-state.test.ts +91 -0
- package/src/lib/color/color-utils.test.ts +220 -0
- package/src/lib/color/color-utils.ts +243 -0
- package/src/lib/color/palette-state.svelte.ts +127 -0
- package/src/lib/color/palette-state.test.ts +154 -0
- package/src/lib/color/palette.ts +79 -0
- package/src/lib/core/bootstrap.ts +66 -0
- package/src/lib/core/command-params.generated.ts +1549 -0
- package/src/lib/core/command-params.ts +20 -0
- package/src/lib/core/command-runner.ts +79 -0
- package/src/lib/core/commands.ts +134 -0
- package/src/lib/core/dispatcher.test.ts +548 -0
- package/src/lib/core/dispatcher.ts +361 -0
- package/src/lib/core/index.test.ts +7 -0
- package/src/lib/core/notification-state.svelte.ts +119 -0
- package/src/lib/core/plugin-api.ts +210 -0
- package/src/lib/core/plugin-discovery.test.ts +53 -0
- package/src/lib/core/plugin-discovery.ts +65 -0
- package/src/lib/core/plugin-loader.test.ts +159 -0
- package/src/lib/core/plugin-loader.ts +240 -0
- package/src/lib/core/plugin-types.ts +286 -0
- package/src/lib/core/registries.svelte.ts +74 -0
- package/src/lib/core/tool-options-state.svelte.ts +61 -0
- package/src/lib/dock/DockLayout.svelte +375 -0
- package/src/lib/dock/TabAddMenu.svelte +90 -0
- package/src/lib/dock/dock-persistence.ts +46 -0
- package/src/lib/dock/dock-plugin.ts +49 -0
- package/src/lib/dock/dock-presets.ts +156 -0
- package/src/lib/dock/dock-state.svelte.ts +77 -0
- package/src/lib/dock/dock-types.ts +2 -0
- package/src/lib/dock/dockview-theme.css +226 -0
- package/src/lib/dock/dockview-theme.ts +17 -0
- package/src/lib/dock/header-action-renderer.ts +77 -0
- package/src/lib/edit/clipboard-state.ts +34 -0
- package/src/lib/export/download.ts +201 -0
- package/src/lib/export/png-metadata.ts +181 -0
- package/src/lib/history/ActionLogPanel.svelte +418 -0
- package/src/lib/history/action-log-panel-plugin.ts +24 -0
- package/src/lib/history/action-log.svelte.ts +172 -0
- package/src/lib/history/action-log.test.ts +168 -0
- package/src/lib/history/history-commands.ts +403 -0
- package/src/lib/history/macros.svelte.ts +320 -0
- package/src/lib/history/macros.test.ts +224 -0
- package/src/lib/history/replay-engine.test.ts +241 -0
- package/src/lib/history/replay-engine.ts +149 -0
- package/src/lib/history/spec-format.test.ts +250 -0
- package/src/lib/history/spec-format.ts +210 -0
- package/src/lib/iso/SeamCheckerPanel.svelte +251 -0
- package/src/lib/iso/iso-math.test.ts +77 -0
- package/src/lib/iso/iso-math.ts +77 -0
- package/src/lib/iso/seam-checker-panel-plugin.ts +25 -0
- package/src/lib/iso/seam-checker.test.ts +126 -0
- package/src/lib/iso/seam-checker.ts +93 -0
- package/src/lib/iso/tessellation.ts +67 -0
- package/src/lib/layers/compositor.test.ts +193 -0
- package/src/lib/layers/compositor.ts +175 -0
- package/src/lib/layers/layer-commands.test.ts +263 -0
- package/src/lib/layers/layer-commands.ts +429 -0
- package/src/lib/layers/layer-tree.svelte.ts +516 -0
- package/src/lib/layers/layer-tree.test.ts +383 -0
- package/src/lib/layers/layer-types.ts +56 -0
- package/src/lib/leveleditor/LevelEditorViewport.svelte +1808 -0
- package/src/lib/leveleditor/MapPropertiesPanel.svelte +266 -0
- package/src/lib/leveleditor/TilePickerPanel.svelte +324 -0
- package/src/lib/leveleditor/depth-sort.test.ts +70 -0
- package/src/lib/leveleditor/depth-sort.ts +39 -0
- package/src/lib/leveleditor/level-editor-commands.ts +353 -0
- package/src/lib/leveleditor/level-editor-viewport-plugin.ts +25 -0
- package/src/lib/leveleditor/map-properties-panel-plugin.ts +25 -0
- package/src/lib/leveleditor/map-state.svelte.ts +372 -0
- package/src/lib/leveleditor/map-state.test.ts +243 -0
- package/src/lib/leveleditor/tile-picker-panel-plugin.ts +25 -0
- package/src/lib/leveleditor/tile-source-registry.svelte.ts +91 -0
- package/src/lib/leveleditor/tiled-export.test.ts +144 -0
- package/src/lib/leveleditor/tiled-export.ts +374 -0
- package/src/lib/pywebview.d.ts +15 -0
- package/src/lib/recovery/.gitkeep +0 -0
- package/src/lib/recovery/idb-store.ts +118 -0
- package/src/lib/recovery/recovery-manager.test.ts +321 -0
- package/src/lib/recovery/recovery-manager.ts +115 -0
- package/src/lib/recovery/recovery-plugin.ts +55 -0
- package/src/lib/recovery/recovery-state.svelte.ts +21 -0
- package/src/lib/recovery/sw-plugin.ts +18 -0
- package/src/lib/recovery/sw-register.ts +17 -0
- package/src/lib/save/directory-format.ts +42 -0
- package/src/lib/save/project-snapshot.ts +139 -0
- package/src/lib/save/recent-projects.ts +56 -0
- package/src/lib/save/save-state.svelte.ts +35 -0
- package/src/lib/save/storage.ts +167 -0
- package/src/lib/save/zip-format.ts +45 -0
- package/src/lib/shortcuts/.gitkeep +0 -0
- package/src/lib/shortcuts/ShortcutEditorPanel.svelte +690 -0
- package/src/lib/shortcuts/default-bindings.ts +61 -0
- package/src/lib/shortcuts/shortcut-editor-panel-plugin.ts +25 -0
- package/src/lib/shortcuts/shortcut-init.ts +380 -0
- package/src/lib/shortcuts/shortcut-manager.test.ts +466 -0
- package/src/lib/shortcuts/shortcut-manager.ts +281 -0
- package/src/lib/shortcuts/shortcut-state.svelte.ts +78 -0
- package/src/lib/shortcuts/shortcuts-plugin.ts +17 -0
- package/src/lib/sync/patch-applicator.ts +300 -0
- package/src/lib/sync/patch-types.ts +65 -0
- package/src/lib/sync/project-manager.ts +108 -0
- package/src/lib/sync/sync-init.ts +152 -0
- package/src/lib/sync/sync-plugin.ts +19 -0
- package/src/lib/sync/sync-state.svelte.ts +56 -0
- package/src/lib/sync/ws-client.test.ts +604 -0
- package/src/lib/sync/ws-client.ts +574 -0
- package/src/lib/tools/.gitkeep +0 -0
- package/src/lib/ui/.gitkeep +0 -0
- package/src/lib/ui/AboutDialog.svelte +113 -0
- package/src/lib/ui/ColorPicker.svelte +761 -0
- package/src/lib/ui/ContextMenu.svelte +216 -0
- package/src/lib/ui/ExportDialog.svelte +747 -0
- package/src/lib/ui/FrameStrip.svelte +854 -0
- package/src/lib/ui/LayerPanel.svelte +810 -0
- package/src/lib/ui/MenuBar.svelte +590 -0
- package/src/lib/ui/NewProjectDialog.svelte +803 -0
- package/src/lib/ui/PluginManagerPanel.svelte +475 -0
- package/src/lib/ui/PromptDialog.svelte +252 -0
- package/src/lib/ui/RecoveryDialog.svelte +295 -0
- package/src/lib/ui/ResizeDialog.svelte +416 -0
- package/src/lib/ui/StatusBar.svelte +145 -0
- package/src/lib/ui/ToolbarPanel.svelte +488 -0
- package/src/lib/ui/animation-menu-commands.ts +194 -0
- package/src/lib/ui/command-palette/CommandPalette.svelte +232 -0
- package/src/lib/ui/command-palette/command-palette-plugin.ts +30 -0
- package/src/lib/ui/command-palette/command-palette-state.svelte.ts +190 -0
- package/src/lib/ui/command-palette/command-palette.test.ts +129 -0
- package/src/lib/ui/dialog-state.svelte.ts +70 -0
- package/src/lib/ui/edit-commands.ts +271 -0
- package/src/lib/ui/file-commands.ts +275 -0
- package/src/lib/ui/file-open.ts +99 -0
- package/src/lib/ui/help-commands.ts +93 -0
- package/src/lib/ui/image-commands.ts +181 -0
- package/src/lib/ui/layer-menu-commands.ts +420 -0
- package/src/lib/ui/menu-builder.ts +224 -0
- package/src/lib/ui/notifications/NotificationBanner.svelte +137 -0
- package/src/lib/ui/notifications/notification-plugin.ts +29 -0
- package/src/lib/ui/notifications/notification-state.svelte.ts +9 -0
- package/src/lib/ui/plugin-manager-panel-plugin.ts +26 -0
- package/src/lib/ui/plugin-state.svelte.ts +62 -0
- package/src/lib/ui/select-commands.ts +75 -0
- package/src/lib/ui/theme-plugin.ts +18 -0
- package/src/lib/ui/theme.svelte.ts +45 -0
- package/src/lib/ui/theme.test.ts +51 -0
- package/src/lib/ui/toolbar-config.ts +90 -0
- package/src/lib/ui/toolbar-plugin.ts +39 -0
- package/src/lib/ui/view-commands.ts +629 -0
- package/src/lib/variants/BisectionExportDialog.svelte +500 -0
- package/src/lib/variants/VariantPanel.svelte +822 -0
- package/src/lib/variants/bisection-export.test.ts +113 -0
- package/src/lib/variants/bisection-export.ts +148 -0
- package/src/lib/variants/palette-extraction.test.ts +111 -0
- package/src/lib/variants/palette-extraction.ts +84 -0
- package/src/lib/variants/palette-interpolation.test.ts +113 -0
- package/src/lib/variants/palette-interpolation.ts +87 -0
- package/src/lib/variants/palette-swap.test.ts +101 -0
- package/src/lib/variants/palette-swap.ts +114 -0
- package/src/lib/variants/variant-commands.ts +594 -0
- package/src/lib/variants/variant-panel-plugin.ts +27 -0
- package/src/lib/variants/variant-randomizer.ts +101 -0
- package/src/lib/variants/variant-state.svelte.ts +166 -0
- package/src/lib/variants/variant-state.test.ts +138 -0
- package/src/main.ts +14 -0
- package/src/vite-env.d.ts +3 -0
- package/svelte.config.js +2 -0
- package/todo/.done/audit-design-decisions.md +812 -0
- package/todo/.done/audit-implementation-plan.md +1235 -0
- package/todo/.done/happy-path-polish.md +177 -0
- package/todo/.done/pixelweaver-full-build.md +937 -0
- package/todo/.done/server-multi-frame-design.md +405 -0
- package/todo/.done/typed-dispatcher-design.md +435 -0
- package/todo/.done/unified-toolbar-and-action-system.md +323 -0
- package/todo/.obsolete/comprehensive-audit-obsolete-items.md +33 -0
- package/todo/.obsolete/tauri-desktop-bundle.md +424 -0
- package/todo/comprehensive-audit.md +1085 -0
- package/tsconfig.app.json +26 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +20 -0
- package/uv.lock +1167 -0
- package/vite.config.ts +32 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# Typed Dispatcher Design
|
|
2
|
+
|
|
3
|
+
Design exploration for tightening end-to-end typing of the command dispatcher
|
|
4
|
+
and cleaning up the loose `CommandContext.getActiveBuffer` surface.
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
The PixelWeaver command system uses a single dispatcher singleton. Plugins
|
|
9
|
+
register commands via `api.addCommand<P>(name, definition)`, and any code can
|
|
10
|
+
fire them via `api.dispatch({ type, plugin, version, params })`. A prior
|
|
11
|
+
refactor (I-03 in `todo/.done/audit-implementation-plan.md`) made
|
|
12
|
+
`Command<P>` and `CommandDefinition<P>` generic on the params type, but the
|
|
13
|
+
two ends of the pipe are still untyped.
|
|
14
|
+
|
|
15
|
+
Two pain points remain:
|
|
16
|
+
|
|
17
|
+
- **Untyped `dispatch(type, params)`**: `PluginAPI.dispatch` takes
|
|
18
|
+
`Omit<Command, 'id' | 'timestamp'>` where `Command.params` is
|
|
19
|
+
`Record<string, unknown>`. The dispatcher looks the definition up in the
|
|
20
|
+
registry at runtime, and since the registry stores `CommandDefinition<any>`
|
|
21
|
+
there is no type link between the `type` string and the shape of `params`.
|
|
22
|
+
As a result every command `execute()` body starts with defensive casts
|
|
23
|
+
like `const color = params["color"] as string;` and every `api.dispatch`
|
|
24
|
+
call site spells out a loosely-typed object literal. If the caller forgets
|
|
25
|
+
a field, the mistake surfaces at runtime, not at compile time.
|
|
26
|
+
|
|
27
|
+
- **Loose `CommandContext.getActiveBuffer`**: `CommandContext` is declared as
|
|
28
|
+
`{ getActiveBuffer?: () => PixelBuffer | null; [key: string]: unknown }`.
|
|
29
|
+
The method is optional and the index signature makes the whole object a
|
|
30
|
+
typed bag, which forced earlier cast patterns and still forces every
|
|
31
|
+
caller to write `ctx.getActiveBuffer?.()` followed by a null check.
|
|
32
|
+
`getActiveBuffer` is called from ~44 sites across 27 files and is
|
|
33
|
+
effectively non-optional at runtime (it is wired up during bootstrap by
|
|
34
|
+
`canvas-init-plugin.ts`), yet the type says otherwise.
|
|
35
|
+
|
|
36
|
+
The goal is to make both sides tight enough that:
|
|
37
|
+
|
|
38
|
+
- The `type` string in `dispatch()` constrains the shape of `params`.
|
|
39
|
+
- Command `execute()` bodies receive statically-typed `params` and
|
|
40
|
+
`context` without local casts.
|
|
41
|
+
- `ctx.getActiveBuffer()` (or an equivalent) is non-optional, non-nullable
|
|
42
|
+
in the common case, and does not require a cast.
|
|
43
|
+
|
|
44
|
+
## Approaches
|
|
45
|
+
|
|
46
|
+
### Approach A -- Global command-type-to-params map (module augmentation)
|
|
47
|
+
|
|
48
|
+
A single ambient interface `CommandParamsMap` maps command type strings to
|
|
49
|
+
their params interfaces. Plugins declare their entries via TypeScript module
|
|
50
|
+
augmentation. The registry, `dispatch()`, and `addCommand()` all derive
|
|
51
|
+
`P` from the `type` string via an index lookup.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
// In core/command-registry-types.ts
|
|
55
|
+
declare global {
|
|
56
|
+
interface CommandParamsMap {
|
|
57
|
+
// populated via module augmentation
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
type CommandType = keyof CommandParamsMap;
|
|
61
|
+
type ParamsOf<T extends CommandType> = CommandParamsMap[T];
|
|
62
|
+
|
|
63
|
+
// In a plugin file
|
|
64
|
+
interface FloodFillParams { x: number; y: number; color: string }
|
|
65
|
+
declare global {
|
|
66
|
+
interface CommandParamsMap {
|
|
67
|
+
flood_fill: FloodFillParams;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
api.addCommand('flood_fill', {
|
|
72
|
+
execute(params, ctx) {
|
|
73
|
+
const buffer = ctx.getBuffer(); // typed, non-optional
|
|
74
|
+
const { x, y, color } = params; // typed FloodFillParams
|
|
75
|
+
// ...
|
|
76
|
+
},
|
|
77
|
+
// ...
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
api.dispatch({
|
|
81
|
+
type: 'flood_fill',
|
|
82
|
+
plugin: 'builtin/fill',
|
|
83
|
+
version: '1.0.0',
|
|
84
|
+
params: { x: 4, y: 2, color: '#f00' }, // required keys enforced
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`PluginAPI` would be redefined so that `addCommand` and `dispatch` have
|
|
89
|
+
overloads keyed on `CommandType`:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
addCommand<T extends CommandType>(
|
|
93
|
+
name: T,
|
|
94
|
+
definition: CommandDefinition<ParamsOf<T>>,
|
|
95
|
+
): void;
|
|
96
|
+
|
|
97
|
+
dispatch<T extends CommandType>(
|
|
98
|
+
cmd: { type: T; plugin: string; version: string; params: ParamsOf<T> },
|
|
99
|
+
): void;
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`CommandContext` becomes a simple interface without an index signature.
|
|
103
|
+
`getActiveBuffer` is renamed to `getBuffer` and made non-optional,
|
|
104
|
+
returning `PixelBuffer` (no `| null`). A new `getBufferOrNull` can be
|
|
105
|
+
provided for the small number of call sites that legitimately want to
|
|
106
|
+
tolerate a missing buffer.
|
|
107
|
+
|
|
108
|
+
- **Pros**
|
|
109
|
+
- Single source of truth for command signatures; any code anywhere can
|
|
110
|
+
look up the params shape by type string.
|
|
111
|
+
- Callers get autocomplete on the `params` object from the `type` string.
|
|
112
|
+
- Works across plugin boundaries without explicit imports (important
|
|
113
|
+
because `ctx.api.dispatch` is called from tool handlers that do not
|
|
114
|
+
import the command that owns the type).
|
|
115
|
+
- Zero runtime cost -- all validation happens at the TypeScript layer.
|
|
116
|
+
|
|
117
|
+
- **Cons**
|
|
118
|
+
- Module augmentation is global and must be imported for the augmentation
|
|
119
|
+
to take effect. Forgetting the side-effect import on a plugin boundary
|
|
120
|
+
silently falls back to `never`/`unknown` for that type.
|
|
121
|
+
- Collision risk: two plugins cannot register the same command type
|
|
122
|
+
without TypeScript errors.
|
|
123
|
+
- `keyof CommandParamsMap` produces large union types that can slow down
|
|
124
|
+
IDE tooling if the command count grows (currently ~60 commands, which
|
|
125
|
+
is still comfortable).
|
|
126
|
+
- Requires rewriting every `execute`/`undo`/`describe` signature and
|
|
127
|
+
every `api.dispatch` call site. Heavy touch but mechanical.
|
|
128
|
+
|
|
129
|
+
- **Effort**: Medium-to-large. ~60 command definitions, ~25 dispatch call
|
|
130
|
+
sites, ~44 `getActiveBuffer` call sites, plus every test that mocks a
|
|
131
|
+
`CommandContext`. Each plugin file gains a params interface declaration.
|
|
132
|
+
|
|
133
|
+
### Approach B -- Locally-typed command tokens (phantom-typed handles)
|
|
134
|
+
|
|
135
|
+
Instead of a global map, `api.addCommand` returns a typed token that
|
|
136
|
+
encodes the params type in its phantom type parameter. Dispatch happens
|
|
137
|
+
through the token, not through a raw string.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// Token type carries the params shape as a phantom type parameter.
|
|
141
|
+
interface CommandToken<P> {
|
|
142
|
+
readonly type: string;
|
|
143
|
+
readonly plugin: string;
|
|
144
|
+
readonly version: string;
|
|
145
|
+
// phantom -- never instantiated
|
|
146
|
+
readonly __params?: (p: P) => void;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// addCommand returns a token
|
|
150
|
+
const floodFill = api.addCommand('flood_fill', {
|
|
151
|
+
execute(params: FloodFillParams, ctx) { /* ... */ },
|
|
152
|
+
undo(params, ctx, snap) { /* ... */ },
|
|
153
|
+
describe(params) { return `Flood fill at ${params.x},${params.y}`; },
|
|
154
|
+
});
|
|
155
|
+
// floodFill: CommandToken<FloodFillParams>
|
|
156
|
+
|
|
157
|
+
// Dispatch uses the token, not a raw string
|
|
158
|
+
api.dispatch(floodFill, { x: 4, y: 2, color: '#f00' });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`CommandContext` is cleaned up the same way as Approach A
|
|
162
|
+
(non-optional `getBuffer()`). Raw-string dispatch remains available as an
|
|
163
|
+
untyped escape hatch for dynamic cases (e.g. shortcut routing, action log
|
|
164
|
+
replay).
|
|
165
|
+
|
|
166
|
+
- **Pros**
|
|
167
|
+
- Type inference is local -- no global map, no augmentation, no
|
|
168
|
+
side-effect imports.
|
|
169
|
+
- Each plugin owns the types for its own commands and exports the tokens
|
|
170
|
+
it wants other plugins to dispatch.
|
|
171
|
+
- Natural fit for factory-style plugins that generate commands
|
|
172
|
+
dynamically at registration time.
|
|
173
|
+
- Preserves the ability to have two internally-scoped commands with the
|
|
174
|
+
same name in different plugins without ambient-type collisions.
|
|
175
|
+
|
|
176
|
+
- **Cons**
|
|
177
|
+
- Requires cross-plugin imports to dispatch from one plugin's code into
|
|
178
|
+
another's command (e.g. tool handlers that fire the commands exposed
|
|
179
|
+
by the drawing-primitives plugin). Today these are decoupled through
|
|
180
|
+
string dispatch; moving to tokens creates new dependencies.
|
|
181
|
+
- Action log replay, shortcut routing, and menu contributions all work on
|
|
182
|
+
raw strings, so a second untyped path must be kept alive -- you get
|
|
183
|
+
two parallel APIs.
|
|
184
|
+
- Renaming a command becomes awkward because the string identifier is
|
|
185
|
+
still the canonical form for serialization but the token is the
|
|
186
|
+
canonical form for dispatch. Two sources of truth.
|
|
187
|
+
- The phantom-type trick is unfamiliar to most TS devs; readability
|
|
188
|
+
suffers slightly.
|
|
189
|
+
|
|
190
|
+
- **Effort**: Large. Touches every call site that currently uses string
|
|
191
|
+
dispatch AND introduces new plugin-to-plugin imports, which means the
|
|
192
|
+
plugin dependency graph must be updated. Likely spawns follow-up
|
|
193
|
+
refactors to avoid circular plugin references.
|
|
194
|
+
|
|
195
|
+
### Approach C -- Discriminated union of command descriptors
|
|
196
|
+
|
|
197
|
+
Instead of a map, a single exported union type enumerates every command
|
|
198
|
+
descriptor. `addCommand` and `dispatch` use a generic that extracts
|
|
199
|
+
the matching member from the union.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// In a central types file, one entry per command
|
|
203
|
+
export type CommandDescriptor =
|
|
204
|
+
| { type: 'flood_fill'; params: { x: number; y: number; color: string } }
|
|
205
|
+
| { type: 'draw_rect'; params: { x: number; y: number; w: number; h: number; color: string } }
|
|
206
|
+
| { type: 'blur'; params: { radius: number } }
|
|
207
|
+
// ...
|
|
208
|
+
;
|
|
209
|
+
|
|
210
|
+
type ParamsFor<T extends CommandDescriptor['type']> =
|
|
211
|
+
Extract<CommandDescriptor, { type: T }>['params'];
|
|
212
|
+
|
|
213
|
+
api.addCommand('flood_fill', {
|
|
214
|
+
execute(params, ctx) {
|
|
215
|
+
// params inferred as { x: number; y: number; color: string }
|
|
216
|
+
const buffer = ctx.getBuffer();
|
|
217
|
+
// ...
|
|
218
|
+
},
|
|
219
|
+
// ...
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
api.dispatch({
|
|
223
|
+
type: 'flood_fill',
|
|
224
|
+
plugin: 'builtin/fill',
|
|
225
|
+
version: '1.0.0',
|
|
226
|
+
params: { x: 4, y: 2, color: '#f00' },
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`CommandContext` is tightened identically to Approach A.
|
|
231
|
+
|
|
232
|
+
- **Pros**
|
|
233
|
+
- All command signatures live in one file -- easy to review, easy to
|
|
234
|
+
grep, easy to detect naming collisions (TS errors immediately).
|
|
235
|
+
- Switch-exhaustiveness checks work on `cmd.type` throughout the app,
|
|
236
|
+
useful for action log replay and menu builders.
|
|
237
|
+
- No module augmentation gymnastics; works with a single explicit import.
|
|
238
|
+
- Discriminated unions are a mainstream TS idiom, familiar to all devs.
|
|
239
|
+
|
|
240
|
+
- **Cons**
|
|
241
|
+
- Central file becomes a bottleneck: every new command requires editing
|
|
242
|
+
a shared file that every plugin imports. This fights the plugin
|
|
243
|
+
architecture's intent that plugins own their own surface area.
|
|
244
|
+
- Scaling: extract over a large union is slower than an index lookup;
|
|
245
|
+
TS compilation time will grow faster than Approach A as command count
|
|
246
|
+
climbs.
|
|
247
|
+
- Third-party plugins cannot extend the union from outside the repo
|
|
248
|
+
without forking the union definition, which defeats the plugin model
|
|
249
|
+
the codebase otherwise leans into.
|
|
250
|
+
|
|
251
|
+
- **Effort**: Medium. Similar call-site churn to Approach A, plus one
|
|
252
|
+
mechanical pass to move params interfaces into the central union file.
|
|
253
|
+
|
|
254
|
+
### Comparison
|
|
255
|
+
|
|
256
|
+
| Dimension | A: global map | B: phantom tokens | C: central union |
|
|
257
|
+
|------------------------------------|----------------------------|-------------------------------|-----------------------------|
|
|
258
|
+
| Where types live | Alongside each plugin | Alongside each plugin | One central file |
|
|
259
|
+
| Dispatch key | String | Token object | String |
|
|
260
|
+
| Requires plugin cross-imports | No | Yes (for cross-plugin calls) | Just the union module |
|
|
261
|
+
| Extensible by third-party plugins | Yes (augmentation) | Yes (export tokens) | No (union is closed) |
|
|
262
|
+
| Autocomplete on `type` string | Yes | n/a (token is the key) | Yes |
|
|
263
|
+
| Autocomplete on `params` | Yes | Yes | Yes |
|
|
264
|
+
| Supports dynamic string dispatch | Yes | Parallel untyped path | Yes |
|
|
265
|
+
| Works with action log replay | Yes (string-keyed) | Needs string fallback | Yes (string-keyed) |
|
|
266
|
+
| TS perf at ~60 commands | Good | Great (local inference) | Good |
|
|
267
|
+
| TS perf at ~500 commands | Acceptable (index lookup) | Great | Degrades (Extract on union) |
|
|
268
|
+
| Familiarity | Intermediate | Advanced | Beginner |
|
|
269
|
+
| Scales with plugin ecosystem | Good | Fair | Poor |
|
|
270
|
+
| Effort | Medium-to-large | Large | Medium |
|
|
271
|
+
|
|
272
|
+
All three approaches tighten `CommandContext` identically: drop the index
|
|
273
|
+
signature, rename `getActiveBuffer` -> `getBuffer`, make it non-optional,
|
|
274
|
+
return `PixelBuffer` (throw or assert on missing buffer, which cannot
|
|
275
|
+
happen in practice after `canvas-init-plugin` has run). Provide a separate
|
|
276
|
+
`tryGetBuffer()` for the small number of call sites that want to tolerate
|
|
277
|
+
its absence (if any turn out to be real).
|
|
278
|
+
|
|
279
|
+
## Recommendation
|
|
280
|
+
|
|
281
|
+
**Approach A (global command-type-to-params map via module augmentation).**
|
|
282
|
+
|
|
283
|
+
Rationale:
|
|
284
|
+
|
|
285
|
+
- It is the only approach that matches the existing architecture where
|
|
286
|
+
plugins are discovered via `import.meta.glob` and communicate with each
|
|
287
|
+
other through string identifiers routed by the registry. String-keyed
|
|
288
|
+
dispatch is the codebase's status quo, and Approach A tightens the
|
|
289
|
+
types without changing that shape.
|
|
290
|
+
- Plugin cross-calls work without new imports. Today, for example,
|
|
291
|
+
`edit-commands.ts` fires `select_rect` via a string dispatch without
|
|
292
|
+
importing the selection plugin. Approach B would force that import and
|
|
293
|
+
create a dependency cycle; Approach A keeps the decoupling.
|
|
294
|
+
- Action log replay, shortcut routing, and menu contributions all
|
|
295
|
+
naturally stay string-keyed.
|
|
296
|
+
- Module augmentation has a known footgun (forgotten side-effect imports),
|
|
297
|
+
but this is mitigated by declaring all params interfaces in the same
|
|
298
|
+
file as `addCommand`, since registering the command and augmenting the
|
|
299
|
+
map live side by side. Existing lint rules can catch missing imports.
|
|
300
|
+
- Effort is on par with Approach C and substantially lower than Approach B.
|
|
301
|
+
|
|
302
|
+
The central union (Approach C) is second-best and would be acceptable if
|
|
303
|
+
we wanted a single grep-friendly catalog, but it scales poorly with
|
|
304
|
+
plugin count and fights the plugin model.
|
|
305
|
+
|
|
306
|
+
## Migration Strategy
|
|
307
|
+
|
|
308
|
+
Incremental rollout, build stays green at every step.
|
|
309
|
+
|
|
310
|
+
- **Step 1: Add `CommandParamsMap` infrastructure (non-breaking).**
|
|
311
|
+
- Create `src/lib/core/command-types.ts` with an empty
|
|
312
|
+
`interface CommandParamsMap {}` in the global namespace and the
|
|
313
|
+
`CommandType` / `ParamsOf<T>` helper types.
|
|
314
|
+
- Leave existing `addCommand<P>` and `dispatch` signatures in place.
|
|
315
|
+
- No behavior change; build stays green.
|
|
316
|
+
|
|
317
|
+
- **Step 2: Introduce typed overloads alongside the existing ones.**
|
|
318
|
+
- Add new overloads of `addCommand` and `dispatch` on `PluginAPI` that
|
|
319
|
+
key on `CommandType`. Keep the existing generic overloads as a fallback
|
|
320
|
+
for any command type not yet registered in the map.
|
|
321
|
+
- Update `PluginAPI.dispatch` to prefer the typed overload when the
|
|
322
|
+
`type` is known.
|
|
323
|
+
- No plugin changes required yet; build stays green.
|
|
324
|
+
|
|
325
|
+
- **Step 3: Tighten `CommandContext` in a single commit.**
|
|
326
|
+
- Add a new non-optional `getBuffer(): PixelBuffer` method to
|
|
327
|
+
`CommandContext`, throwing if the dispatcher context has not been
|
|
328
|
+
initialized (it always is, in practice, by `canvas-init-plugin`).
|
|
329
|
+
- Keep the old `getActiveBuffer?: () => PixelBuffer | null` method on
|
|
330
|
+
the interface temporarily so existing call sites continue to compile.
|
|
331
|
+
- Wire both methods in `canvas-init-plugin.ts`.
|
|
332
|
+
|
|
333
|
+
- **Step 4: Migrate plugins one at a time.**
|
|
334
|
+
- For each plugin file, define the params interfaces inline, augment
|
|
335
|
+
`CommandParamsMap`, rewrite `execute`/`undo`/`describe` to use typed
|
|
336
|
+
params, and swap `ctx.getActiveBuffer?.()` for `ctx.getBuffer()`.
|
|
337
|
+
- Drop the `as Type` casts inside the bodies as they become redundant.
|
|
338
|
+
- One commit per plugin. Order by risk: start with the smallest
|
|
339
|
+
(e.g. `fill-tool.ts`), end with `drawing-primitives-plugin.ts` and
|
|
340
|
+
`selection-tool.ts`.
|
|
341
|
+
- Each commit should keep the tree fully buildable, since untouched
|
|
342
|
+
plugins still use the old index-signature path.
|
|
343
|
+
|
|
344
|
+
- **Step 5: Migrate dispatch call sites.**
|
|
345
|
+
- Once all commands are in the map, sweep for `api.dispatch({ type: ...})`
|
|
346
|
+
and make sure each call site benefits from the typed overload. No
|
|
347
|
+
functional change; this is mostly a verification pass that reveals
|
|
348
|
+
missing/extra params fields as TS errors.
|
|
349
|
+
|
|
350
|
+
- **Step 6: Remove legacy surface.**
|
|
351
|
+
- Drop `getActiveBuffer` from `CommandContext`; remove the index
|
|
352
|
+
signature from `CommandContext`.
|
|
353
|
+
- Drop the fallback generic overload on `addCommand`/`dispatch`.
|
|
354
|
+
- Update tests to construct `CommandContext` mocks via a helper that
|
|
355
|
+
implements `getBuffer()` directly.
|
|
356
|
+
- Bump the audit doc to reflect the new baseline.
|
|
357
|
+
|
|
358
|
+
At every step the project compiles, tests pass, and no runtime behavior
|
|
359
|
+
changes. The only commit where TS errors would appear is Step 6, and only
|
|
360
|
+
if a call site was missed in Step 4 or 5.
|
|
361
|
+
|
|
362
|
+
## Files That Would Change
|
|
363
|
+
|
|
364
|
+
Core types and dispatcher:
|
|
365
|
+
|
|
366
|
+
- `src/lib/core/commands.ts` -- tighten `CommandContext`; drop the index
|
|
367
|
+
signature; add typed helpers.
|
|
368
|
+
- `src/lib/core/dispatcher.ts` -- update context storage type.
|
|
369
|
+
- `src/lib/core/plugin-api.ts` -- new typed overloads of `addCommand` and
|
|
370
|
+
`dispatch`; pass the typed context.
|
|
371
|
+
- `src/lib/core/plugin-types.ts` -- new `PluginAPI.addCommand`/`dispatch`
|
|
372
|
+
overloads keyed on `CommandType`.
|
|
373
|
+
- `src/lib/core/registries.svelte.ts` -- `commandRegistry` type updated
|
|
374
|
+
(still heterogeneous, but no longer needs an explicit `any`).
|
|
375
|
+
- `src/lib/core/command-types.ts` (new) -- declares `CommandParamsMap`,
|
|
376
|
+
`CommandType`, `ParamsOf<T>`.
|
|
377
|
+
|
|
378
|
+
Plugins (each gets a params interface and a `CommandParamsMap` augmentation):
|
|
379
|
+
|
|
380
|
+
- `plugins/builtin/drawing-primitives-plugin.ts`
|
|
381
|
+
- `plugins/builtin/fill-tool.ts`
|
|
382
|
+
- `plugins/builtin/advanced-fill-tool.ts`
|
|
383
|
+
- `plugins/builtin/selection-tool.ts`
|
|
384
|
+
- `plugins/builtin/noise-tool.ts`
|
|
385
|
+
- `plugins/builtin/dither-tool.ts`
|
|
386
|
+
- `plugins/builtin/gradient-tool.ts`
|
|
387
|
+
- `plugins/builtin/pattern-stamp-tool.ts`
|
|
388
|
+
- `plugins/builtin/circle-tool.ts`
|
|
389
|
+
- `plugins/builtin/diamond-tool.ts`
|
|
390
|
+
- `plugins/builtin/line-tool.ts`
|
|
391
|
+
- `plugins/builtin/rect-tool.ts`
|
|
392
|
+
- `plugins/builtin/make-stroke-tool.ts`
|
|
393
|
+
- `plugins/builtin/eyedropper-tool.ts`
|
|
394
|
+
- `plugins/builtin/effects/blur.ts`
|
|
395
|
+
- `plugins/builtin/effects/glow.ts`
|
|
396
|
+
- `plugins/builtin/effects/shadow.ts`
|
|
397
|
+
- `plugins/builtin/effects/outline.ts`
|
|
398
|
+
- `plugins/builtin/effects/sharpen.ts`
|
|
399
|
+
- `plugins/builtin/effects/scale.ts`
|
|
400
|
+
- `plugins/builtin/effects/rotate.ts`
|
|
401
|
+
- `plugins/builtin/effects/flip.ts`
|
|
402
|
+
- `plugins/builtin/effects/color-effects.ts`
|
|
403
|
+
- `plugins/builtin/drawing-utils.ts` -- helpers that read `ctx.getBuffer()`.
|
|
404
|
+
|
|
405
|
+
UI-level command plugins:
|
|
406
|
+
|
|
407
|
+
- `src/lib/ui/edit-commands.ts`
|
|
408
|
+
- `src/lib/ui/image-commands.ts`
|
|
409
|
+
- `src/lib/ui/file-commands.ts` (if present in the registration pass)
|
|
410
|
+
- `src/lib/history/history-commands.ts`
|
|
411
|
+
|
|
412
|
+
Canvas wiring:
|
|
413
|
+
|
|
414
|
+
- `src/lib/canvas/canvas-init-plugin.ts` -- provide `getBuffer()` in the
|
|
415
|
+
dispatcher context (plus a guarded error path instead of `| null`).
|
|
416
|
+
|
|
417
|
+
Tests:
|
|
418
|
+
|
|
419
|
+
- `plugins/builtin/tool-plugins.test.ts`
|
|
420
|
+
- `plugins/builtin/effects.test.ts`
|
|
421
|
+
- `plugins/builtin/gradient.test.ts`
|
|
422
|
+
- `plugins/builtin/noise-dither.test.ts`
|
|
423
|
+
- `plugins/builtin/selection.test.ts`
|
|
424
|
+
- Any other test that mocks `CommandContext` via `setContext({ getActiveBuffer: ... })`.
|
|
425
|
+
|
|
426
|
+
Categories of change:
|
|
427
|
+
|
|
428
|
+
| Category | Count (approx) | Change kind |
|
|
429
|
+
|----------------------------------|----------------|------------------------------------------------------|
|
|
430
|
+
| Core type files | 5 | Tighten types, add helpers |
|
|
431
|
+
| Plugin command files | ~24 | Add params interfaces + augmentation, drop casts |
|
|
432
|
+
| UI command files | ~4 | Same as plugin command files |
|
|
433
|
+
| Dispatch call sites | ~25 | Benefit from typed overload; fix any real mismatches |
|
|
434
|
+
| `getActiveBuffer` -> `getBuffer` | ~44 | Mechanical rename |
|
|
435
|
+
| Test mock files | ~5 | Update `CommandContext` stubs |
|