In-process read surface: albums, photos, and timeline grouping #64

Merged
clawbot merged 3 commits from issue-44-read-surface into next 2026-09-22 17:21:48 +02:00
Collaborator

Adds the in-process read surface for
#44, served from RAM over the record
projection from #43; no call touches the
network.

Namespaces on Library, each taking one named-argument object:

  • lib.albumslist(), byName({albumName}), byID({collectionID}),
    returning Album wrappers, newest-updated first.
  • lib.photosbyID({fileID}) returns a Photo; records({fileIDs})
    returns plain PhotoRecord[] in the requested order, each id once, unknown
    ids dropped.
  • lib.timeline.groups({groupBy, filter?}) — buckets photos by local
    day/week/month; groups newest first, members newest first, each file once.

Album/Photo are thin wrappers for in-process callers only; record()
returns the JSON-safe record, which stays the IPC surface. Content fetch
(original/thumbnail) is a later unit — this is read-only.

Not obvious from the diff:

  • Grouping is local-time: startsAt is local midnight of the period, weeks
    start Monday (a Sunday joins the preceding Monday's week). Keys are
    YYYY-MM-DD for day and week (the Monday) and YYYY-MM for month.
  • PhotoFilter combines with AND: albumID, text (case-insensitive
    substring of title, caption, or any album name the photo belongs to),
    fileTypes, hasLocation (true = geotagged, false = none, omitted =
    either), includeArchived (default false). Hidden photos are never returned.

Judgement call: the issue sketched albums.list({onProgress?}); a RAM read is
synchronous with nothing to report progress on, so it takes no such argument,
matching the existing Library reads. Adding the field later is non-breaking.

make check is green (tests plus the Docker lint).

Model: opus-4-8

Adds the in-process read surface for https://git.eeqj.de/sneak/quak/issues/44, served from RAM over the record projection from https://git.eeqj.de/sneak/quak/issues/43; no call touches the network. Namespaces on `Library`, each taking one named-argument object: - `lib.albums` — `list()`, `byName({albumName})`, `byID({collectionID})`, returning `Album` wrappers, newest-updated first. - `lib.photos` — `byID({fileID})` returns a `Photo`; `records({fileIDs})` returns plain `PhotoRecord[]` in the requested order, each id once, unknown ids dropped. - `lib.timeline.groups({groupBy, filter?})` — buckets photos by local day/week/month; groups newest first, members newest first, each file once. `Album`/`Photo` are thin wrappers for in-process callers only; `record()` returns the JSON-safe record, which stays the IPC surface. Content fetch (original/thumbnail) is a later unit — this is read-only. Not obvious from the diff: - Grouping is local-time: `startsAt` is local midnight of the period, weeks start Monday (a Sunday joins the preceding Monday's week). Keys are `YYYY-MM-DD` for day and week (the Monday) and `YYYY-MM` for month. - `PhotoFilter` combines with AND: `albumID`, `text` (case-insensitive substring of title, caption, or any album name the photo belongs to), `fileTypes`, `hasLocation` (true = geotagged, false = none, omitted = either), `includeArchived` (default false). Hidden photos are never returned. Judgement call: the issue sketched `albums.list({onProgress?})`; a RAM read is synchronous with nothing to report progress on, so it takes no such argument, matching the existing `Library` reads. Adding the field later is non-breaking. `make check` is green (tests plus the Docker lint). Model: opus-4-8
clawbot added the needs-review label 2026-09-22 15:36:29 +02:00
clawbot self-assigned this 2026-09-22 15:36:29 +02:00
clawbot added 2 commits 2026-09-22 15:36:29 +02:00
TDD red phase for issue #44: the in-process read API served from RAM —
lib.albums (list/byName/byID), lib.photos (byID/records), Album/Photo
wrappers, and lib.timeline.groups with the PhotoFilter and day/week/month
grouping rules. These fail until src/library/read.ts lands.

Model: opus-4-8
Serve albums, photos, and a grouped timeline from RAM over the record
projection (#43), with no network. Every call takes one named-argument
object. `lib.albums` lists and looks albums up by name or id; `lib.photos`
resolves a file to a `Photo` wrapper or returns plain deduped records;
`lib.timeline.groups` buckets photos by local day/week/month, newest group
and newest member first, each file once.

`PhotoFilter` narrows the timeline by album, case-insensitive text (title,
caption, or album name), file type, and presence of a location; archived
photos are excluded unless asked for and hidden photos are never included.
Weeks start on Monday and `startsAt` is local-time midnight of the period.

Thin `Album`/`Photo` classes wrap the records for in-process callers only;
the plain records remain the IPC-safe surface. Content fetch (original,
thumbnail) is a later unit — this surface is read-only.

Model: opus-4-8
Author
Collaborator

FAIL — needs-rework.

Week timeline keys do not match the design. In src/library/read.ts, periodOf keys a week by its Monday's calendar date (dateKey(start)), so a week group's key is a YYYY-MM-DD value like 2024-01-15. Issue #44 fixes the keys as 2025-08-04 (day), 2025-W32 (week), 2025-08 (month): weeks are meant to use the ISO week form YYYY-Www. As built, a week key is formatted identically to a day key for the same Monday, so a day group and a week group collide and cannot be told apart from the key alone — which is exactly what the distinct -Www form exists to prevent. The definition of done's "timeline grouping keys correct" is therefore not met. The PR body and the code comment disclose the Monday-date choice but present it as the design; it contradicts the issue. Acceptable: week keys as YYYY-Www (e.g. 2025-W32), with the week tests updated to assert that form (the current week tests lock in the Monday-date value, so they change too). If Monday-date keys are actually wanted instead, that needs an owner ruling on the issue changing the spec.

Landing commit body runs long. The commit 1df0e52 body is about 136 words, past the ~120-word guideline. Acceptable: trim to essentials.

Disclosure: I concur with the PR's judgement call that albums.list() drops the sketched { onProgress? } argument — a synchronous RAM read has nothing to report and adding it later is non-breaking.

Model: opus-4-8

FAIL — needs-rework. **Week timeline keys do not match the design.** In `src/library/read.ts`, `periodOf` keys a week by its Monday's calendar date (`dateKey(start)`), so a week group's key is a `YYYY-MM-DD` value like `2024-01-15`. Issue https://git.eeqj.de/sneak/quak/issues/44 fixes the keys as `2025-08-04` (day), `2025-W32` (week), `2025-08` (month): weeks are meant to use the ISO week form `YYYY-Www`. As built, a week key is formatted identically to a day key for the same Monday, so a day group and a week group collide and cannot be told apart from the key alone — which is exactly what the distinct `-Www` form exists to prevent. The definition of done's "timeline grouping keys correct" is therefore not met. The PR body and the code comment disclose the Monday-date choice but present it as the design; it contradicts the issue. Acceptable: week keys as `YYYY-Www` (e.g. `2025-W32`), with the week tests updated to assert that form (the current week tests lock in the Monday-date value, so they change too). If Monday-date keys are actually wanted instead, that needs an owner ruling on the issue changing the spec. **Landing commit body runs long.** The commit `1df0e52` body is about 136 words, past the ~120-word guideline. Acceptable: trim to essentials. Disclosure: I concur with the PR's judgement call that `albums.list()` drops the sketched `{ onProgress? }` argument — a synchronous RAM read has nothing to report and adding it later is non-breaking. Model: opus-4-8
clawbot added needs-rework and removed needs-review labels 2026-09-22 17:00:50 +02:00
clawbot added 1 commit 2026-09-22 17:03:58 +02:00
Key timeline weeks by ISO week, not the Monday date
check / check (push) Successful in 16s
555badc0b9
periodOf keyed a week by the Monday's YYYY-MM-DD, which collides with
the day-key form. Weeks now key as YYYY-Www (ISO 8601, e.g. 2025-W32);
the week-year comes from the week's Thursday, so it stays correct across
the January/December boundary. The Monday-start boundary and startsAt
are unchanged. Week tests now assert the ISO form.

Model: opus-4-8
clawbot added needs-review and removed needs-rework labels 2026-09-22 17:06:51 +02:00
Author
Collaborator

PASS — the in-process read surface meets the definition of done: albums, photos, and timeline are served from RAM with args-object signatures over the #43 record projection (no read touches the client), dedup/filtering/ordering are correct, hidden photos are never returned, and the reworked week keys are now ISO YYYY-Www (e.g. 2025-W32), distinct from the day YYYY-MM-DD form and asserted in that shape by the week tests.

Disclosures:

  • The prior review's second finding is not applied: the landing commit 1df0e52 body is still ~136 words, over the ~120-word guideline. Because this branch is squash-merged, trim it into the squash message rather than spending a rework cycle on a commit body the squash supersedes.
  • Concur with the retained judgement call: albums.list() drops the sketched { onProgress? } argument — a synchronous RAM read has nothing to report and adding it later is non-breaking.

Model: opus-4-8

PASS — the in-process read surface meets the definition of done: albums, photos, and timeline are served from RAM with args-object signatures over the `#43` record projection (no read touches the client), dedup/filtering/ordering are correct, hidden photos are never returned, and the reworked week keys are now ISO `YYYY-Www` (e.g. `2025-W32`), distinct from the day `YYYY-MM-DD` form and asserted in that shape by the week tests. Disclosures: - The prior review's second finding is not applied: the landing commit `1df0e52` body is still ~136 words, over the ~120-word guideline. Because this branch is squash-merged, trim it into the squash message rather than spending a rework cycle on a commit body the squash supersedes. - Concur with the retained judgement call: `albums.list()` drops the sketched `{ onProgress? }` argument — a synchronous RAM read has nothing to report and adding it later is non-breaking. Model: opus-4-8
clawbot merged commit c5c1f387df into next 2026-09-22 17:21:48 +02:00
clawbot deleted branch issue-44-read-surface 2026-09-22 17:21:49 +02:00
Sign in to join this conversation.