Cache/API implementation (#36), phase 2.
Depends on the snapshot/subscribe unit.
Goal
The in-process read surface for the CLI and scripts (the object model the owner
chose), all served from RAM: albums, photos, and timeline grouping. Every call
takes one args object with named keys (owner ruling — no positional arguments).
Album and Photo thin wrapper classes over the record calls, for in-process
callers only (the window uses the snapshot, not these). Album.photos.list, Photo fields (title, takenAt, fileType, ...). Content-fetch methods
(Photo.original()/thumbnail()) are added in the content-store unit; this
unit is read-only metadata.
lib.timeline.groups({ groupBy: "day"|"week"|"month"; filter? }) → TimelineGroup[] ({ key, startsAt ms local, fileIDs newest-first, each
file once). PhotoFilter ({ albumID?, text? case-insensitive substring of
title/caption/album name, fileTypes?, hasLocation?, includeArchived?
default false; hidden never included }). Week starts Monday; keys per the
design (2025-08-04, 2025-W32, 2025-08).
No network in any of these; all from the RAM model.
Definition of done
All read calls served from RAM, args-object signatures, correct dedup and
filtering; timeline grouping keys/order correct.
Tested; make check green.
Grounding
src/library/. Depends on snapshot/subscribe.
Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends (closes #<this issue>). End every message with Model: opus-4-8.
Model: opus-4-8
Cache/API implementation (https://git.eeqj.de/sneak/quak/issues/36), phase 2.
Depends on the snapshot/subscribe unit.
## Goal
The in-process read surface for the CLI and scripts (the object model the owner
chose), all served from RAM: albums, photos, and timeline grouping. Every call
takes one args object with named keys (owner ruling — no positional arguments).
## Scope
- `lib.albums.list({ onProgress? })`, `albums.byName({ albumName })`,
`albums.byID({ collectionID })`.
- `lib.photos.byID({ fileID })`, `photos.records({ fileIDs })` (plain
`PhotoRecord[]`).
- `Album` and `Photo` thin wrapper classes over the record calls, for in-process
callers only (the window uses the snapshot, not these). `Album.photos.list`,
`Photo` fields (`title`, `takenAt`, `fileType`, ...). Content-fetch methods
(`Photo.original()`/`thumbnail()`) are added in the content-store unit; this
unit is read-only metadata.
- `lib.timeline.groups({ groupBy: "day"|"week"|"month"; filter? })` →
`TimelineGroup[]` ({ `key`, `startsAt` ms local, `fileIDs` newest-first, each
file once). `PhotoFilter` ({ `albumID?`, `text?` case-insensitive substring of
title/caption/album name, `fileTypes?`, `hasLocation?`, `includeArchived?`
default false; hidden never included }). Week starts Monday; keys per the
design (`2025-08-04`, `2025-W32`, `2025-08`).
- No network in any of these; all from the RAM model.
## Definition of done
- All read calls served from RAM, args-object signatures, correct dedup and
filtering; timeline grouping keys/order correct.
- Tested; `make check` green.
## Grounding
`src/library/`. Depends on snapshot/subscribe.
Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends ` (closes #<this issue>)`. End every message with
`Model: opus-4-8`.
Model: opus-4-8
Implemented as #64 (branch issue-44-read-surface, base next).
Added lib.albums, lib.photos, and lib.timeline on Library, served from RAM over the record projection from #43; every call takes one named-argument object. Thin Album/Photo wrappers are for in-process callers only; the plain records stay the IPC surface. The timeline groups by local day/week/month (weeks start Monday, a Sunday joins the preceding Monday), newest group and member first, each file once; PhotoFilter covers albumID / text (case-insensitive title, caption, or album name) / fileTypes / hasLocation / includeArchived (default false), and hidden photos are never included. Read-only — content fetch is a later unit.
One judgement call: the issue sketched albums.list({onProgress?}), but a RAM read is synchronous with no progress to report, so it takes no such argument (matching the existing Library reads); adding it later is non-breaking.
make check is green (tests plus the Docker lint).
Model: opus-4-8
Implemented as https://git.eeqj.de/sneak/quak/pulls/64 (branch `issue-44-read-surface`, base `next`).
Added `lib.albums`, `lib.photos`, and `lib.timeline` on `Library`, served from RAM over the record projection from https://git.eeqj.de/sneak/quak/issues/43; every call takes one named-argument object. Thin `Album`/`Photo` wrappers are for in-process callers only; the plain records stay the IPC surface. The timeline groups by local day/week/month (weeks start Monday, a Sunday joins the preceding Monday), newest group and member first, each file once; `PhotoFilter` covers albumID / text (case-insensitive title, caption, or album name) / fileTypes / hasLocation / includeArchived (default false), and hidden photos are never included. Read-only — content fetch is a later unit.
One judgement call: the issue sketched `albums.list({onProgress?})`, but a RAM read is synchronous with no progress to report, so it takes no such argument (matching the existing `Library` reads); adding it later is non-breaking.
`make check` is green (tests plus the Docker lint).
Model: opus-4-8
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.
Cache/API implementation (#36), phase 2.
Depends on the snapshot/subscribe unit.
Goal
The in-process read surface for the CLI and scripts (the object model the owner
chose), all served from RAM: albums, photos, and timeline grouping. Every call
takes one args object with named keys (owner ruling — no positional arguments).
Scope
lib.albums.list({ onProgress? }),albums.byName({ albumName }),albums.byID({ collectionID }).lib.photos.byID({ fileID }),photos.records({ fileIDs })(plainPhotoRecord[]).AlbumandPhotothin wrapper classes over the record calls, for in-processcallers only (the window uses the snapshot, not these).
Album.photos.list,Photofields (title,takenAt,fileType, ...). Content-fetch methods(
Photo.original()/thumbnail()) are added in the content-store unit; thisunit is read-only metadata.
lib.timeline.groups({ groupBy: "day"|"week"|"month"; filter? })→TimelineGroup[]({key,startsAtms local,fileIDsnewest-first, eachfile once).
PhotoFilter({albumID?,text?case-insensitive substring oftitle/caption/album name,
fileTypes?,hasLocation?,includeArchived?default false; hidden never included }). Week starts Monday; keys per the
design (
2025-08-04,2025-W32,2025-08).Definition of done
filtering; timeline grouping keys/order correct.
make checkgreen.Grounding
src/library/. Depends on snapshot/subscribe.Dispatch notes: TDD; no scripted edits; no interactive questions; plain language.
Squash subject ends
(closes #<this issue>). End every message withModel: opus-4-8.Model: opus-4-8
Implemented as #64 (branch
issue-44-read-surface, basenext).Added
lib.albums,lib.photos, andlib.timelineonLibrary, served from RAM over the record projection from #43; every call takes one named-argument object. ThinAlbum/Photowrappers are for in-process callers only; the plain records stay the IPC surface. The timeline groups by local day/week/month (weeks start Monday, a Sunday joins the preceding Monday), newest group and member first, each file once;PhotoFiltercovers albumID / text (case-insensitive title, caption, or album name) / fileTypes / hasLocation / includeArchived (default false), and hidden photos are never included. Read-only — content fetch is a later unit.One judgement call: the issue sketched
albums.list({onProgress?}), but a RAM read is synchronous with no progress to report, so it takes no such argument (matching the existingLibraryreads); adding it later is non-breaking.make checkis green (tests plus the Docker lint).Model: opus-4-8