Follow-ups from PR #44's second review. None blocking; filed rather than spending another review cycle.
1. .pin-btn floor of 10 false-passes on a partial regression
test/viewport/checks.js — tap-targets-44px requires each selector to match a minimum count of visible elements. .pin-btn declares 10, but 26 render (one per pinnable host row).
Demonstrated: patching src/main.js to render pins only for index < 12 and running at a 1px threshold gives 53/55 with tap-targets passing at every touch viewport — 54% of pin buttons gone, no signal.
The anti-vacuity property that blocked PR #44 still holds: 12 measured means the oracle is genuinely measuring the page. This is the weaker adjacent claim — the rework comment said the floor "also catches pin buttons stopped rendering per row", which is only true below 10.
Derive .pin-btn's minCount from facts.rowCount rather than a constant, so the floor tracks what should actually render.
Verify with a 12-of-26 pin-render mutation at a 1px threshold: tap-targets must FAIL. Revert after.
2. Two overclaiming statements
PR #44's body: "a hard kill cannot strand one". SIGKILL bypasses the trap; naming containers makes them identifiable, not self-cleaning. The in-file comment at script/frontend-viewport-test:31-35 is accurate — it only claims the timeout/SIGTERM case, which does work. Correct the body if it is edited for another reason; not worth a commit alone.
TODO.md: "Every check carries a presence guard". nothing-past-viewport-edge and no-clipped-text rely on the run-level app-rendered gate rather than their own. Nothing is vacuous — the whole run reds if the app did not render — but the wording overclaims.
TODO.md wording narrowed to what is true.
Not in scope
The mixed-breakpoint case throwing an uncaught Error with a stack trace rather than a clean message. Noisy, not wrong; leave it.
Notes
Coordinate with #43. Once that lands, the size threshold stops masking anything and this check becomes the sole guard against a stale selector — worth doing before or alongside it.
Not on the 1.0.0 milestone.
No attribution trailers in the commit message.
Follow-ups from PR #44's second review. None blocking; filed rather than spending another review cycle.
## 1. `.pin-btn` floor of 10 false-passes on a partial regression
`test/viewport/checks.js` — `tap-targets-44px` requires each selector to match a minimum count of visible elements. `.pin-btn` declares 10, but 26 render (one per pinnable host row).
Demonstrated: patching `src/main.js` to render pins only for `index < 12` and running at a 1px threshold gives **53/55 with `tap-targets` passing at every touch viewport** — 54% of pin buttons gone, no signal.
The anti-vacuity property that blocked PR #44 still holds: 12 measured means the oracle is genuinely measuring the page. This is the weaker adjacent claim — the rework comment said the floor "also catches pin buttons stopped rendering per row", which is only true below 10.
- [ ] Derive `.pin-btn`'s `minCount` from `facts.rowCount` rather than a constant, so the floor tracks what should actually render.
- [ ] Verify with a 12-of-26 pin-render mutation at a 1px threshold: `tap-targets` must FAIL. Revert after.
## 2. Two overclaiming statements
- **PR #44's body**: "a hard kill cannot strand one". `SIGKILL` bypasses the trap; naming containers makes them identifiable, not self-cleaning. The in-file comment at `script/frontend-viewport-test:31-35` is accurate — it only claims the `timeout`/`SIGTERM` case, which does work. Correct the body if it is edited for another reason; not worth a commit alone.
- **`TODO.md`**: "Every check carries a presence guard". `nothing-past-viewport-edge` and `no-clipped-text` rely on the run-level `app-rendered` gate rather than their own. Nothing is vacuous — the whole run reds if the app did not render — but the wording overclaims.
- [ ] `TODO.md` wording narrowed to what is true.
## Not in scope
The mixed-breakpoint case throwing an uncaught `Error` with a stack trace rather than a clean message. Noisy, not wrong; leave it.
## Notes
- Coordinate with #43. Once that lands, the size threshold stops masking anything and this check becomes the sole guard against a stale selector — worth doing before or alongside it.
- Not on the `1.0.0` milestone.
- No attribution trailers in the commit message.
Plan, against next as it is now (the harness is unchanged since this issue was filed):
test/viewport/checks.js: the .pin-btn entry of the tap-target check expects one visible pin button per host row, facts.rowCount, instead of the constant 10. The other controls keep their counts.
Verify: with src/main.js changed to render pin buttons for only the first 12 rows, make frontend-viewport-test fails on the tap-target check at the touch viewports; with the change reverted it passes. The planted change is not committed.
TODO.md: the 2026-08-09 harness entry says every check carries its own presence guard; narrow it to what is true (most checks guard themselves; the edge and clipped-text checks rely on the run failing as a whole when the app did not render). Check test/viewport/README.md for the same claim.
Nothing else in the harness changes. The PR body wording point is moot (that PR is merged).
Model: opus-5-5
Plan, against `next` as it is now (the harness is unchanged since this issue was filed):
1. `test/viewport/checks.js`: the `.pin-btn` entry of the tap-target check expects one visible pin button per host row, `facts.rowCount`, instead of the constant 10. The other controls keep their counts.
2. Verify: with `src/main.js` changed to render pin buttons for only the first 12 rows, `make frontend-viewport-test` fails on the tap-target check at the touch viewports; with the change reverted it passes. The planted change is not committed.
3. `TODO.md`: the 2026-08-09 harness entry says every check carries its own presence guard; narrow it to what is true (most checks guard themselves; the edge and clipped-text checks rely on the run failing as a whole when the app did not render). Check `test/viewport/README.md` for the same claim.
Nothing else in the harness changes. The PR body wording point is moot (that PR is merged).
Model: opus-5-5
Built in #96: the tap-target check now expects one pin button per WAN host row, and the TODO.md harness entry says which checks guard themselves and which rely on app-rendered. One departure from the plan: the harness's host row count also counted the two local host rows, which have no pin button, so it now counts only the WAN host rows; the PR body has the detail.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/netwatch/pulls/96: the tap-target check now expects one pin button per WAN host row, and the `TODO.md` harness entry says which checks guard themselves and which rely on `app-rendered`. One departure from the plan: the harness's host row count also counted the two local host rows, which have no pin button, so it now counts only the WAN host rows; the PR body has the detail.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-ups from PR #44's second review. None blocking; filed rather than spending another review cycle.
1.
.pin-btnfloor of 10 false-passes on a partial regressiontest/viewport/checks.js—tap-targets-44pxrequires each selector to match a minimum count of visible elements..pin-btndeclares 10, but 26 render (one per pinnable host row).Demonstrated: patching
src/main.jsto render pins only forindex < 12and running at a 1px threshold gives 53/55 withtap-targetspassing at every touch viewport — 54% of pin buttons gone, no signal.The anti-vacuity property that blocked PR #44 still holds: 12 measured means the oracle is genuinely measuring the page. This is the weaker adjacent claim — the rework comment said the floor "also catches pin buttons stopped rendering per row", which is only true below 10.
.pin-btn'sminCountfromfacts.rowCountrather than a constant, so the floor tracks what should actually render.tap-targetsmust FAIL. Revert after.2. Two overclaiming statements
PR #44's body: "a hard kill cannot strand one".
SIGKILLbypasses the trap; naming containers makes them identifiable, not self-cleaning. The in-file comment atscript/frontend-viewport-test:31-35is accurate — it only claims thetimeout/SIGTERMcase, which does work. Correct the body if it is edited for another reason; not worth a commit alone.TODO.md: "Every check carries a presence guard".nothing-past-viewport-edgeandno-clipped-textrely on the run-levelapp-renderedgate rather than their own. Nothing is vacuous — the whole run reds if the app did not render — but the wording overclaims.TODO.mdwording narrowed to what is true.Not in scope
The mixed-breakpoint case throwing an uncaught
Errorwith a stack trace rather than a clean message. Noisy, not wrong; leave it.Notes
1.0.0milestone.Plan, against
nextas it is now (the harness is unchanged since this issue was filed):test/viewport/checks.js: the.pin-btnentry of the tap-target check expects one visible pin button per host row,facts.rowCount, instead of the constant 10. The other controls keep their counts.src/main.jschanged to render pin buttons for only the first 12 rows,make frontend-viewport-testfails on the tap-target check at the touch viewports; with the change reverted it passes. The planted change is not committed.TODO.md: the 2026-08-09 harness entry says every check carries its own presence guard; narrow it to what is true (most checks guard themselves; the edge and clipped-text checks rely on the run failing as a whole when the app did not render). Checktest/viewport/README.mdfor the same claim.Nothing else in the harness changes. The PR body wording point is moot (that PR is merged).
Model: opus-5-5
Built in #96: the tap-target check now expects one pin button per WAN host row, and the
TODO.mdharness entry says which checks guard themselves and which rely onapp-rendered. One departure from the plan: the harness's host row count also counted the two local host rows, which have no pin button, so it now counts only the WAN host rows; the PR body has the detail.Model: opus-5-5