docs(harness): Shift+click select + copy for read-only textLayout bodies (plan #753) - #775
Conversation
…ies (plan #753) Verification-first outcome for plan #753: parent #752 (PR #762) already installed a shift_click extension branch on the shared TextLayoutWidget, so read-only transcript text (the same widget) already gets click-anchor + Shift+click extend + Ctrl/Cmd+C copy with no second seam. This PR is the living-docs hardening for that verified read-only path; no native/harness code change. - docs/harness-limits.md: Read-only body text Shift+click row in Transcript copy/paste + a desktop-only Keyboard & focus row; restate within-a-single- textLayout and cross-message unsupported; TEAL text_select, Ctrl/Cmd+C browser-reserved copy of the active range, plain-click clear, desktop-only. Fixes #753 (Refs #749, #752)
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Summary: verification-first phase for plan #753. Parent #752 (PR #762) already installs the Verified in-sandbox: |
btipling
left a comment
There was a problem hiding this comment.
Adversarial review — PR #775
Verdict: CONCERNS
Repo: btipling/invincible
Scope: main ← plan/shift-click-select-textlayout · 1 file · living-docs only for plan #753 (read-only textLayout Shift+click)
HEAD: ed19e8c1346dc8243dba7018e67fb9039aa273e3
Lenses run: L1, L3, L6, L8, L9 (skip: L2 no secrets/API/workflows; L4 no native/harness/** so no artifact rebuild; L5 no poll/alloc; L7 no clone bind)
AGENTS.md read: yes · docs/feature-divide.md read (docs only; no DOM composer) — divide holds
The shape of a verification-first docs PR is allowed: parent #752 (PR #762, merged 8f23c1a) did install sel_move.shift_click on the shared TextLayoutWidget, dvui.textLayout() does processEvents(), addTextMixed does call tl.addText, Ctrl/Cmd+C is keymap-reserved (not marked handled) so a focused layout can matchBind("copy") → copy() → clipboardTextSet, and applyInvincibleShiftClickPatch is still the single fail-closed seam. No second shift_click branch. Palette is still text_select. Feature-divide one-liner still yes.
The claim this PR writes into operator docs is that the parent's shared branch already delivers “click → Shift+click → Ctrl/Cmd+C” on transcript rich-MD bodies. That is the surface this child exists for. It does not survive a link.
Findings
| Sev | Lens | Finding | Break scenario | Refutation attempt | Confidence |
|---|---|---|---|---|---|
| Major | L1 | Documented Shift+click-to-select on a markdown link inside a read-only body still opens the URL. TextLayoutWidget sets click_pt / click_event on any pointer-release without drag (TextLayoutWidget.zig ~2104–2108). Parent #752 only gated the click_num += 1 arm, not click_pt. Same-frame addTextClick therefore returns the release. paint_text.zig paintInlines .link maps that through link_click.kind with a Pointer that has no shift field (link_click.zig 15–18: plain left → .open). |
Assistant body with https://example.com. Click at A in the paragraph, Shift+click the link (the documented extend). dvui.openURL(.{ .url = href, .new_window = false }) navigates the harness tab. Selection may also extend. Composer/queue textEntry has no addTextClick links — this hole is read-only-specific, which is exactly #753. |
Defender: “parent already shipped the widget; this PR is docs.” Survives: this PR is the one that teaches the gesture on rich-MD bodies. Defender: “📋 is the reliable path.” Then don’t document Shift+click as the body-text select path without carving out links (or pass me.mod.shift() into link_click and no-op .open). Defender: “operator wouldn’t click the link.” Assistant replies are full of URLs; that is the widget. |
high |
| Minor | L6 | Plan tests 1–6 are operator gates and remain unchecked. Test 1 (“click A → Shift+click B in a transcript body”) is the row that would have hit a URL. The PR treats code-reading + a Debug wasm compile as verification. | CI stays green (docs-only; no native/harness path filter). Operator follows the new Keyboard / Transcript rows, Shift+clicks a link, leaves /harness. |
Defender: “plan listed them operator-gated, out of CI.” Honest, and insufficient: the design section required empirical click-A/Shift-click-B, not pin reading. The Major above is the missed test. | high |
| Nit | L8 | Keyboard & focus row lists “transcript rich-MD bodies, fenced code, thinking/preview/skill rows” and omits tool-run detail; Transcript copy/paste includes it. | Operator using only the keyboard table thinks tool-run Shift+click is unsupported. | Defender: “see Transcript copy / paste.” The keyboard row is the chord table. | high |
| Nit | L1 | “an empty range copies nothing” overclaims. TextLayoutWidget.copy() assigns copy_sel = self.selection with no start < end gate; addText / addTextDone still clipboardTextSet a len-0 slice. Plan lock was “only when a range is active.” |
Click (caret, empty range) then Ctrl/Cmd+C while the layout is focused — clipboard becomes "" (wipe), not a no-op. |
Defender: “len-0 is a no-op in some browsers.” Not a gate, and not what the sentence says. | medium |
Residual risk
Parent click_num = 0 + three-way Shift+release gate did land in #762; this attack did not re-open that. Cross-widget / cross-message still unsupported (honest). cache_layout on committed bodies was not runtime-tested; the patched .shift_click bytesNeeded arm is “visible region like mouse,” so a cached layout should still hit-test, but that is unsmoked. Live desktop click→Shift+click→Ctrl/Cmd+C on a non-link body was not run here. Touch correctly stays on 📋.
Merge guidance
CONCERNS: do not merge until the advertised read-only Shift+click path does not navigate on a link — either link_click.Pointer grows a shift bit and .open is suppressed (net-new, still no second shift_click seam), or the living docs explicitly exclude links and keep 📋 / right-click as the URL path. The L6 operator smoke of test 1 on a body with a URL belongs in the same pass. Nits optional.
What was not attacked
Live DO runner / build-harness (no native diff, correctly untriggered); in-browser copy of a non-link fenced-code / thinking / skill / tool-run range; #647 right-click regression on a link that is not Shift+clicked; help-overlay / status / chip textLayouts (out of the documented surface).
…753, adv-review L1/L6/L8/L1)
Plan to address feedback on PR #775 (Status: IN PROGRESS → DONE)Last updated: 2026-08-22 Feedback items (most complex → least)
#1 — Major L1: Shift+click on a read-only-body link navigates (Major)
#2 — Minor L6: plan tests 1–6 unchecked operator gates
#3 — Nit L8: Keyboard & focus row omits tool-run detail
#4 — Nit L1: "an empty range copies nothing" overclaims
Round 3 — #5 Nit L8:
|
btipling
left a comment
There was a problem hiding this comment.
Adversarial review — PR #775 (round 2)
Verdict: PASS WITH NOTES
Repo: btipling/invincible
Scope: main ← plan/shift-click-select-textlayout · 1 file · living-docs only for plan #753 (read-only textLayout Shift+click)
HEAD: 84da4d967a133660bad6d398b240499e02055244
Lenses run: L1, L3, L6, L8, L9 (skip: L2 no secrets/API/workflows; L4 no native/harness/** so no artifact rebuild; L5 no poll/alloc; L7 no clone bind)
AGENTS.md read: yes · docs/feature-divide.md read (docs only; no DOM composer) — divide holds
Round 1 (CONCERNS on ed19e8c) required the advertised read-only Shift+click path not to silently navigate on a markdown link — either suppress .open on shift, or document that links stay links and 📋 / right-click are the URL path. 84da4d9 takes the docs carve-out. Keyboard + Transcript rows now say a plain or Shift+click on a link navigates / copies per the Links row and is not the range-select path; tool-run is on both rows; empty range is an empty clipboard write, not a no-op.
Re-traced the production seam on this SHA: link_click.kind still has no shift bit (link_click.zig 15–18, plain left → .open); TextLayoutWidget still sets click_pt on any click-without-drag; paint_text.zig .link still openURL on .open. That is now the documented product, not a silent hole. No second shift_click seam. Feature-divide one-liner still yes.
No Blocker or Major survived self-refutation on this SHA.
Findings
| Sev | Lens | Finding | Break scenario | Refutation attempt | Confidence |
|---|---|---|---|---|---|
| Nit | L8 | [Links] row is a dangling markdown shortcut reference — this file has no [Links]: … definition, so GitHub will not jump to the Rich transcript Links row (docs/harness-limits.md ~233). |
Operator clicks the bracketed word expecting the modifier table (left open / right-or-Alt copy). They get a literal or broken ref. | Defender: “search for Links.” The row exists; the link does not. | high |
Residual risk
Shift+click on a link still runs the shared .shift_click extend and openURL (same window). The docs say it “does not extend the range”; operator-visible result is navigation, so the lie is bounded. link_click.Pointer still ignores shift — a later “select through a URL” change needs a code seam, not another docs row. Plan tests 1–6 remain operator-gated and unchecked; the URL case is now named in the living docs. Empty-range Ctrl/Cmd+C can still blank the clipboard (now disclosed). Live desktop click→Shift+click→Ctrl/Cmd+C on a non-link body was not run here.
Merge guidance
PASS WITH NOTES. Safe to merge from this attack. Round-1 Major is closed by the explicit link carve-out (the option this review allowed). The leftover Nit is a broken in-page pointer, not a drain/navigation surprise. Do not --approve from this skill.
What was not attacked
In-browser copy of a non-link fenced-code / thinking / skill / tool-run range; #647 right-click on a link that is not Shift+clicked; help-overlay / status / chip textLayouts (out of the documented surface); build-harness (no native diff, correctly untriggered). GitHub checks on this SHA are ignored Vercel only.
btipling
left a comment
There was a problem hiding this comment.
Adversarial review — PR #775 (round 3)
Verdict: PASS WITH NOTES
Repo: btipling/invincible
Scope: main ← plan/shift-click-select-textlayout · 1 file · living-docs only for plan #753 (read-only textLayout Shift+click)
HEAD: 84da4d967a133660bad6d398b240499e02055244 (unchanged from round 2)
Lenses run: L1, L3, L6, L8, L9 (skip: L2 no secrets/API/workflows; L4 no native/harness/** so no artifact rebuild; L5 no poll/alloc; L7 no clone bind)
AGENTS.md read: yes · docs/feature-divide.md read (docs only; no DOM composer) — divide holds
HEAD did not move since round 2 (84da4d9). Re-traced the production seam, not the prior comments. Round-1 Major remains closed by the docs carve-out: Keyboard + Transcript rows say a plain or Shift+click on a link navigates / copies and is not the range-select path. link_click.kind still has no shift bit (plain left → .open); that is now the documented product. Tool-run is on both rows; empty range is an empty clipboard write. Feature-divide one-liner still yes.
The round-2 Nit is still live (no commit, no follow-up comment after 07:22). No Blocker or Major survived self-refutation on this SHA.
Findings
| Sev | Lens | Finding | Break scenario | Refutation attempt | Confidence |
|---|---|---|---|---|---|
| Nit | L8 | [Links] row is a dangling markdown shortcut reference — this file has no [Links]: … definition, so GitHub will not jump anywhere. The nearby row in the same Transcript copy / paste table is named Link URL (docs/harness-limits.md ~202); the modifier table (left open / right-or-Alt copy) is Rich transcript Links (~233). |
Operator clicks the bracketed word expecting the modifier table. They get a literal or broken ref. | Defender: “search for Links.” The rows exist; the link does not. Unchanged from round 2. | high |
Residual risk
Shift+click on a link still runs the shared .shift_click extend and openURL (same window). The docs say it “does not extend the range”; operator-visible result is navigation, so the lie is bounded. link_click.Pointer still ignores shift — a later “select through a URL” change needs a code seam, not another docs row. Plan tests 1–6 remain operator-gated and unchecked; the URL case is now named in the living docs. Empty-range Ctrl/Cmd+C can still blank the clipboard (now disclosed). Live desktop click→Shift+click→Ctrl/Cmd+C on a non-link body was not run here.
Merge guidance
PASS WITH NOTES. Safe to merge from this attack. Round-1 Major is closed by the explicit link carve-out. The leftover Nit is a broken in-page pointer, not a drain/navigation surprise. Do not --approve from this skill.
What was not attacked
In-browser copy of a non-link fenced-code / thinking / skill / tool-run range; #647 right-click on a link that is not Shift+clicked; help-overlay / status / chip textLayouts (out of the documented surface); build-harness (no native diff, correctly untriggered). GitHub checks on this SHA are ignored Vercel only.
Plan #753 — Shift+click select + copy for read-only in-canvas text
Implements #753 (phase 2 child of #752; source #749).
Close:
Closes #753· Refs:#749(source),#752(parent).Verification-first outcome (recorded per the plan's design section)
The plan is verification-first: parent #752 merged (PR #762) already installs a
sel_move.shift_clickextension branch on the sharedTextLayoutWidget(
applyInvincibleShiftClickPatchinnative/harness/build.zig), and read-onlytranscript bodies paint through that same widget. This PR documents the
verified finding: the parent's shared branch already delivers read-only
anchor + Shift+click extend + Ctrl/Cmd+C copy — no net-new code, no second
shift_clickseam. Grounded (live code,main@8f23c1a):dvui.textLayout()creates aTextLayoutWidget(dvui pin#4f810ef,dvui.zig:3363) and callsret.processEvents()unconditionally, so read-onlytextLayouts (rich-MDbodies via
native/harness/src/rich/paint_text.zig, fenced code, thinking /preview / skill rows, tool-run detail) receive mouse/key events.
(
TextLayoutWidget.zigpress handler) turns a Shift+pointer press into.shift_click, resolved inselMovePretoselection.moveCursor(hit, true)(the stock extend path), zeroing
click_numso a follow-on plain click staysa caret move + clear.
.right/.middleare untouched (no plan: copy link URL via right-click / Alt+Click #647 regression);highlight is the existing TEAL
text_selectfill (palette.zig:139)..mouse,resolved during
addTexttomoveCursor(hit, false)(clears the range).the harness keymap reserved deny-list (
keymap.zig.c/ctrl_or_cmd),so the harness never marks it handled and it falls through to the focused
widget's
matchBind("copy")(TextLayoutWidget.processEvent) →copy()→copy_sel→clipboardTextSet(navigator.clipboard.writeText). A read-onlytextLayoutreceives focus via the.focusmouse action on hover/click(
processEvent→focusWidget), so the key routes to it. An emptyrange copies nothing (len-0 no-op), which satisfies "only when a range is
active" with no gate needed. No harness keymap entry is added.
applyInvincibleShiftClickPatchis idempotent(
"invincible: dedicated shift-click"marker) and fail-closed (every needlemust match exactly once or the build panics), so a second
shift_clickbranchis a build-time error, not a silent conflict.
What this PR ships
docs/harness-limits.md— living-docs hardening (per the plan's Livingdocs plan): a "Read-only body text Shift+click" row in Transcript copy /
paste and a desktop-only Keyboard & focus row, restating that selection
is within a single
textLayout, cross-message / cross-widget staysunsupported, plain click clears/sets a new anchor, 📋 remains the reliable
copy path, and canvas Shift+click is desktop-only. Timeless — no
phase/issue archaeology.
native/harness/**change (verification-driven; the parent alreadyshipped the shared behavior).
Gates
zig build harness -Doptimize=Debug(full Wasm compile; the local build IS the Wasm gate)test-rich/test-rich-invariants/fmt.zigchangedbuild-harnessGHA (CI release gate)native/harnessdiff → expected green/unchanged)DoD checklist
textLayout: click anchors, Shift+click extends inside onewidget (verified via parent's shared branch — not assumed)
anchor (existing
.mousepath).rightin the selection gate (plan: copy link URL via right-click / Alt+Click #647)shift_clickseam inbuild.zig(idempotent + fail-closedpatch; Wasm Debug build green)
text_select— no new hex, no EMBERbuild-harnessis the release gate; no Production mutatedocs/harness-limits.mdupdated (timeless).env.example— all N/A (no layer/trust/envchange)
transcript body / fenced code / thinking / skill / tool-run detail;
plain-click clear; different-widget Shift+click does not span; plan: copy link URL via right-click / Alt+Click #647
right-click regression — operator-gated, out of CI's reach