(workspace-router) Single command router, launch handshake and empty-CLI fix#239
Merged
Conversation
…ansion Pure, filesystem-free decision (expanders injected) turning a parsed CLI intent into a single workspace command. The decision is made AFTER path expansion, so a path that matches nothing still yields an explicit command (open the step empty) instead of leaving the renderer to guess landing suppression from raw argument counts and strand in the default layout.
Typed-intent router with an intent buffer: intents dispatched before the workspace signals ready are queued and flushed in order on markReady (the "router not up yet" race). Hand-off intents (queue-files, open-culling, open-count, open-import, open-rename-nef, open-review-queue, load-image) share one morph + waitForListeners + emit implementation, so the cold-mount guard (the "target module not mounted yet" race) is written once and behaves identically for every hand-off. signalExternalLoad for the count hand-off is preserved via the HANDOFFS descriptor.
Consolidate the three "open" mechanisms and the CLI launch bridge into the single command router. The menu dispatch table, window.workspace, and the in-app moduleAPI open-* events are now thin adapters that build a typed intent and call dispatch; the router owns routing and the per-hand-off waitForListeners guards. Cold-start launch now uses a workspace-ready handshake instead of a timer: the renderer signals workspace-ready once its router and listeners are live, and the main process holds its resolved launch command until then, sent over one unified workspace-command IPC. This replaces the did-finish-load + 1000ms setTimeout timing lottery (removed). The renderer no longer guesses landing suppression from raw argument counts — it reads the post-expansion willLaunch boolean — and a CLI path that expands to nothing opens the target step empty (e.g. `ansikten culling /typo`) rather than stranding in the default layout. Guards removed and what replaces them: - did-finish-load + 1000ms setTimeout (x3: culling/import/queue): replaced by the deterministic workspace-ready handshake (main sends only after the renderer's listeners are live). - Renderer raw-arg landing guess (hasFiles/clear/verb): replaced by the main process's post-expansion willLaunch boolean. Guards kept verbatim (relocated into the router): the per-hand-off waitForListeners cold-mount guard (buffer does not cover lazy module mount), the review-dirty/keepDirty morph semantics, and signalExternalLoad for count.
… fix Strike the resolved CLI empty-expansion roadmap item; add CHANGELOG entries (Changed: router consolidation + workspace-ready handshake; Fixed: CLI path that expands to nothing opens the step empty instead of stranding). Add navigation rule 6 (one router opens everything; handshake not timer; launch decided post-expansion) to ux-principles, and note the CLI empty-path behaviour in the user workspace guide.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Pure (Electron-free, DI delivery) queue that holds workspace commands until the renderer completes the workspace-ready handshake. It is a FIFO queue, not a single slot, so an initial CLI launch and a second-instance launch that both arrive before ready deliver in order instead of the second clobbering the first. markNotReady() re-arms the hold (queue preserved) so a caller can stash commands across a renderer reload.
…loads Replace the single launchCommand slot + workspaceReady flag with the FIFO launch queue. Two robustness fixes: - Renderer reload (Cmd+R / crash) previously left workspaceReady stuck true, so a second-instance command mid-reload was sent into a router-less page and dropped. markNotReady() on webContents 'did-start-loading' re-arms the hold; the command queues and delivers on the next workspace-ready (the renderer re-signals per mount). - A second launch arriving before the first handshake overwrote the initial launch (single slot). The FIFO queue delivers both in order.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fifth PR in the navigation-overhaul series (after #235–#238).
workspaceCommands.js: a typeddispatch(intent)router with an intent buffer (queues before ready, flushes in order). The menu dispatch table,window.workspace, and the moduleAPIopen-*events are now thin adapters over one implementation; all hand-offs share a single morph + waitForListeners + emit path (count'ssignalExternalLoadpreserved).workspace-readywhen the router and listeners are live; main holds the launch command until then and sends one unifiedworkspace-commandIPC. The threedid-finish-load+ 1000 mssetTimeouthacks are gone.src/main/launch-command.jsdecides after path expansion — an empty glob/typo now opens the step view empty instead of stranding the user in the default layout; the renderer no longer guesses landing suppression from raw argv.waitForListeners(the buffer does not cover lazy module mounting), the review-dirty/keepDirty morph semantics.Testing
npm test: 86 files / 806 tests passed (new: router intent buffer 18 cases, launch resolver, updated adapters)npm run build:workspace: OKansikten culling /typo→ empty Gallra view) recommended in the owner's visual pass — not runnable headless