fix(annotate): QA follow-ups for the folder, All files, and HTML surfaces (#1537)
* fix(annotate): honor and persist the HTML tools toggle in folder sessions A folder annotate session suppressed the whole HTML chrome restore, so the eye could never remember anything there: every folder session opened with the floating tools hidden no matter how often the reviewer showed them, and the toggle wrote nothing back (the save effect is gated on the restore having run). Only the sidebar/panel halves are genuinely not a folder session's to remember — its file browser owns the left sidebar for the whole session. `toolsHidden` describes the HTML surface itself and means the same thing everywhere, so it now restores and persists there too, with the other two halves kept as the last ordinary HTML session left them (`mergeHtmlChromeState`). * fix(ui): keep 44px touch targets on the cross-file panel controls The This file / All files buttons, the document group headers, "Show in files" and "View all …" carry no data-pn-touch-target, so inside the compact touch shell they render at desktop density — the affordance they replaced (the legacy "+N in M other files" button) had the marker. The attribute only grows the box within the compact scope, so desktop density is unchanged. * fix(plan): keep the plan's own comments in the All files view The panel's cross-file groups are keyed by document path, and a plan-review session's document is the plan itself, which has no path (`sourceFilePath` is annotate-only). The open document therefore contributed no group at all: switching to All files listed every linked document and silently dropped the reviewer's comments on the plan in front of them, from the list and from the header count. The open document is now always contributed, under a synthetic key when it has no path of its own, with an explicit "(this plan)" / "(this document)" label. It is still the open document, so its group is `isCurrent` and the panel routes select/edit/delete to the live host state rather than to the cross-document store. The memo body moved into a pure `buildAnnotationDocumentGroups` so the rule is testable on its own. * fix(ui): compare cross-file annotation paths normalized, and act on a refused write The panel addresses documents by the normalized path its groups carry (forward slashes, collapsed separators) while the linked-doc cache is keyed by the raw path the server sent. On Windows those differ, so the lookup in `updateStoredAnnotations` missed every time and a cross-file Edit or Delete was a silent no-op — the card vanished from the view but the comment still shipped in the export. `useAnnotationJump` compared the same two spellings, so a jump inside the open document navigated instead of selecting, and the commit for a destination never matched the pending request. Both sides now normalize before comparing. App also acts on the `false` `updateStoredAnnotations` returns instead of discarding it: the open document falls back to the live mutators, and anything else raises a toast rather than appearing to work. * fix(plan): do not announce the terminal tools in a session with no server The gate skipped read-only shared plans, but the share portal's own root — and any demo session that never reaches /api/plan — is not a "shared session", so the announcement (and its video fetch to plannotator.ai) fired on a public page with no author to address. `!isApiMode` now joins the read-only term; the cookie is still deferred, not consumed, and isApiMode is settled by the time isLoading clears, so a real session can never be deferred by it. * ci: run the DOM-gated tests that drifted off the allowlist, and guard it A DOM-gated test file runs nowhere but the hand-maintained list in test.yml, and three PRs in this release added seven files (34 tests) that guard controls which had just shipped — none of them ran. Another 34 older files had drifted off the same way. All of them are added here, and a guard test asserts that every DOM-gated test file in the repo is named in one of the workflow's DOM_TESTS steps, so the list cannot silently drift again. The guard needs no DOM and runs in the default sweep as well as its own step. * fix(ui): scrub query and fragment from relative URLs in element context The captured element context documents its href/src values as "scrubbed of query and fragment", but only absolute http(s) URLs were: a relative `./checkout?session=…#access_token=…` was copied through whole into drafts, submission records and exported feedback. Relative URLs carry the same per-visit state absolute ones do, and the implicit-flow convention puts tokens in the fragment specifically. The path still survives in every form; data: truncation and the javascript: drop are unchanged. * fix(ui): restore byte-identical export for multi-target comments with no context The element-context work claimed to be additive, but the extra-target locator suffix was keyed off `anchor.selector`, which every multi-target annotation has always carried — so an annotation captured before element context existed (or restored from an older draft) silently changed export shape. The locator is a property of the captured context, and is now emitted only when the target carries one. * docs(marketing): HTML tools start hidden; document the eye and pen chords annotate.md still described the eye as the way to hide controls that were on screen by default, and the pen as one-way. Both surfaces now open with the tools hidden, the eye (Cmd/Ctrl+Shift+X) shows them and remembers the choice, and the pen (Cmd/Ctrl+Shift+A) toggles annotate mode in both directions.
M
Michael Ramos committed
4fd3b42f28ced9575c0d13bb15c94f9dc67fb385
Parent: 02ce55f
Committed by GitHub <noreply@github.com>
on 9/15/2026, 10:29:50 AM