mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-11-06 03:01:18 +00:00
75802627aa
Instrument only, not for merge. Four probe rounds, 61 runs, 19 failures (~1 in 3, matching every earlier count). The prior trail recorded "an unexplained Chromium activation failure" as what survived. That is now falsified. The click works. Round 7 — CDP Page domain + geometry. The FAILING click fires `Page.frameRequestedNavigation` with reason `anchorClick` and the CORRECT url, and `elementFromPoint` at the click coordinates is inside the right anchor with the right href, identical before and after. So activation is not suppressed and the click is not landing on the wrong element. Both readings this instrument was built to separate are refuted, and at the Page domain the failing click is indistinguishable from the succeeding retry. Round 8 — browser-level Target domain. A page target IS created for the failing click and IS navigated to the correct url (`created[X] url=""` then `changed[X] url=<the item>`), and is never destroyed. The tab opens. The navigation commits. Round 9 — page inventory. `context.pages()` contains only the main page. Round 10 — the timing, because round 9 cannot be read without it: "absent from context.pages()" means the opposite thing if the wait failed fast rather than timing out. It times out: `wait: 20056ms outcome=rejected: TimeoutError`, and a further `inventory(+2s)` — 22 seconds after the click — still holds one page. So the chain is complete: Chromium accepts the click, requests the navigation, creates the target, commits the url, keeps the target — and Playwright's BrowserContext never adopts it and never emits `page`. The retry's target, from an identical click on the same element, is adopted normally. That makes this a harness observation failure, not a product defect, and it retires the user-impact question for good: the tab opens and loads the right page every time, including on the runs the test calls failures. Consequence for the fix, which is the lead's call: polling `context.pages()` will not help, because the page never enters that list. The reliable signal is the CDP `Target.targetCreated` / `targetInfoChanged` pair, which fired correctly in all 19 failures. Claude-Session: https://claude.ai/code/session_019EmDd3Wy8b3cPG1TZBSzBu
Pad Web UI
SvelteKit 2 + Svelte 5 frontend for Pad, compiled to static files and embedded into the Go binary.
Development
npm install
npm run dev # Dev server at localhost:5173 (proxies API to localhost:7777)
npm run build # Production build to build/
npm run check # Type checking with svelte-check
When developing, run the Go backend separately with make dev from the project root.
Building for Production
Do not build in isolation. Always use make build from the project root — this builds the web frontend, then compiles the Go binary with the build output embedded via //go:embed.
Stack
- Svelte 5 with runes (
$state,$derived,$effect) - SvelteKit 2 with
adapter-static(SPA mode) - Tiptap block editor with markdown round-trip
- svelte-dnd-action for drag-and-drop in board/list views
- SSE for real-time updates
- TypeScript throughout
Structure
src/
routes/ SvelteKit pages
+layout.svelte App shell (sidebar + main)
+page.svelte Landing/redirect
[workspace]/
+page.svelte Dashboard (collections, phases, activity)
+layout.svelte SSE connection per workspace
[collection]/
+page.svelte Collection view (board/list)
[collection]/[item]/
+page.svelte Item detail + editor
conventions/ Purpose-built conventions page
playbooks/ Purpose-built playbooks page
settings/ Workspace settings
lib/
api/client.ts HTTP API client
components/
layout/ Sidebar, navigation
editor/ Tiptap editor, raw markdown editor
fields/ FieldEditor, relation picker
items/ ItemCard, ItemDetail
collections/ BoardView, ListView
common/ StatusBadge, badges, modals
search/ CommandPalette
stores/ Svelte 5 reactive stores
workspace.svelte.ts Workspace state
collections.svelte.ts Collection + item state
ui.svelte.ts Sidebar, mobile state
types/index.ts TypeScript types and constants
app.css Global styles and design tokens