Review topic-recency-pagination: harden mutation coverage

Architectural review of the topic recency indexes and pagination:

- Indexer topic index maintenance lives in its own topic-indexing.js,
  separate from the action handlers; the backfill library takes injected
  LevelDB handles so its logic stays testable.
- DB listTopics reads counts from topicSummaries and paginates the
  topicRecency index without iterating the rooms store; the client reuses
  PaginatedPage.
- Kill four topic-indexing mutation survivors with focused unit tests
  covering the height fallbacks, plus exact-key/isNotFound and max-size
  boundary tests.
- One topic-message survivor is an intrinsic equivalent: handlePost reads
  the text at push index 1 and ignores push index 0.

Includes tool-written mutate4javascript and acceptance-mutation manifests.

By architect.
This commit is contained in:
Chris Troutner
2026-09-17 10:27:26 -07:00
parent d94aed8e64
commit 0e8f8f0eae
17 changed files with 167 additions and 7 deletions
@@ -1,3 +1,7 @@
# acceptance-mutation-manifest-begin
# {"version":1,"tested_at":"2026-09-17T17:25:15.930044025Z","feature_name":"Topic Pagination","feature_path":"/home/trout/work/psf-memo/.worktrees/architect/psf-memo-client/specs/topic-pagination.feature","background_hash":"74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b","implementation_hash":"unknown","scenarios":[{"index":1,"name":"Topic Pagination - 2 the topics page can load a later page","scenario_hash":"1d76d7c408593ae66f0f1551b1d583ccdceb0931d1dae35f5d02f8a0cb9636e9","mutation_count":6,"result":{"Total":6,"Killed":6,"Survived":0,"Errors":0},"tested_at":"2026-09-17T17:25:15.930044025Z"}]}
# acceptance-mutation-manifest-end
# Scenarios: Topic Pagination - 1, Topic Pagination - 2
#
# The topics page loads topics in pages of 50 and can move to a later page. The
@@ -39,5 +39,5 @@ TopicDiscoveryPage.topicFeedPath = function (room) {
module.exports = TopicDiscoveryPage
// mutate4javascript-manifest-begin
// {"version":1,"tested_at":"2026-08-28T15:33:23.381Z","module_hash":"a238b89f4edc83d06d6a424a0f2e19307187410fe8328b5220289dab5bf18fe6","functions":[{"id":"func/TopicDiscoveryPage.constructor","name":"TopicDiscoveryPage.constructor","line":12,"end_line":16,"hash":"5e7790aac90f4000c71b5e8a4b4b15c6b2895d1315cc05741a4fa2577c9f1d61"},{"id":"func/TopicDiscoveryPage.load","name":"TopicDiscoveryPage.load","line":18,"end_line":27,"hash":"2ce74ae73560c443d862dc97c65adda83ca5cd2bcc4c0df8bb87889d99b60f1d"},{"id":"func/TopicDiscoveryPage.getTopic","name":"TopicDiscoveryPage.getTopic","line":29,"end_line":31,"hash":"7faf4b56db0bc89d32176a1741546958495ba10b5f313581f321de47e58ecb95"},{"id":"func/TopicDiscoveryPage.openTopic","name":"TopicDiscoveryPage.openTopic","line":33,"end_line":37,"hash":"ebd17b5f176c964308b69705b7a53af4c9c392e9856308b3095d69151ebde9aa"}]}
// {"version":1,"tested_at":"2026-09-17T16:44:01.309Z","module_hash":"5d9d81d1a2fa72e4365f6db50999dc28988b51dfe9c90662187ebc8dc634bba9","functions":[{"id":"func/TopicDiscoveryPage.constructor","name":"TopicDiscoveryPage.constructor","line":14,"end_line":21,"hash":"78cbee16b0d08e3f695dc65865466d12424e67d40f16683603585a48adfc2510"},{"id":"func/TopicDiscoveryPage.getTopic","name":"TopicDiscoveryPage.getTopic","line":23,"end_line":25,"hash":"7faf4b56db0bc89d32176a1741546958495ba10b5f313581f321de47e58ecb95"},{"id":"func/TopicDiscoveryPage.openTopic","name":"TopicDiscoveryPage.openTopic","line":27,"end_line":31,"hash":"ebd17b5f176c964308b69705b7a53af4c9c392e9856308b3095d69151ebde9aa"}]}
// mutate4javascript-manifest-end