fix(web): restore dead drag-and-drop feedback, remove the invisible inbox poll, add a webcheck guard #330

Merged
Cordy merged 12 commits from feat/rot-sweep into main 2026-08-27 18:38:47 +00:00
Owner

Deferred-items cluster A (#311 items 4, 5, 8, 12). The guard was written first; everything else in this PR is something the guard found.

Two real bugs, not just cleanup

Drag-and-drop row feedback has been dead since rows stopped being <tr>. The JS still calls classList.add("dragrow") and add("droptarget") on every drag, but the CSS was tr.dragrow and tr.droptarget > td — the classes are live, the element name died in PR1. Dragging a file has therefore had no grab cursor, no drag opacity and no drop highlight. Fixed by dropping the tag qualifier, not the rule: deleting these would have deleted a working feature's styling. (Breadcrumb drop targets were unaffected — .crumbs a.droptarget still matches a real <a>.)

The rail inbox dot was polling every 60 seconds for an element nobody can see. It was suppressed with display:none !important during the redesign and left in place. Behind it: setInterval(pollInbox, 60000) firing GET /api/v1/files?path=<Inbox> forever, purely to decide the visibility of an unreachable span. Removed the function, the timer, the element, the CSS override and the now-orphaned INBOX_SEEN_KEY.

The guard

internal/webcheck — a Go test, deliberately not a lint stage. go test ./... already runs in CI and on every contributor's machine; a Node or Python step would mean new tool installs on the runner and a second place for checks to live. No CI file is touched by this PR.

  • TestI18nKeysDefinedt() returns the key verbatim when missing, so an undefined key ships as literal ownerLbl text instead of failing. This check already caught one such bug in slice C.
  • TestSelectorTagsExist — the tr.pvsel shape: a class we really do set, pinned to an element we no longer build. Only tag+class compounds are checked, so styling markup injected by a vendored preview library (.xlsxwrap tr) doesn't false-positive.
  • TestUnusedClassesReportlogs, never fails. Classes are assembled at runtime ("kvbadge " + badgeCls), so an enforcing version would be flaky. Proven by this run: it flags teal and gray, which are real and applied through that very concatenation.
  • TestDetectorsCatchKnownBad — feeds each detector input that is broken in exactly the way the real bugs were broken, plus valid input that must not trip it. Without this, a refactor that quietly broke a regex would turn the file green and keep it green.

Dead CSS removed (item 8)

Twelve rules from the <table> era and admin slice A: td.meta, td.namecell*, .ncflex, tr.pvrow, td.rowactions*, .rowicon, .subpath, .namefav svg, .adminback*, .ovcard/.ovcards/.ovlabel/.ovnum. Matched on exact selector text so a combined rule could never be half-deleted.

Five candidates were left alone because I could not prove them dead: car, cl, gray, pc-toggle, teal. Two of those are known false positives; the rest are unverifiable statically, and deleting CSS on a guess is how you ship an invisible regression.

Stated limitation

None of these checks can see a broken combinator. aside > button shipped dead for weeks because the button stopped being a direct child while both the tag and the class still existed. Catching that needs a real DOM, which needs a login. The 47 combinator-coupled selectors in the file were reviewed by hand this pass; the limitation is written into the package doc so the next person doesn't assume more coverage than exists.

Gate: node --check on every script block, go vet ./..., go test ./..., go build ./cmd/cairnd.

Deferred-items cluster A (#311 items 4, 5, 8, 12). The guard was written first; everything else in this PR is something the guard found. ## Two real bugs, not just cleanup **Drag-and-drop row feedback has been dead since rows stopped being `<tr>`.** The JS still calls `classList.add("dragrow")` and `add("droptarget")` on every drag, but the CSS was `tr.dragrow` and `tr.droptarget > td` — the classes are live, the element name died in PR1. Dragging a file has therefore had no grab cursor, no drag opacity and no drop highlight. Fixed by dropping the tag qualifier, not the rule: deleting these would have deleted a working feature's styling. (Breadcrumb drop targets were unaffected — `.crumbs a.droptarget` still matches a real `<a>`.) **The rail inbox dot was polling every 60 seconds for an element nobody can see.** It was suppressed with `display:none !important` during the redesign and left in place. Behind it: `setInterval(pollInbox, 60000)` firing `GET /api/v1/files?path=<Inbox>` forever, purely to decide the visibility of an unreachable span. Removed the function, the timer, the element, the CSS override and the now-orphaned `INBOX_SEEN_KEY`. ## The guard `internal/webcheck` — a Go test, deliberately not a lint stage. `go test ./...` already runs in CI and on every contributor's machine; a Node or Python step would mean new tool installs on the runner and a second place for checks to live. No CI file is touched by this PR. - `TestI18nKeysDefined` — `t()` returns the key verbatim when missing, so an undefined key ships as literal `ownerLbl` text instead of failing. This check already caught one such bug in slice C. - `TestSelectorTagsExist` — the `tr.pvsel` shape: a class we really do set, pinned to an element we no longer build. Only tag+class compounds are checked, so styling markup injected by a vendored preview library (`.xlsxwrap tr`) doesn't false-positive. - `TestUnusedClassesReport` — **logs, never fails.** Classes are assembled at runtime (`"kvbadge " + badgeCls`), so an enforcing version would be flaky. Proven by this run: it flags `teal` and `gray`, which are real and applied through that very concatenation. - `TestDetectorsCatchKnownBad` — feeds each detector input that is broken in exactly the way the real bugs were broken, plus valid input that must *not* trip it. Without this, a refactor that quietly broke a regex would turn the file green and keep it green. ## Dead CSS removed (item 8) Twelve rules from the `<table>` era and admin slice A: `td.meta`, `td.namecell*`, `.ncflex`, `tr.pvrow`, `td.rowactions*`, `.rowicon`, `.subpath`, `.namefav svg`, `.adminback*`, `.ovcard/.ovcards/.ovlabel/.ovnum`. Matched on exact selector text so a combined rule could never be half-deleted. Five candidates were left alone because I could not prove them dead: `car`, `cl`, `gray`, `pc-toggle`, `teal`. Two of those are known false positives; the rest are unverifiable statically, and deleting CSS on a guess is how you ship an invisible regression. ## Stated limitation None of these checks can see a broken **combinator**. `aside > button` shipped dead for weeks because the button stopped being a direct child while both the tag and the class still existed. Catching that needs a real DOM, which needs a login. The 47 combinator-coupled selectors in the file were reviewed by hand this pass; the limitation is written into the package doc so the next person doesn't assume more coverage than exists. Gate: `node --check` on every script block, `go vet ./...`, `go test ./...`, `go build ./cmd/cairnd`.
Cordy merged commit bcbaf0f851 into main 2026-08-27 18:38:47 +00:00
Cordy deleted branch feat/rot-sweep 2026-08-27 18:38:49 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#330
No description provided.