Skip to content

Explorer entries read "Open terminal here"; a window edges setting (#27) - #29

Merged
Maxaubert merged 2 commits into
mainfrom
feat/27-verbs-edges
Sep 20, 2026
Merged

Maxaubert merged 2 commits into
mainfrom
feat/27-verbs-edges

Conversation

@Maxaubert

@Maxaubert Maxaubert commented Sep 19, 2026 •

Copy link
Copy Markdown
Owner

Closes #27

App version 0.2.0 -> 0.3.0 (a feature, so a minor bump; merging publishes v0.3.0). Nothing under core/ is touched, so there is no core release and no Prism bump from this PR.

1. Explorer entries: "Open terminal here"

Owner: "for the Terminal app, have it say Open Terminal here and don't have any of them mention Prism, you can see that by the logo".

  • Both verbs (on a folder, and on a folder's empty space) are now labelled Open terminal here (VERB_LABEL in src/main/shellVerb.ts). They were "Open in Prism Terminal" and "Open Prism Terminal here".
  • Existing installs are relabelled. reconcile (src/main/verbSwitch.ts) used to leave a present verb alone, so an existing user would have kept the old text for ever. It now relabels, under the narrowest rule that does the job:
    • only when the build is the installed app (allowed: packaged and not --e2e, the existing guard, tests kept);
    • only with no off-marker on record. An entry the user turned off is never turned on, and in that case the registry is not even queried;
    • per key: the key's own command must point at THIS exe and its label must be readable and different. A missing key, a key pointing at another copy, or a label that cannot be read is left alone;
    • only the label value is written (reg add <key> /ve ...), not the icon or the command, and relabelVerb refuses any key that is not one of the app's two.
  • The label is parsed by matching REG_SZ, not the value's name, because reg.exe prints "(Default)" in the language of the Windows it runs on ("(Standard)" on a Norwegian one).
  • Read-only check on this machine: the shipped regex reads the two real keys as "Open in Prism Terminal" and "Open Prism Terminal here", so this install will be relabelled on the first launch of 0.3.0. Nothing was written to the registry while building this.
  • build/installer.nsh names no labels (it deletes keys), so it is unchanged. Settings hint, README, CLAUDE.md and a note in the design spec are updated. The 2026-09-18 plan document is left as the historical record it is.

2. Window edges

Owner: "add the option to specify the edges that you have in the Terminal app, like we have in the main app, where you can choose like Hairline, Faint, or like Solid edges, or even No edges".

  • Settings > Appearance > Edges (data-pref="window-edges"): None / Faint / Hairline / Solid (weakest to strongest, the order of Prism's own Edges row; see the review note below), built from the core's Pref + Segmented. It is this app's own row (in Prism the edges belong to the app style, which has its own Edges row), so it is added to the options e2e's closed list of this app's rows and its key is prism.window.edges, not prism.term.*.
  • Store: src/renderer/src/lib/edgesPrefs.ts (same shape as newTabPrefs). The numbers live in src/shared/windowEdges.ts, shared because main reads them too.
  • Applied once, where the tokens are derived. Every edge in the window reads --p-divider or --p-line (I grepped src/ and core/: the tab separators, the title bar's rule, the settings rail and rows, control outlines, menus, dialogs, the find bar, the dictation pill). chromeTokens takes the choice as a fourth argument and sets the alpha of those two tokens. No component knows the setting exists.
  • The default reproduces today's look exactly. Hairline is ink at 7% / 10% (dark / light) for --p-divider and 9% / 12% for --p-line, the values that were hard-coded. A unit test pins #ffffff12 / #ffffff17 on the default theme and that the full token table for 'hairline' equals the table with no argument; the e2e asserts the same on the running app with nothing stored.
  • Faint is 2.2% / 3.5% and Solid is 16% / 18%: Prism's faint and strong (lib/theme.ts). None is alpha 00, still a colour, so borders keep their width and nothing shifts.
  • DWM window border (src/main/windowEdge.ts): it was simple and safe, so it follows. The page tells main over a new window:edges IPC (validated in main; anything unknown is the default), edgeFor scales its step off the ground (hairline 0.13 / 0.16 as before, faint a third, solid a little over double), and None is DWMWA_COLOR_NONE, which a maximized window already gets.

Verification

  • npm run typecheck: clean. npm run lint: 0 errors, 8 warnings, the same 8 as on main (react-refresh, in files this PR does not add to).
  • npm test: 48 files, 612 tests, all passing (after the review commit). New: 6 label tests, 7 relabel tests against a fake registry behind execFile (shellVerbRelabel.test.ts), 5 reconcile tests in verbSwitch.test.ts, 6 edges tests in chromeTheme.test.ts, 4 in edgesPrefs.test.ts, 4 in windowEdge.test.ts. The label and chrome tests were written first and seen failing.
  • E2E (built app, this machine), all passing: spawn 7, theme 8, newTabFolder 6, restore 4, lastTab 7, options 10, edges 35 (new; 4 runs, 4 passes, after the one fix below), plus cwdLabel, indicator, handoff, closeAsk, links, dropAndMenu, exitClosesTab, promptLayout. The two dictation* scenarios were deliberately NOT run (another suite was running on this machine and they count each other's speech servers).
  • The new edges scenario measures real edges, not tokens: the border between two tabs, the rule under the title bar, the settings rail's edge and the rule under a settings row. For each option it WAITS until every edge has arrived at its token (the strip's border colour transitions over 550ms), then asserts none = alpha 0, faint < hairline < solid (measured 0 / 0.024 / 0.07 / 0.16 for the chrome line and 0 / 0.03 / 0.09 / 0.18 for the list line), white ink on dark, black ink at 18% after switching to a light theme, no layout movement across options, that main heard each choice, and that Solid survives a real quit and relaunch, measured before Settings is opened.
  • First run of edges had one failure, in the test and not the app: I had asserted a 1px border, and at this display's 225% scaling a CSS pixel computes to 0.888889px. The check now compares widths across options instead of assuming 1px.
  • Screenshots I opened: .e2e-shots/edges-hairline.png, edges-faint.png, edges-solid.png, edges-none.png, settings-general.png. Hairline looks like the page did before. Faint: the rules are barely there, control outlines almost gone. Solid: clearly stronger rules and outlines, nothing heavy. None: no rules at all; the dropdowns, the hex fields and the segmented controls still read because they keep their fill, and the selected theme card keeps its accent border. The Edges row sits at the foot of the Appearance list with one rule under it, no doubled line. On General, the Explorer row's hint reads "Open terminal here" on a folder. On Windows 11 it is under Show more options. on one line, not truncated.

Not verified, and why

  • The DWM border on a real window. The helper is off under --e2e by design, and I did not install or launch a non-e2e build (the installed app was not to be touched). The colour maths is unit-tested and the e2e proves main receives the choice. Hands-on: pick each option on a floating window and look at its outer border; None should show no border.
  • The relabel against the real registry. Proven against a fake registry only, by design. Hands-on after installing 0.3.0: launch once, then right-click a folder > Show more options; both entries should read "Open terminal here".
  • Installing the build as the last step (CLAUDE.md's rule) was skipped for the same reason.

Independent review (second agent, commit 48818cb)

  • Read the whole diff against origin/main and the CLAUDE.md passages it touches. No binaries or caches in the diff, no em-dashes, version and lock bumped, nothing under core/.
  • Changed: the Edges control offered Hairline, Faint, Solid, None, the order the words were said in. Prism's row is a scale (None, Faint, Hairline, Strong) and the ask was "like we have in the main app", so it now runs None, Faint, Hairline, Solid. Settings builds its options from WINDOW_EDGES (one list, not two), and a new src/shared/windowEdges.test.ts pins that list as weakest to strongest by every number it carries. E2E text and CLAUDE.md follow. Two small tidies: an over-long JSX line wrapped, and a comment in src/main/index.ts put back beside the constant it describes.
  • Checked and left alone: the relabel rule (off-marker first, per-key command and label, label-only write, own keys only, allowed gate; no test reaches the real registry, child_process is mocked whole); the REG_SZ parse, including an unset default value (reg.exe prints a translated "(value not set)", which reads as different and is rewritten on our own key, which is right); hairline numbers equal to the old hard-coded ones; the debounced DWM apply at launch (ground, then edges, last one wins); the e2e waits (every read is behind until/settled, the one sleep is the bound of a race against the process exit).
  • Re-run on this machine after the change: typecheck clean, lint 0 errors / the same 8 warnings, unit 48 files / 612 tests, e2e edges 35, options 10, theme 8, spawn 7, restore 4, cwdLabel 3, indicator 9, newTabFolder 6, handoff 3, lastTab 7, closeAsk 8, links 6, dropAndMenu 5, exitClosesTab 3, promptLayout 2, all passing. No dictation* scenario was run.
  • Screenshots opened: edges-faint.png, edges-solid.png, edges-none.png, settings-general.png. The row reads None / Faint / Hairline / Solid with the pressed step filled; Solid's rules and control outlines are clearly stronger without being heavy; None has no rules at all and the controls still read by their fill; the Explorer hint fits on one line.
  • Note for hands-on: an upgrade through the installer removes the verb keys (the old uninstaller runs), so on a normal upgrade the entries come back through the ordinary repair with the new label, and the relabel path is the one for keys that survived.

For the owner

  1. "Solid" is a stronger line, not an opaque one. I took the word as your name for Prism's strong step and used its numbers (16% / 18% ink). If you meant a fully opaque rule, that is one line in src/shared/windowEdges.ts.
  2. Settings rows follow the choice here; in Prism they do not. Prism keeps --p-line (list rows) at a fixed hairline whatever the style's edges say. You asked for every edge, so here None also removes the rules between settings rows. The screenshot looks fine to me, but it is a difference from Prism worth a glance.
  3. CLAUDE.md's Explorer-verbs line said the default was "APPLIED ONCE (marker file)". The code has used an off-marker and a repair-at-launch for a while, so I corrected that sentence while I was adding the relabel rule to it.

🤖 Generated with Claude Code

Maxaubert and others added 2 commits September 19, 2026 23:30
…es setting (#27)

Explorer entries (owner, 2026-09-19: "have it say Open Terminal here and
don't have any of them mention Prism, you can see that by the logo"): both
verbs are labelled "Open terminal here". An install that already has them is
relabelled by reconcile at launch, under the narrowest rule that does it: no
"no" on record, the key present and pointing at this exe, its label readable
and different, and only the label value is written. Never under --e2e or
unpackaged, never an entry the user turned off.

Window edges (owner: "Hairline, Faint, or like Solid edges, or even No
edges"): Settings > Appearance > Edges, stored as prism.window.edges. Applied
where chromeTokens derives --p-divider and --p-line, so every edge in the
window follows it, the core's components included, with no change to core/.
Hairline is the default and is exactly the numbers hard-coded before. The DWM
border round the window follows too; none removes it.

Version 0.2.0 -> 0.3.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s does (#27)

Review of #29. The row offered Hairline, Faint, Solid, None: the order the
owner happened to say the words in. He asked for the option "like we have in
the main app", and Prism's Edges row is a scale (None, Faint, Hairline,
Strong); a segmented control with its steps out of order does not read as one.

Settings now builds its options from WINDOW_EDGES, so there is one list, and a
new unit test pins that list as weakest to strongest by every number it
carries (both line tokens, both grounds, and the DWM border step). The e2e's
expected row text and the CLAUDE.md passage follow. Also: an over-long JSX
line wrapped, and in main the comment about the DWM helper sits beside the
constant it describes again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Maxaubert
Maxaubert merged commit e4e2bcb into main Sep 20, 2026
2 checks passed
@Maxaubert
Maxaubert deleted the feat/27-verbs-edges branch September 20, 2026 11:22
Maxaubert added a commit that referenced this pull request Sep 25, 2026
…2e harness (#71) (#72)

Settings: the colour editor saves the whole setup into Custom and is a theme
pick (#8, #29); ThemeSwitchAsk registers once (#22); a hex field commits only
a changed draft (#26); the dictation key is never a key that types or a chord
the terminal owns, and a press elsewhere ends the capture (#27); the editor
takes the focus, traps Tab and hears Escape, the pencil is its own button
(#28); a finished download reads fresh state before picking the model (#30).

Release and CI: release.yml tags the built commit (#11); core-release runs
from main only (#34), waits for terminal-gate by name and its success (#38),
and opens an issue when a core change cannot be released; core-version also
requires the core version above the base's (#39).

Harness: a time limit per scenario and closeApp (#35), profiles removed after
each scenario (#36), the poll's first verdict awaited instead of 6 s (#37).

Core 0.15.3, app 0.18.3. New reviewSettings e2e and unit tests.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Sep 25, 2026
…2e harness (#71) (#72)

Settings: the colour editor saves the whole setup into Custom and is a theme
pick (#8, #29); ThemeSwitchAsk registers once (#22); a hex field commits only
a changed draft (#26); the dictation key is never a key that types or a chord
the terminal owns, and a press elsewhere ends the capture (#27); the editor
takes the focus, traps Tab and hears Escape, the pencil is its own button
(#28); a finished download reads fresh state before picking the model (#30).

Release and CI: release.yml tags the built commit (#11); core-release runs
from main only (#34), waits for terminal-gate by name and its success (#38),
and opens an issue when a core change cannot be released; core-version also
requires the core version above the base's (#39).

Harness: a time limit per scenario and closeApp (#35), profiles removed after
each scenario (#36), the poll's first verdict awaited instead of 6 s (#37).

Core 0.15.3, app 0.18.3. New reviewSettings e2e and unit tests.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

Explorer entries say what they do, not the app's name; a window edges setting

1 participant