Captures the owner's requirements and decisions from the planning conversation, current branch/worktree state, open tasks 17-19, pending owner decisions and the controller's rulings so a new agent can resume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
status
| status |
|---|
| in-progress |
Phase 1 handoff (state as of 2026-11-02)
Read this first if you are picking up STTracker Phase 1. It is the bridge between the original conversation with the owner and the repo. Everything the owner decided is in the spec. Everything the controller decided while executing is in docs/plans/001-phase1-sdd/ledger.md (search for "Ruling").
Read in this order:
AGENTS.md- this file
docs/specs/001-sttracker-v1-design.mddocs/plans/001-phase1-own-your-data.mddocs/plans/001-phase1-sdd/ledger.md
1. What the owner asked for, and decided
The original request. A self-hosted "meta" entertainment tracker.
- Users connect their accounts on other platforms and get everything in one place.
- They can create their own entries when no platform has the item.
- Required platforms: Hardcover, Backloggd, Trakt and Last.fm.
- Stack: Bun with SQLite or Postgres.
- After the research, prepare the repo with the "preparing repos for agents" skill and push it to
https://gitea.lucaswinther.info/lucasw89/STTracker.git.
Why the owner wants it (their own words, summarised):
- Detect entries that were deleted or merged without their knowledge.
- Get backups that platforms don't offer.
- Move data between services that have no link to each other.
- Let an AI help convert data between services.
- Log things quickly without needing a "real" ID such as an ISBN or a TMDB id, and fix them later.
- Have the same features for every kind of media, instead of a separate "Trakt for X" per media type.
- Get cross-media recommendations and lists, e.g. Leitner → Magnus Archives → Voices of the Void → Twilight Zone.
- Have a personal, shareable page.
- The app must put the user in control. Users who keep a spreadsheet or Obsidian/Joplin notes must not have to conform to the data. Examples they gave:
- screenshots on games;
- where they bought something;
- rating a whole series as well as each book.
Owner decisions (all are already in the spec):
- Audience: the owner first, then a few friends, maybe a small public instance later. Social features are a nice-to-have, not now.
- Backloggd: wait for its official CSV export. Do not scrape it (it has no API and sits behind Anubis bot protection).
- Music: ListenBrainz is primary, with Libre.fm as a mirror and Last.fm as a read-only archive.
- Sources are plugins, so they can be fixed or added without big core changes.
- Owned library: a private "owned library" (Steam, Jellyfin and so on) that never shows on the profile.
- Other apps plug in later: Jellyfin, Kavita and Calibre-Web, through STTracker's own API, app tokens and OAuth. Phase 3 ingest: webhooks, a ListenBrainz-compatible endpoint and kosync.
- Stack: React plus Docker.
- Look:
- The app is "Hardcover-style".
- The public page is "scrapbook + river".
- "Shelf" and "card catalogue" are parked as future themes.
- Mockups:
docs/design/mockups/.
- Conflicts: when two sources disagree, ask the user via the Changes inbox. The same play from two sources is merged.
- Write-back: Phase 1 is read-only. Write-back is opt-in per connection, off by default, and comes in Phase 2.
- Execution: "Use subagent drive, and use multiple agents at once."
- The owner's global preference (
~/.claude/CLAUDE.md): once a design is approved, carry it through spec → plan → execution with no extra review stops, and report decisions at the end.
2. Where the code is
main(on Gitea): only the bootstrap commit (560c27c). Nothing else has been pushed.feat/phase1(local only, not pushed) @42fea7dcontains Tasks 1–16, all reviewed, fixed and merged:- db layer, schema, migrations 0001–0003;
- plugin SDK;
- auth;
- works and matching;
- user layer (entries, engagements, history, lists, copies, custom fields);
- attachments and crypto;
- all six plugins (Trakt, Hardcover, MangaBaka, CSV/JSON, ListenBrainz, Last.fm);
- sync engine and Changes inbox;
- jobs, scheduler, registry and connections;
- export, restore and backups;
- the server API.
- Last full verification on
feat/phase1: 520 tests pass on SQLite+Postgres, and typecheck is clean.
Open work (each item is a branch with a worktree under .worktrees/):
| Task | Branch @ head | State | Next step |
|---|---|---|---|
| 17 web shell, library, entry detail | task/17 @ 9546fa1 |
Fix round 3 done. Its re-review died on a usage limit before finishing. | Re-run the scoped re-review of 4608c97..9546fa1 (review-draft sync; see ledger). If clean, merge into feat/phase1. |
| 18 Changes, Sources, Log, Lists, Owned, Settings, About | task/18 @ bbd04a5 |
Partly done. Committed: core/server log feed, change titles, copy work titles, the plugins device flag, the library cache fix, and the Changes, Sources, Log and Lists screens. Not done: Owned, Settings (prefs, custom fields, tokens, invites, reload, export/import), About, the describeChange/scheduleLabel tests, the CDP check and docs. The implementer stopped on a usage limit. |
Dispatch a fresh implementer with task-18 brief + this table + "continue from bbd04a5". Then review it. It also must git merge task/17 again after Task 17 is final. |
| 19 Docker, compose, CI, docs | task/19 @ 0a54020 |
Barely started. Only an uncommitted DECISIONS.md reorder exists in .worktrees/t19. |
Dispatch a fresh implementer (brief + the Task 19 rulings in the ledger). Base it on feat/phase1 after 17/18 land, or merge them in later. The uncommitted DECISIONS edit can be kept or redone. |
After 17, 18 and 19 are merged, follow the plan's Completion section:
- Full suite on both DBs, plus typecheck.
- A whole-branch final review on the most capable model, triaging the deferred minors in the ledger.
git rmthe plan, this handoff anddocs/plans/001-phase1-sdd/.- Mark the spec
implemented. - Merge to
mainvia superpowers:finishing-a-development-branch. - Push only with owner approval.
Branches task/4…task/16 are merged and can be deleted. The .worktrees/t8, t9, t15, t16 worktrees are merged too and can be removed with git worktree remove.
3. How the work is being run (for the next controller)
-
Skill: superpowers:subagent-driven-development, with parallel implementers. The owner asked for this, overriding the skill's one-at-a-time default.
-
Worktrees: the controller creates them itself:
git worktree add .worktrees/tN -b task/N feat/phase1 cd .worktrees/tN && bun install --frozen-lockfileDo not use the Agent tool's
isolation: "worktree". It branches frommain, notfeat/phase1. -
Workspace scripts:
- SDD workspace and briefs:
bash <superpowers>/skills/subagent-driven-development/scripts/{sdd-workspace,task-brief,review-package}. - The ignored workspace is
.superpowers/sdd/001-phase1-own-your-data/. A copy of the ledger, rulings, fix findings and implementer reports is indocs/plans/001-phase1-sdd/, because.superpowers/is gitignored.
- SDD workspace and briefs:
-
Dispatch pattern:
- Implementers read
docs/plans/001-phase1-sdd/common-implementer.md, their brief and anytask-N-rulings.md. - Reviewers read
common-reviewer.md. - Every fix round gets a scoped re-review.
- Merge with
git merge --no-ff task/N, then run the full suite on both DBs. - The owner has interrupted merge commands twice, then replied "Approved." Expect a permission prompt on merges into
feat/phase1.
- Implementers read
-
Test Postgres: the docker container
sttracker-pg-teston127.0.0.1:55432(docker start sttracker-pg-testif it is stopped).TEST_POSTGRES_URL=postgres://postgres:postgres@127.0.0.1:55432/postgres bun test -
Model choice that worked:
- Opus for core, engine, server and web implementers and their reviewers.
- Sonnet for plugins and small fixes.
- Haiku only for tiny re-reviews.
4. Pending owner decisions (surface these, don't work around them)
- Agent permission files. Task 16's implementer tried to add verified commands to
.claude/settings.jsonand.gemini/settings.json, and the harness denied it as agent self-modification. Nobody has worked around this.- The wanted change is in
docs/TODO.md: allowbun run typecheck,bun apps/server/src/main.tsandbun --hot apps/server/src/main.ts. docs/PERMISSIONS.mdand the AGENTS.md Commands section are waiting on the same decision.- The owner should either make the edit, or approve an agent making it.
- The wanted change is in
- Pushing
feat/phase1to Gitea, and the final merge tomain.
5. Key technical decisions made during execution
The full list is in the ledger and docs/DECISIONS.md. The ones a newcomer would otherwise trip on:
- Database access:
- A single Kysely dialect over
Bun.SQLserves bothsqlite://andpostgres://. - SQLite runs on one connection behind a mutex, so inside a transaction always use
tx, neverdb.k, or it deadlocks. - IDs are UUIDv7. JSON is stored as text.
- A single Kysely dialect over
- External-ID namespaces are type-specific (
trakt_movie,tvdb_episode,anilist_manga, …). Private works can't carry external IDs. field_sources:- It records who owns each field. Any non-
plugin:actor is stored as"user"; history keeps the full actor (token:<name>). - A sync only applies a field it owns. Otherwise it files a pending
changedorconflictevent. - Stale pending events are superseded.
- Plugin actors never revive deletes.
- It records who owns each field. Any non-
- Hierarchy:
- Creating a child entry also ensures the root ancestor has an entry.
- Rollups and drill-down work to depth 3, skipping untracked intermediates.
- Lists from sources are applied. A list becomes user-owned after a user edit.
- Secrets:
- Secret config is stored only in encrypted
credentials_enc(AES-GCM, key fromSTTRACKER_SECRET). - Rate limits are declared on the plugin manifest (
rateLimit).
- Secret config is stored only in encrypted
- Jobs:
- The queue lives in the DB, with an advisory-locked enqueue, an atomic claim, a heartbeat and a stale-reaper.
- Pre-run failures (bad secret, missing plugin) are non-retryable and visible.
- API:
- Cookie sessions plus app tokens.
- CSRF uses the
X-Requested-With: sttrackerheader on every non-Bearer write, including login. - JSON bodies require
content-type: application/json.
- Export:
- The format is
sttracker-export/v1: a per-user zip with JSONL files, including deleted rows, aliases and tombstones, and no secrets. - Restore goes into an empty account only.
- Backups are daily, with 0600 files.
- The format is
6. Not in Phase 1 (from the spec)
The following come later:
- the public page (scrapbook + river);
- Markdown vault sync;
- Steam and Jellyfin owned-library connectors;
- IGDB, TMDB and OpenLibrary lookups;
- Libre.fm;
- write-back and migration;
- the ingest endpoints;
- the Kavita, Audiobookshelf, Komga and Calibre-Web connectors;
- Backloggd CSV import;
- an MCP server;
- themes;
- an OAuth provider;
- social features.
Deferred minors from every task review are in the ledger, with "minor (deferred)" lines, and in docs/TODO.md.