Skip to content

(workspace-router) Single command router, launch handshake and empty-CLI fix#239

Merged
krissen merged 6 commits into
devfrom
feature/workspace-commands
Jul 17, 2026
Merged

(workspace-router) Single command router, launch handshake and empty-CLI fix#239
krissen merged 6 commits into
devfrom
feature/workspace-commands

Conversation

@krissen

@krissen krissen commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

Fifth PR in the navigation-overhaul series (after #235#238).

  • New workspaceCommands.js: a typed dispatch(intent) router with an intent buffer (queues before ready, flushes in order). The menu dispatch table, window.workspace, and the moduleAPI open-* events are now thin adapters over one implementation; all hand-offs share a single morph + waitForListeners + emit path (count's signalExternalLoad preserved).
  • Launch handshake: the renderer sends workspace-ready when the router and listeners are live; main holds the launch command until then and sends one unified workspace-command IPC. The three did-finish-load + 1000 ms setTimeout hacks are gone.
  • CLI empty-expansion bug fixed (ROADMAP known issue): src/main/launch-command.js decides 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.
  • Deliberately kept verbatim: per-hand-off 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: OK
  • Manual cold-start CLI verification (ansikten culling /typo → empty Gallra view) recommended in the owner's visual pass — not runnable headless

krissen added 4 commits July 17, 2026 21:32
…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.
@krissen krissen added the enhancement New feature or request label Jul 17, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

krissen added 2 commits July 17, 2026 21:47
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.
@krissen
krissen merged commit 2b76c7d into dev Jul 17, 2026
2 checks passed
@krissen
krissen deleted the feature/workspace-commands branch July 17, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant