From 3095be68eedb74136183b90c45cf6c17e891f21d Mon Sep 17 00:00:00 2001 From: Destin Date: Fri, 11 Sep 2026 04:44:05 -0700 Subject: [PATCH] =?UTF-8?q?wrap-up:=20the=20site-copy=20session's=20findin?= =?UTF-8?q?gs=20=E2=80=94=20deck=20write=20guard,=20probe=20traps,=20shell?= =?UTF-8?q?=20trap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four findings from the session that shipped the site copy (youcoded #471, this workspace #92), landed where the next session reads them. - roadmap (dev-workspace, rigs): a stale review-deck page can overwrite .answers.json — deck/serve.py writes it on every POST with no guard, and that is the bug just fixed in site-copy-editor.py, where it erased a finished set of Destin's edits. The deck is the surface he answers every UI review on, so the same accident there loses answers. rotate_submitted covers only the already-submitted case. - scripts/ui-probe.mjs header: the three shapes that make a live-site probe read wrong — scrollTo/scrollIntoView do nothing on a body with `overflow: hidden auto`; intro-revealed sections sit at opacity 0 until their IntersectionObserver fires; the gallery and loops are lazy. Cost ~12 probe calls and one blank screenshot nearly reported as a rendering bug. - docs/wrap-ups.md: the session's entry, including the destructive-copy mistake (copying a file into a worktree copies the SHARED checkout's version, and `git checkout --` then discards a sibling session's uncommitted edits) and that the old session branch was 42 commits behind when wrap-up edits were attempted. The `pkill -f` self-match (it killed my own shell and silently skipped a commit) went to ~/system/tools/claude-code-bash-shell.md, which is outside this repo. Submitted via YouCoded Assistant --- ROADMAP.md | 2 +- docs/roadmap/dev-workspace.md | 10 ++++++++++ docs/wrap-ups.md | 11 +++++++++++ scripts/ui-probe.mjs | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 04c33c7b..3af1f24a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -53,7 +53,7 @@ Target: `v1.3` ## Backlogs | Area | Open | Needs verify | Decisions | Parked | |---|---|---|---|---| -| [dev-workspace](docs/roadmap/dev-workspace.md) — building the app, not the app | 104 | 30 | 4 | 10 | +| [dev-workspace](docs/roadmap/dev-workspace.md) — building the app, not the app | 105 | 30 | 4 | 10 | | [native-harness](docs/roadmap/native-harness.md) — the app's own agent doing work | 63 | 11 | 4 | 23 | | [user-interface](docs/roadmap/user-interface.md) — shared primitives, chrome, layout, copy | 36 | 17 | 1 | 6 | | [remote-access](docs/roadmap/remote-access.md) — reaching the app from another device | 28 | 6 | 0 | 4 | diff --git a/docs/roadmap/dev-workspace.md b/docs/roadmap/dev-workspace.md index e56cd448..f482e08a 100644 --- a/docs/roadmap/dev-workspace.md +++ b/docs/roadmap/dev-workspace.md @@ -248,6 +248,16 @@ seen-on is always n/a here. reviewing the new terminal scenario, 2026-09-10 `desktop` `confirmed` `checked 2026-09-10` +- [ ] A stale review-deck page can overwrite the answers file. `scripts/ui-review/deck/serve.py` + writes `.answers.json` on every `/answers` POST with no guard, so a deck page left + open across a server restart rewrites the file from its own state. That is the bug fixed in + `site-copy-editor.py` on 2026-09-10, where it erased a finished set of Destin's site edits — + and the deck is the surface he answers EVERY UI review on, so the same accident there loses + review answers, not copy. `serve.py` already rotates a *submitted* file aside on re-serve + (`rotate_submitted`); this is the in-flight case it does not cover. Fix as that tool now + does: refuse a write that would drop answered steps instead of overwriting. + `n/a` `confirmed` `checked 2026-09-10` + - [ ] The speed-test comparison judges two runs taken at very different machine load as if they were alike. On 2026-09-10 two freeze-fix branches both read 16–20% slower than master on long-conversation switches; it took a second master run and a second run of each branch diff --git a/docs/wrap-ups.md b/docs/wrap-ups.md index f64994e5..f34ddbf1 100644 --- a/docs/wrap-ups.md +++ b/docs/wrap-ups.md @@ -395,3 +395,14 @@ recurred — the repetition is the data. - Two fresh reviewers each found ONE real issue in code I'd already tested green: the WS Origin check refused the phone's opaque `Origin: null` (would 403 the real Android WebView), and the updater's "Open in browser instead" link handed the user the raw binary a verify-failure had just refused. Both fixed → applied (youcoded 723eb9e8, e607c7c9). The phone-origin lesson landed at the top of the ladder (pinning test in `remote-origin.test.ts` + WHY comment), not as prose. **A green test suite is not a substitute for an adversarial reader on security code** [2 real defects past a passing suite] - `update-install-types.ts` told the next session to "keep in sync with the Kotlin stub's error-code enum" — there is no such enum (the stub only returns "not-supported"), which cost one search to confirm before adding two codes → applied: corrected the comment (youcoded 311ad4f7) so the next code addition skips that search - deleted/merged: none found — the docs touched (STATUS, fix-plan companion, memory, one roadmap line) were each load-bearing; no overlapping tooling created. + +## 2026-09-11 — site copy editing, then shipping it (session/2026-09-10-site-copy-editor, youcoded + workspace) + +- **Destin asking to "edit the website" found an untracked scratch tool that had never run against the current site**, and the five blockers between it and working were all invisible until it ran: no page could show its own pictures (served one file from `/tmp`), the "Show editable" button had no CSS, a centred toolbar sat on the site's own docked pill, a whole-element regex let a matched ancestor swallow nested blocks (the first FAQ answer was permanently uneditable), and a single stalled connection froze the page → applied: tool documented in `scripts/ui-review/README.md` → "Editing copy on the site", MAP landing-page row, `.claude/rules/landing-page.md`, `workspace-workflows.md`, and `tests/test_site_copy_editor.py` (14 cases) in CI; shipped with the round-1/2 copy in youcoded #471 [the FAQ question cost 2 restarts and ~15 probe calls because nothing said `` is a tag the marker ignores] +- **The tool destroyed its own output, and Destin found out first.** `rm -rf /tmp/site-copy-edit` on a restart deleted a finished set of 24 submitted edits, and a tab still open from before the restart then autosaved its empty state over the file → applied: `write_edits` refuses to overwrite a real submission with an empty one (3 new tests), `--out-dir` defaults to the git-ignored `scratch/` instead of `/tmp`, README says why [recovered from the transcript, so nothing was lost — but a submission is exactly the thing a tool must not lose] +- **The same unguarded write is in the review deck, where it costs answers.** `deck/serve.py` writes `.answers.json` on every POST with no guard, so a stale deck page can rewrite it from its own state; the deck is the surface Destin answers EVERY UI review on, and `rotate_submitted` only covers the already-submitted case → roadmap: `dev-workspace.md` `## rigs` [found by generalising one line of my own fix, not by a search] +- **Probing the live site in headless produced three false readings before any of them was real**: `window.scrollTo`/`scrollIntoView` move nothing on a body with `overflow: hidden auto` (so the screenshot is the wrong place), intro-revealed sections sit at `opacity: 0` until an IntersectionObserver fires (so a blank shot looks like a broken page), and the gallery/loops are lazy (so they read as unloaded) → applied: all three named in `scripts/ui-probe.mjs`'s header with the day they were measured [~12 probe calls, and one blank screenshot I nearly reported as a rendering bug] +- **`pkill -f ""` killed my own shell twice, and the second time silently skipped a commit**; the wrapper's command line contains the pattern, so it matches itself and everything after it never runs → applied: note + PID-loop recipe in `~/system/tools/claude-code-bash-shell.md`, corrected to say it is not zsh- or Claude-Code-specific [one commit that "succeeded", re-run to find out it had not] +- **Copying a file into my worktree copied the SHARED checkout's version of it, and my `git checkout --` then discarded the shared edits.** Three files (roadmap, ROADMAP, ui-probe) had work from a parallel session on disk; only the ui-probe edit was mine and only dev-workspace came back on the next start. The old session branch was also 42 commits behind, so it was the wrong base for wrap-up edits and a fresh worktree was required → dropped as a rule (the copies were redundant once rebased); recorded because `git checkout -- ` in the shared checkout is a destructive habit that can discard a sibling session's uncommitted work [~8 calls of forensics, and one near-miss where I almost swept another session's content onto my branch] +- **Workspace CI red on my PR on the perf rig was the runner's Chrome launch, not my change** — the perf-lab flake already filed in `dev-workspace.md` → recurrence; `gh run rerun --failed` came back green. Recorded so `ci-red-vs-master.sh` being right about "not on master" is not read as "your fault": it says *new relative to master*, and a flake is exactly that on the day it first appears +- deleted/merged: `copy-review.py` left alone after checking (the old-table tool `copy-preview`'s header cites as rejected; no test, script or live doc runs it — a real deletion, but not mine to make mid-wrap-up) → filed here rather than deleted silently diff --git a/scripts/ui-probe.mjs b/scripts/ui-probe.mjs index 9b67bfe6..39806529 100755 --- a/scripts/ui-probe.mjs +++ b/scripts/ui-probe.mjs @@ -51,6 +51,21 @@ // content, structure, text and geometry; check colour and highlight state in a // dev instance (`bash scripts/run-dev.sh`), not here. // +// TWO PAGE SHAPES THAT MAKE A PROBE LOOK WRONG, both measured 2026-09-10 on +// youcoded/docs/index.html: +// * `window.scrollTo` / `scrollIntoView` move NOTHING when the page scrolls a +// body with `overflow: hidden auto` — `window.scrollY` stays 0 and the +// element's rect never changes, so the screenshot shows the wrong place. Check +// `getComputedStyle(document.body).overflow` before trusting a scroll. +// * Sections revealed by an intro animation sit at `opacity: 0` (the site's +// `body.intro-mode > section`) and the reveal runs on IntersectionObserver. A +// probe that does not let that observer fire photographs a blank page while the +// DOM reports the element present and in view. Force `opacity: 1` in the probe +// (a stylesheet), or isolate the section; an all-dark shot is the ANIMATION not +// having run, not a broken page. +// * The gallery and the media loops are lazy — they load on scroll, so they read +// `naturalWidth 0` / `readyState 0` in a probe that never scrolls. +// // Examples: // node scripts/ui-probe.mjs http://127.0.0.1:8791/deck.html \ // --wait 'window.__deckReady' --eval 'document.body.dataset.layout' --shot /tmp/deck.png