Skip to content

Correct the terminal, notepad, and clipboard specs; fix a right-click ending a mouse override - #710

Draft
nedtwigg wants to merge 3 commits into
specs-layout-auditfrom
specs-terminal-audit
Draft

nedtwigg wants to merge 3 commits into
specs-layout-auditfrom
specs-terminal-audit

Conversation

@nedtwigg

@nedtwigg nedtwigg commented Sep 20, 2026

Copy link
Copy Markdown
Member

Spec audit, group 2 (terminal-state / terminal-context / terminal-escapes / mouse-and-clipboard / notepad). Stacked on #708 (the spec-audit PRs merge in order #708#715); independent of the alert series.

Commit 1 — docs and comments. Twenty-four inaccuracies corrected against the code (stale helper-status strings, an OSC 8 rule whose implementing module was not named, a dragDropEnabled claim that predates pointer-based pane drag — in the spec and two code comments and a third copy in standalone.md — wrong Source of truth: pointers for the notepad quit gate, the WSL -d gate, bash argv replacement, the 260 ms Cancel flash, IS_MAC's real reach, six rules carrying both a why-clause and a (rationale) marker, and more). Condensed: the helper lifecycle table → one rule + pointer, keystroke-fallback mechanism → the store's comments, per-shell integration mechanics → the scripts, duplicate statements across mouse/notepad/terminal-context.

Commit 2 — code.

  • Bug: under a temporary mouse override, a right-click started a pendingDrag and its release read as the click that ends the override, while contextmenu stayed swallowed — the user got nothing. Non-primary buttons no longer start a pending drag; test added, spec §2 now says "primary click".
  • Deleted write-only TerminalPaneState.title, derived VolatileSurfaceNotes.terminalId, dead shellName options, the dragBlock module latch (folded into Selection), two unreachable guards (proved by test), and a double control-strip on every output chunk.
  • Mirrored-constants tests now pin DEFAULT_HELPER_COMMAND and the helper-command validator against the sidecar.

Budgets: mouse 3800→3750, notepad 4000→3850, terminal-escapes 3850→3800, standalone 10700→10650.

Deferred (reported, not done): the second outside-release finalizer, one shared CWD-refresh helper, moving bracketedPaste off the selection store, headerPrimary returning the winning title, the double beginClosing.

🤖 Generated with Claude Code

nedtwigg and others added 2 commits September 20, 2026 00:16
An audit of terminal-state, terminal-context, terminal-escapes,
mouse-and-clipboard, and notepad found rules that no longer described the
code, pointers that named the wrong symbol or test, and mechanism restated
in a spec that the code already carries at the line it constrains.

Corrections: the helper status table listed strings the view no longer
renders, so it is now one rule pointing at HELPER_STATUS; OSC 8 names the
confirmation host and its test; the drag-drop flag no longer claims to keep
HTML5 drag-and-drop alive, since pane dragging is pointer-based; the
standalone quit gate, source-pin teardown, Door popover height, notepad
scope, CwdState shape, banner Cancel flash, IS_MAC reach, clipboard writer,
prompt last-line cap, WSL and bash injection shapes, and the XTSMGRAPHICS
report form all now say what the code does. The `.vsix` dotfile line is a
note, not an imperative, because nothing asserts it.

Condensations: per-shell integration mechanism, prompt-shape enumeration,
header-icon placement, and six why-clauses that were already in a rationale
file move to their owning script, code comment, or spec. Budgets ratchet
down for mouse-and-clipboard, notepad, and terminal-escapes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… from ending a mouse override

Six pieces of state or work carried a second copy of something already known,
and one of them was a bug.

- `TerminalPaneState.title` duplicated the newest `titleCandidates` entry and
  was never read outside its own dedupe. The candidate map is now the only
  store, so a transfer carries one title channel rather than two.
- The VS Code notepad mirror carried a `terminalId` beside every terminal
  Surface, always equal to the Surface id. A teardown now filters on the
  Surface kind and asks `ptyManager.getCwd` with the Surface id.
- `deriveFallbackCommandTitle` took a `shellName` no caller passed, as did
  `HeaderOptions`, and `terminal-registry` re-exported the function for nobody.
- The mouse router latched block-drag shape in a module variable that
  `pendingDrag.block` and the selection already held; it rides the selection
  record now.
- `onData` stripped mouse reports twice per chunk and the returned-prompt
  heuristic ran the stateful control strip twice over the same text; each
  strips once and both readers share the result.
- `navigator.userAgent` sat behind `navigator.platform`, which every browser
  defines, so it could never be reached.

The bug: a right-click during a temporary mouse override left a pendingDrag
whose release read as the paired click that ends the override — so the
override went away and, the context menu being swallowed, the user got nothing
for it. Only the primary button starts a drag now.

`mirrored-constants.test.ts` gains the sidecar's helper autorun default and
command validator, neither of which the CJS sidecar can import; the keystroke
fallback's one-command-at-a-time guard gains the test that shows it is
load-bearing, and loses the two arms that test showed unreachable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 20, 2026

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1cb2bf2
Status: ✅  Deploy successful!
Preview URL: https://ee0151f7.mouseterm.pages.dev
Branch Preview URL: https://specs-terminal-audit.mouseterm.pages.dev

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feedback on work in progress, not a merge verdict — mark the PR ready for review when you want the full pass.

Two spec-accuracy points in docs/specs/notepad.md, both as inline suggestions.

The scope claim. notepad-store.ts is a per-webview module instance, and a VS Code window can hold several Dormouse webviews at once — the sidebar WebviewView plus any editor panels, each with its own attachRouter call in extension.ts. "Per window" therefore undercounts in exactly the host the "VS Code lifecycle" section below it is about; the sentence's own explanation already says "in the webview". The same wording went into NotepadPanel.test.tsx's doc comment, so there's a third suggestion for that line.

The window-close.test.ts citation. That test sets mocks.notepadSurfaceIds.mockReturnValue(["pane-a"]), so the "even after their last note is deleted" half of the rule is stubbed out — what it pins is that the discard path iterates the id set at all. quit-notepad.test.ts pins the archiving half for real: it deletes the last note and asserts the landed batch is still removed on the next attempt.

Comment thread docs/specs/notepad.md

- **The attached notepad is a panel in the top-right of the Surface body, three quarters of it wide and tall.** It closes on its close control, Escape, or an outside click.
- **Only one Surface notepad is open per Wall.** The store holds a single open id, and opening a Door's popover closes the attached panel.
- **Only one Surface notepad is open per window.** The store holds a single open id across every Wall in the webview, and opening a Door's popover closes the attached panel.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Only one Surface notepad is open per window.** The store holds a single open id across every Wall in the webview, and opening a Door's popover closes the attached panel.
- **Only one Surface notepad is open per webview.** The store holds a single open id across every Wall in it, and opening a Door's popover closes the attached panel.

Comment thread docs/specs/notepad.md
- **A failure or timeout leaves the quit pending in Rust**, whose phase-2 wait is unbounded for exactly this (`docs/specs/standalone.md` → "Quit flow"), and the dialog shows the error with **Cancel** (default) and **Quit anyway**, which discards the notes. **Only Cancel calls `quit_cancel`**: Quit anyway must reach teardown with the watchdog still armed.
- **A timeout aborts the archive it stopped waiting for** ([Closure](#closure)).
- **Must include Surfaces with pending batch IDs even after their last note is deleted**, both when archiving and discarding on Quit anyway; pinned by `standalone/src/quit-notepad.test.ts`.
- **Must include Surfaces with pending batch IDs even after their last note is deleted**, both when archiving (`standalone/src/quit-notepad.test.ts`) and when discarding on Quit anyway (`standalone/src/window-close.test.ts`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Must include Surfaces with pending batch IDs even after their last note is deleted**, both when archiving (`standalone/src/quit-notepad.test.ts`) and when discarding on Quit anyway (`standalone/src/window-close.test.ts`).
- **Must include Surfaces with pending batch IDs even after their last note is deleted**, both when archiving and when discarding on Quit anyway; pinned by `standalone/src/quit-notepad.test.ts`.

}

/** Both panels a Wall would mount, so "one notepad per Wall" is observable. */
/** Both panels a Wall would mount, so "one notepad open per window" is observable. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Both panels a Wall would mount, so "one notepad open per window" is observable. */
/** Both panels a Wall would mount, so "one notepad open per webview" is observable. */

@nedtwigg
nedtwigg changed the base branch from main to specs-layout-audit September 20, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants