From 0e1549406f5fcb068adbe45f7118543196bdabe6 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 15 Sep 2026 16:57:14 -0700 Subject: [PATCH] Mark thread-query-bounds complete and refresh specifier notes Merge hardening verified on master: psf-memo-db unit (357), property (44), acceptance (11 suites, including thread-query-performance), and lint all pass. Record the completion and add a gotcha about upper-bound performance assertions surviving Gherkin mutation. By specifier. --- specifier-prompt.md | 25 +++++++++++++++++-------- specs/feature-backlog.md | 39 +++++++++++---------------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/specifier-prompt.md b/specifier-prompt.md index ca8271e..35c08be 100644 --- a/specifier-prompt.md +++ b/specifier-prompt.md @@ -386,7 +386,16 @@ that a single user-facing feature may require specs in more than one component. store and falls back to an optional externally loaded URL (e.g. from memo-db). Spec rendering features against that seam (image shown with the right `src`, no `` when unset) rather than against the DOM. Spec: - `psf-memo-client/specs/account-avatar-display.feature`. +23. **Upper-bound performance assertions can survive Gherkin mutation.** + A step like `the postChildren store was read at most entries` + only fails when the measured reads exceed the bound, so mutating the example + value upward (e.g. `1 -> 3`) can never fail and survives. The + thread-query-performance soft mutation run killed 6 of 8 and left both + `max_entries` upper-bound mutations alive. Treat these as intrinsic + equivalents (documented in `docs/reviews/thread-query-bounds-summary.md`), + not implementation gaps; prefer exact counts or independently-tied fixture + data when a bound must itself be mutatable. Spec: + `psf-memo-db/specs/thread-query-performance.feature`. --- @@ -424,13 +433,13 @@ At the end of each session, update this file: - Note the current `master` HEAD commit. - State the next feature to work on. -Current `master` HEAD: `5afaa64` (merged architect's account-avatar-display job — -the `/account` page now renders the avatar image when an avatar URL is set, -via a pure `AvatarImage` component shared by the browser build and the Node -acceptance adapter, with `AccountPage` display helpers -`getDisplayAvatarUrl`/`hasAvatarImage`/`getAvatarImageUrl` as the testable seam. -Verified client unit (298) + property (43) + acceptance (all 25 suites) + -lint + build all passing). +Current `master` HEAD: `c8ceb82` (merged architect's thread-query-bounds job — +`GET /posts/:txid/thread` now counts likes only for the thread's txids via +`countLikesForTxids` and prefix-scans `postChildren` per parent through a new +`PostQuery.listChildTxids` seam, so its work is proportional to the thread +rather than the database. Spec: +`psf-memo-db/specs/thread-query-performance.feature`. Verified psf-memo-db unit +(357) + property (44) + acceptance (all 11 suites) + lint all passing). Next action: **TBD** — current direction is front-end improvements to `psf-memo-client` (UI/UX polish, accessibility, performance, responsiveness, state handling, error surfacing). See `specs/feature-backlog.md`. diff --git a/specs/feature-backlog.md b/specs/feature-backlog.md index f5f6504..ca19ec2 100644 --- a/specs/feature-backlog.md +++ b/specs/feature-backlog.md @@ -31,6 +31,14 @@ focus is **front-end improvements** to `psf-memo-client` (the React SPA). ## Recently completed +- **Thread query performance (2026-09-15):** `GET /posts/:txid/thread` now does + work proportional to the thread instead of the whole database. Like counts are + computed only for the thread's txids via `countLikesForTxids` (the global + `buildLikeCountMap` was removed), and child lookups prefix-scan `postChildren` + per parent through a new `PostQuery.listChildTxids` seam instead of walking the + whole store once per node. Spec: + `psf-memo-db/specs/thread-query-performance.feature`. Merged to `master` at + `c8ceb82`. - **Account avatar display (2026-09-05):** the `/account` page now renders the avatar image when an avatar URL is set, instead of only showing the URL as text. A pure `AvatarImage` component (`src/components/account/avatar-image.js`, @@ -157,35 +165,10 @@ Reference: https://memo.sv/protocol (Wayback snapshot 2025-12-15) --- -## Next up: Thread query performance (psf-memo-db) +## Next up: TBD -`GET /posts/:txid/thread` is slow because `get-post-thread.js` does work -proportional to the whole database instead of the requested thread. Two -independent parts, one feature spec: - -- **Part A — like counts scoped to the thread.** `execute()` calls - `buildLikeCountMap()`, which iterates every `postLikes` entry and loads one - post per like. Build the thread first, then count likes for the thread's - txids via the existing `countLikesForTxids`. -- **Part B — child loading uses the parent index.** `loadChildTxids()` - iterates every `postChildren` entry once per thread node. Prefix-scan - `parentTxid:childTxid` (as `countRepliesForTxids` already does) instead. - -Spec: `psf-memo-db/specs/thread-query-performance.feature`. Affected -component: D (`psf-memo-db`). No client, indexer, or protocol changes. - -Thread shape, reply ordering, and per-node `likeCount` remain specified by -`psf-memo-db/specs/like-counts.feature` (scenario 3). `buildLikeCountMap` -still has unit/property coverage; the coder should update it if the method is -removed. - ---- - -## Previous: account avatar display — DONE (2026-09-05) - -The `/account` page now renders the avatar image when an avatar URL is set -(pure `AvatarImage` component + `AccountPage` display helpers). Merged to -`master` at `5afaa64`. +Current direction is front-end improvements to `psf-memo-client` (UI/UX polish, +accessibility, performance, responsiveness, state handling, error surfacing). ## Notes for future cycles