Files
STTracker/AGENTS.md
T
2026-10-30 15:39:14 +01:00

5.0 KiB
Raw Blame History

STTracker

Self-hosted meta media tracker: the user's own permanent record of books, games, film/TV, manga, podcasts and music, pulled from Hardcover, Trakt, MangaBaka, ListenBrainz, Last.fm and more. Bun 1.3, TypeScript 5, React, Kysely over SQLite (bun:sqlite) or Postgres (Bun.sql). Bun workspaces.

AGENTS.md is the single source of truth for agents here. CLAUDE.md and GEMINI.md only point here. Deeper context on demand: docs/ARCHITECTURE.md, docs/DECISIONS.md, docs/TODO.md. Product spec: docs/specs/001-sttracker-v1-design.md. Read it before any feature work.

Commands

Install: bun install --frozen-lockfile Test: bun test | Single test: TODO(maintainer): confirm bun test <path> once tests exist Typecheck: TODO(maintainer): confirm bun run typecheck (fails until source files exist) Lint: TODO(maintainer): confirm once a linter is chosen Dev / Build: TODO(maintainer): confirm once apps/server exists

Workflow

Required skills: superpowers, impeccable. Check at session start; install if missing. Specs → docs/specs/NNN-slug.md (permanent). Plans → docs/plans/NNN-slug.md while in progress; git rm them before opening a merge request. The spec is the record. (Overrides the superpowers default paths.)

Anything beyond a trivial fix: brainstorm → spec (sign-off) → plan (sign-off) → TDD → review. TDD means failing test first, watch it fail, minimal code, watch it pass, commit. Tick plan checkboxes as you go so an interrupted session is resumable. Trivial changes (typo, version bump, one-line config): say "trivial, skipping spec" and proceed.

Use impeccable for user-facing UI: craft for new UI, audit/polish on existing UI, harden before shipping. Design context: PRODUCT.md, DESIGN.md, docs/design/mockups/.

Rules

  • Bun-native only:
    • Bun.serve() with HTML imports for the web app. No Express, no Vite.
    • bun:sqlite and Bun.sql. No better-sqlite3, pg or postgres.js.
    • bun test. No Jest or Vitest.
    • Bun.password, Bun.file.
    • Bun loads .env itself. No dotenv.
  • Domain code queries through Kysely from packages/db. Dialect-specific SQL lives only in packages/db. Every DB-touching test must pass on both SQLite and Postgres.
  • Syncs never overwrite or delete user data directly. Source records go through the change engine. It applies a value only if field_sources says the user never edited the field; anything else becomes a Changes-inbox event. Deletes are soft (deleted_at).
  • Plugins (plugins/*) import only @sttracker/plugin-sdk. They never import packages/db or core internals, and they return SourceRecords instead of writing.
  • packages/* and plugins/* never import from apps/*.
  • IDs are UUIDv7 (newId()) generated in app code. Ratings are integers 0–100. Dates carry a precision (day | month | year | unknown).
  • Tests never call live APIs. Plugin tests use recorded fixtures through the SDK test harness.
  • Write-back (push) is opt-in per connection and off by default. No plugin pushes in Phase 1.

Architecture

apps/server -> Bun.serve: REST API /api/v1, /ingest/<plugin>, job worker, serves the web app apps/web -> React app via HTML imports packages/core -> domain services: entries, matching, change engine, history, export packages/db -> Kysely setup, SQLite/Postgres dialects, migrations packages/plugin-sdk -> plugin contract, SourceRecord types, http/rate-limit helpers, test harness plugins/ -> one source integration each

Full picture: docs/ARCHITECTURE.md. Read it before your first change in a session.

Boundaries

Never touch: docs/design/mockups/ (reference only), node_modules/, data/. Never commit .env, secrets, API keys, or recorded fixtures containing real tokens. Never force-push, rewrite pushed history, or commit directly to main.

Ask first: new runtime dependencies · public API, export schema (sttracker-export/v1) or migration changes after release · auth, token and credential-encryption code · anything destructive (rm -rf, git reset --hard, DB resets) · work the approved plan does not cover.

If the task turns out much larger than the plan assumed: stop, report, re-plan.

Docs duties

Same commit as the code, not "later":

  • docs/ARCHITECTURE.md: when a module, boundary, or data flow changes.
  • docs/DECISIONS.md: append-only; any choice a future maintainer would reverse-engineer.
  • docs/TODO.md: anything noticed and deliberately not fixed. No TODO comments in source.
  • docs/PERMISSIONS.md: together with .claude/settings.json, .codex/ and .gemini/settings.json, in one commit.

Git

Branches: feat|fix|chore/<slug>. Commits: Conventional Commits. Keep them small, each leaving tests green.

Done means verified

Do not report success on work you have not run. Before saying done, all of these must hold:

  • tests run in this session and seen passing, on both databases for DB code;
  • typecheck clean;
  • matches the approved spec;
  • docs duties complete;
  • git status clean and the diff is only what you intended.

"It should work" is not verification.