Commit Graph

3 Commits

Author SHA1 Message Date
xarmian a0c7d68aa9 build(web): SvelteKit 3 + adapter-static 4 (TASK-3423 PR B) (#1835)
* wip(web): SvelteKit 3.0.1 + adapter-static 4 with the $lib alias (TASK-3423 PR B, WIP)

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

* wip(web): kit 3 migration fixes - goto reset, page.url.href, $app/env, $app/state, cookie v2 (TASK-3423 PR B)

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

* fix(web): pane Back restores scroll through kit 3's snapshot() (TASK-3423 PR B)

PaneHost read page.state one task after popstate; kit 3 applies a popped
entry after an await, so the saved paneScrollTop was never seen. Kit's own
snapshot() keeps the position per history entry, captures it when the entry
is left, drops it on a replace, and restores only on a traversal after the
entry is applied. The controller's replaceState(paneScrollTop) write, the
getPaneScrollTop dep and readPaneScrollTop are gone. The 9 bug-2182 legs pass.

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

* test(e2e): the back-settle latch opens at the Back's popstate, where kit 3 arms it (TASK-3423 PR B)

Kit 3's popstate handler is async, so afterNavigate (where the settle is
armed) now runs after every popstate listener; measured 2-30ms after the
helper's listener. Not yet run green: the box is held.

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

* fix(web): the pane back-settle waits for an in-flight drill instead of minting the popped-to item (TASK-3423 PR B)

Kit 3 resolves a goto to afterNavigate across tasks, so a drill fired inside
the 140ms window could still be in flight when the settle fired; it minted
the popped-to item first (measured: URL still ?item=A at fire time, 2 of 4
runs). The settle now re-arms while navigating.current is set. Unit tests
cover the defer and the cancelled-navigation fallback; both die without
the defer. e2e not yet re-run on this commit.

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

* fix(web): defer the back-settle on navigating.type, not a nonexistent navigating.current (TASK-3423 PR B)

79175a8bc read navigating.current, which kit 3's $app/state navigating does
not have: undefined !== null held always, so the settle deferred forever.
The R14 drill legs passed for that wrong reason and 432 (a drill AFTER the
window still sees A minted) failed 5/5. navigating.type is null exactly
when no navigation is in flight. Measured at this commit: pane-async-race
373 and 432 and capstone 645, 5 repeats each, 15/15 pass.

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

* fix(web): the list's restore-skip is released by the next navigation, not a microtask (TASK-3423 PR B)

Closing the pane from a scrolled column jumped the list (bug-3165 e2e):
the handoff wrote the anchored position at 52ms, then the scroll restore
applied the list entry's saved offset (top 600) from 82ms on (measured with
a scroll-write probe after Escape). Kit 3 calls snapshot.restore after an
await in its navigate, so the queueMicrotask release ran before the
restore it was meant to skip. The skip now belongs to the navigation that
armed it: its own restore consumes it and the next beforeNavigate releases
any remainder. bug-3165 spec: 6/6 desktop legs pass.

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

* fix(web): editor menus unsubscribe from the editor they subscribed to, not the live prop (TASK-3423 PR B)

version-restore-collab (BUG-2264's e2e) blanked the item page after a
restore under live collab, 3/3 on kit 3: the force-refresh remount ran
EditorBubbleMenu's and EditorLinkPopover's effect cleanups, which read the
live editor prop. That read re-entered Svelte's flush and destroyed the
editor mid-transaction (state_unsafe_mutation from ProseMirror's blur
handler), and a null prop then threw on .off, killing the page (stacks
captured with Error.stackTraceLimit=100). The cleanups now close over the
editor their run subscribed to.

Evidence is the e2e: red 3/3 at 347942e17, green 3/3 (2 tests x 3) with
this change alone. A jsdom unit test could not reproduce it: there Svelte
hands a teardown the pre-teardown prop value, so the old cleanup passed
too, and a test that passes either way was not kept.

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

* fix(web): kit 3 in code main added since PR B: $app/env, goto reset in the library tabs (TASK-3423)

* test(web): re-review the identity-gate rows the rebase onto main re-hashed (TASK-3423)

collection page: quickCreateInColumn, the two pane-follow continuations,
installPaneTestHook, loadUrlFilters and updateUrlFilters. Only kit 3 API swaps
reach them (page.url.href, goto reset:false); no await or fence moved.
library page: the tab-switch goto now restores focus to the tab after the
navigation (kit 3 has no keepFocus); its continuation writes no state and is
tabled.

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

* test(e2e): quick capture's Open lands in the title editor under kit 3 (TASK-3423)

The captured item's URL carries ?new=1, which opens it with its title in
the editor. Under kit 2 the follow-up goto's focus reset closed the editor
at once, so the title read as text; kit 3's reset:false keeps it open
(site 3 of the day-87 ruling). Assert the editor's value instead.

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

* test(e2e): login honours ?redirect= and still refuses off-site targets (TASK-3423)

The login page now reads ?redirect= through $app/state's page, and that
value is validateRedirect's input. Nothing exercised the read: the share
and invite specs check only the link that points at /login. Covers the
form path from a signed-out context, the signed-in forward, and three
off-site shapes (absolute, protocol-relative, encoded slash).

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

* test(e2e): name the encoded-slash case by what the guard receives; off-site on the form path too (TASK-3423 r2)

Codex r2: the encoded-slash case is a value that still holds %2f after
searchParams decodes it once; the label and a comment now say so. Hunter
r2 L1: the form sign-in also gets an off-site target. Hunter r2 L2: the
off-site cases wait on one poll for "this origin, past /login", so an
intermediate URL cannot satisfy half of it.

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

* fix(web): the activity page's URL clear uses kit 3's goto options (TASK-3423)

#2226 landed dropFromUrl with goto's noScroll/keepFocus, which kit 3 removed
(they throw in dev and are ignored in prod), and new URL(page.url) on the
$app/state proxy. reset: false keeps scroll and focus as both options did;
page.url.href gives URL a string.

Claude-Session: https://claude.ai/code/session_018oQ5EErQKHtBJK8yLpcDNF
2026-10-18 19:03:13 -04:00
xarmian 652584bcfa test(web): jsdom/Svelte vitest harness + Modal & breakpoint tests (TASK-2081) (#887)
* test(web): add jsdom/Svelte vitest project + Modal & breakpoint tests (TASK-2081)

* test(web): update package-lock for jsdom test deps (TASK-2081 review)
2026-07-09 19:53:55 -04:00
xarmian 81579847c6 Initial release
Pad — project management for developers and AI agents.
Single Go binary with embedded SvelteKit web UI, SQLite storage,
CLI, and Claude Code /pad skill integration.

https://getpad.dev
2026-03-26 01:52:36 +00:00