Skip to content

Make row decorations unselectable; de-slop residual machine-voice strings - #243

Merged
Ambisphaeric merged 2 commits into
mainfrom
feat/selection-slop
Jul 17, 2026
Merged

Ambisphaeric merged 2 commits into
mainfrom
feat/selection-slop

Conversation

@Ambisphaeric

Copy link
Copy Markdown
Owner

Closes #242

Why

Copying values out of the HUD is a core workflow. A native selection (double-click, drag, select-all) was capturing row decorations along with the value — e.g. a summary line yielding <value>.<why-line>. Copy must yield the fully realized value and nothing else.

A. Selection hygiene (headline)

The block renderer already isolates every decoration in its own classed span; the only user-select:none rule was the .hudtop drag handle. This adds user-select:none (+ -webkit- prefix) to every decoration class across styles.ts and panel-styles.ts (why lines, mark glyphs, kind/ext tags, micro-state dot, moment time/glyph, unanswered tag, block/section headers, live-transcript chrome, citations/role/status/attachment lines, glyph + clarify + session-control + notetaker-nav affordances). Value text stays selectable by inheriting the default (entity/moment/summary/todo/draft/transcript/field text, chat messages, transcript utterances). The separating space in relevant-now / pinned-doc titles moved inside the non-selectable .ext span so a selection has no trailing separator.

Regression test (selection-hygiene.test.ts): a vnode-level test that DERIVES the non-selectable classes from the actual stylesheet string (not a hardcoded list), walks a rendered relevant-now / todos / distillates row collecting the text a selection would keep, and asserts it equals the bare value. Includes explicit contract assertions on the relied-on classes and a by-construction negative probe (drop the .why suppression → the why line rejoins the selection).

B. Voice-slop strings (before → after)

  • distillates label: Transcript · distillate stream → Transcript; row why distilled from capture → from what was captured (banned "distillate/distilled" vocabulary)
  • fields label: Fields · fast → Fields (internal lane/tier name)
  • ask placeholder why: ask this context — recall path P3 → ask about what is here (roadmap phase)
  • custom placeholder why: sandboxed custom block — P6 → a self-contained custom block (roadmap phase)
  • transcript-inspector retention why: …ephemeral fast-path (#58); the durable stream is the distillate block → …ephemeral fast-path; the durable stream lives in the Transcript block (tracker ref + banned vocabulary)
  • chat catch-all: raw error.message under the input → calm line Couldn't answer — the engine returned an error. with the raw message on the hover title (same detail-on-inspection pattern as calmChatStatus)
  • chat screen-capture exception passthrough: raw error.message → screen capture did not respond
  • citations line: raw chunk ordinal #N for pageless sources → the source's human title (deduped); page anchors (p.3) unchanged
  • summaries degraded row: suppressed the copy affordance entirely (was a live Copy button carrying an empty-string payload)

C. Fully-realized copy value

EntityKind is closed (person | artifact | topic) — there is no link/url entity kind. A link surfaces as an artifact entity whose name is the model-extracted surface form (index/extract.ts trims it; no URL parsing/normalization), and Entity has no separate canonical-URI field (external.url exists but no current producer populates it). So row.entity.name already is the value the entity carries — no richer field to prefer; the existing relevant-now copy-payload test still pins it. Genuine URL documents carry the full canonical URI as pin.uri, and the pinned-doc block already copies pin.uri (full) with pin.title as the display form. Added a url-kind pinned-doc test pinning copy = the full canonical URL (scheme + host + path + query), negative-guarding the display title, decoration, and a bare-domain shortening.

Gates (Node 22)

pnpm -r build green; pnpm -r test green (contracts 114, fixtures 15, client 620, engine 1105); schema regen zero drift (gen then git diff clean under shared/contracts/schemas).

Deliberately not changed

  • The hint block's inline label prefix: .hk and the duplicate .copybar preview are suppressed, but the inline excerpt (a value) stays selectable; hint is on-match and rarely shown, and its primary copy path is its button. Left minimal to avoid scope creep.
  • Diagnostics-tier machine detail (stt slot endpoint/model lines, queue failure class/endpoint) kept — diagnostics may carry machine detail; only the tracker reference was removed.

…-voice strings

Copying values out of the HUD is a core workflow, but a native selection
(double-click / drag / select-all) captured row decorations along with the
value (why lines, mark glyphs, kind tags, affordance labels). Every decoration
span is now user-select:none so a selection yields the bare value only; value
text (entity/moment/summary/todo/draft/transcript/field text) stays selectable.
A vnode-level regression test derives the non-selectable classes from the actual
stylesheet and asserts a selection across representative rows extracts the bare
value, with a by-construction negative probe.

Also removes residual machine-voice from user-visible strings: banned end-user
vocabulary and an internal lane name in two block labels; roadmap-phase and
tracker references in placeholder/diagnostics copy; a raw chunk ordinal in the
citations line; a raw exception painted under the chat box (now a calm line with
the machine reason behind the hover title); and a live copy control on degraded
summary rows whose payload was an empty string.

Refs #242
…ocabulary

The prepared-drafts why-line rendered "from N distillates + M moments" —
"distillate" is banned end-user vocabulary (hud-voice §2). Reworded to the human
word "summary/summaries" ("from N summaries + M moments"), with an explicit
plural form since the source noun does not take a naive +s.

Refs #242
@Ambisphaeric
Ambisphaeric merged commit 8d9edde into main Jul 17, 2026
2 checks passed
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.

Native selection captures row decorations; residual machine-voice strings in HUD surfaces

1 participant