From 29b9d2437cc190d60f81e847b023b91b1c1192a5 Mon Sep 17 00:00:00 2001 From: Keysat Date: Fri, 12 Jun 2026 20:02:27 -0500 Subject: [PATCH] Add AGENTS.md, ROADMAP.md, and CLAUDE.md symlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Onboarding doc for fresh agent sessions: stack, commands, layout, conventions, and an Always/Never list of gotchas hit during the AI overhaul. Current state section tracks the 1.1.0:7 checkpoint. ROADMAP.md holds the longer-term backlog. CLAUDE.md symlinks AGENTS.md so Claude Code loads it. Secrets kept out — private registry/file-host URLs and creds referenced by file location, not value. --- AGENTS.md | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + ROADMAP.md | 25 ++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md create mode 100644 ROADMAP.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..217ad26 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,112 @@ +# AGENTS.md — Proof of Work + +Self-hosted multi-user workout logger (Next.js app) packaged as a StartOS 0.4 `s9pk`, published to a private Start9 registry. + +## Stack (versions that matter) + +- **Next.js 14** (App Router, server components + server actions, SSE streaming) +- **React 18**, **TypeScript 5**, **TailwindCSS 3** +- **Prisma 5** ORM over **SQLite** (WAL mode; tuned at boot) +- **bcrypt** (native — NOT bcryptjs), **zod 3** for validation +- **Vitest 4** for tests +- **@start9labs/start-sdk** for the 0.4 packaging layer +- Node **>= 20** to build + +## Layout (two projects in one repo) + +``` +proof-of-work/ ← the Next.js app (THIS is where you run npm) + app/ ← App Router routes; app/api/** = route handlers + app/main/ ← authed UI; navigation.tsx = sidebar + components/ ← React components (workouts/, ai/, settings/) + lib/ai/ ← AI subsystem (see below) + lib/ai/providers/ ← claude.ts openai.ts gemini.ts ollama.ts + index.ts (getProvider) + prisma/schema.prisma ← schema (mirror; real DB migrates via entrypoint ALTERs) + prisma/*.seed.json ← curated exercise library + AI templates (reconciled each boot) + tests/ ← Vitest specs (ai-*.test.ts, routes-*.test.ts, ...) +start9/0.4/ ← StartOS packaging wrapper + docker_entrypoint.sh ← boot: first-boot seed, additive ALTERs, library reconcile + Makefile / s9pk.mk ← s9pk build (ARCHES := x86) + startos/versions/ ← one file per ExVer version + index.ts (the version graph) +~/.proof-of-work/ ← publish.sh + unpublish.sh (NOT in repo; self-hosted registry) +``` + +`workout-planner/` is scratch (only `logs/`) — ignore. `start9/0.4/*.s9pk` are build artifacts. + +## Commands + +Run app commands **from `proof-of-work/`** (running tsc/vitest/next from repo root fails — wrong cwd): + +```bash +cd proof-of-work +npm run dev # local dev server +npm run build # next build (run this to catch route/type errors before shipping) +npm run lint # next lint +npm test # vitest run (full suite) +npx vitest run tests/ai-pricing.test.ts # single file +npx vitest run -t "findPrice" # single test by name +npx tsc --noEmit # typecheck only +npx prisma generate # REQUIRED after editing schema.prisma (else TS can't see new fields) +``` + +Build/sideload the s9pk (from `start9/0.4/`): `make x86` then `make install`. +Publish to the registry: `~/.proof-of-work/publish.sh` (builds, uploads to FileBrowser, registers). Unpublish: `~/.proof-of-work/unpublish.sh`. + +## Conventions + +- **Versioning is ExVer**: `1.1.0:4` (note the colon). Every release = a new `start9/0.4/startos/versions/vMAJOR.MINOR.PATCH.N.ts` file, imported into `versions/index.ts` and promoted to `current` (previous `current` moves into `other[]`). +- **Bump the version BEFORE building the s9pk** — Start9 0.4 won't recognize a rebuild as an update otherwise. +- **Schema changes are additive ALTERs in `docker_entrypoint.sh`**, guarded by `PRAGMA table_info` checks. Keep `schema.prisma` in sync as the mirror, but the entrypoint is what migrates live `/data`. Never write a destructive migration. +- **Commit subject** = `vX.Y.Z:N — short summary`, imperative, body explains the *why*. +- **Git remote is self-hosted** (a private Start9 registry + a FileBrowser artifact host), NOT GitHub. The actual registry/file-host URLs are constants in `~/.proof-of-work/{publish,unpublish}.sh`; FileBrowser creds live in `~/.keysat/filebrowser.env` (outside the repo, gitignored). Default branch is `master`. +- AI provider abstraction: each provider yields an async iterable of `GenerateChunk` (`text` / `usage` / `done` / `error`); add new ones under `lib/ai/providers/` and register in `index.ts`. +- Streaming AI uses SSE; partial JSON is recovered with `lib/ai/lenientJson.ts`. +- Tests live in `proof-of-work/tests/`; mock server-action deps with `vi.hoisted()` + `vi.mock`. +- Pricing/model menus live in `lib/ai/pricing.ts` (`PRICES`, `MODEL_MENU`) — keep them paired so every menu model has a price entry (there's a test enforcing this). + +## Always + +- Run `npx prisma generate` after any `schema.prisma` edit, then `npx tsc --noEmit`. +- Run `npm test` AND `npm run build` before shipping a version. +- Add the boot-time `ALTER TABLE` (with an existence guard) for any new column, in `docker_entrypoint.sh`. +- Treat API keys / secrets as plaintext in `/data` BY DESIGN (threat model: the operator owns `/data`). Reference env-var names (`DATABASE_URL`, etc.); never hardcode values. +- Keep migrations idempotent and additive; data already on a user's server must survive upgrades. +- Verify the published file actually changed (size / 404 / Last-Modified) after publish.sh. + +## Never + +- **Never add `Co-Authored-By` / "Generated with" trailers** to commits — the user authors commits solo. (This was done wrong in earlier commits; do not repeat.) +- **Never reintroduce nonce-based CSP** — it broke first paint. Use the static `'unsafe-inline'` CSP in `next.config.js`. +- **Never run app commands from the repo root** — always `cd proof-of-work` first. +- **Never export non-HTTP-method symbols from a `route.ts`** — Next.js rejects the build (helpers go in `lib/`, e.g. `lib/ai/activateConfig.ts`). +- **Never commit `app.db`, `*.bak`, or any user data** — they're gitignored; double-check `git status` before `git add`. +- **Never click Uninstall on a StartOS package during a data cutover** — it destroys the volume; use Stop. +- **Never assume GitHub** — don't add a GitHub remote or push there. + +## AI subsystem cheat-sheet + +- `generate/route.ts` kicks off a **detached background runner** (`generationRunner.ts`) and returns an id; the client attaches via SSE (`generations/[id]/stream`) and can also poll the row. Navigating away does NOT cancel generation. +- System prompt = `systemPromptBase.ts` (output contract: JSON-only, library `exerciseId`s only, suggested weights) + the template's coaching prompt + `PROGRAM_OUTPUT_SHAPE` + library + optional history block (`historyContext.ts`). +- Multi-config: `AIConfigProfile` rows per user; `UserPreferences.activeAIConfigId` points at the active one and is mirrored into the legacy `ai*` columns for back-compat. + +## TODO (verify before relying on) + +- Exact `make` target set beyond `x86` (Makefile sets `ARCHES := x86`; `make install` sideloads — confirm host config). +- Whether `npm run db:seed` is needed in any current workflow (entrypoint handles seeding on the server). + +## Current state + +Latest version is **1.1.0:7** (built locally, installed on the StartOS server). The registry is currently **empty** — all versions were unpublished; nothing is downloadable until `publish.sh` runs again. + +Working: workout logging, programs (manual + AI), multi-user, curated library, full AI subsystem (5 providers, multi-config, background generation, history detail, cost/duration, Ollama auto-detect, infinite-scroll exercise history). + +In progress: none — repo is at a clean checkpoint. + +Decided but not implemented: tiered AI prompt formatting — JSON-Schema enforcement (Ollama `format` / OpenAI `response_format`), pipe-separated library, XML-tagged sections, Ollama-only few-shot. Targets local-model output quality; would ship as 1.1.0:8. + +Known issues: earlier commits (`8f149d3`–`5b0535f`) carry `Co-Authored-By` trailers to scrub from history. publish.sh Step 3 (registry register) silently no-op'd on 1.1.0:6 and :7 — uploaded the file but didn't register; investigate before relying on those versions appearing in the registry. + +Next steps: +1. Scrub `Co-Authored-By` trailers from history (filter-branch or rebase). +2. Re-publish current version once the Step-3 registry-register failure is diagnosed. +3. Implement the tiered AI prompt formatting (1.1.0:8). diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..61f4adb --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,25 @@ +# ROADMAP — Proof of Work + +Longer-term backlog. Near-term state + next steps live in `AGENTS.md` → Current state. + +## AI quality + +- Tiered prompt formatting (also the immediate next step): JSON-Schema output enforcement via Ollama `format` and OpenAI `response_format`; pipe-separated library rows; XML-tagged prompt sections; Ollama-only few-shot example; stable prefix first for prompt-cache hits. +- Keep `MODEL_MENU` / `PRICES` current as providers ship new models. + +## Packaging / distribution + +- Diagnose and fix the `publish.sh` Step-3 registry-register silent no-op. +- Build for `arm` / additional arches once StartOS 0.4 supports them on the host. +- Consider submission to the Start9 community registry (use the start9-spec-checker agent first). + +## Product + +- Adherence tracking: compare logged workouts against the planned `ProgramDay` (the `programDayId` link already exists). +- Per-user export/import polish and scheduled backups. +- Charts/progress views over history (the data and 1RM estimates already exist). + +## Hygiene + +- Scrub `Co-Authored-By` trailers from git history. +- Revisit `workout-planner/` scratch dir — remove if truly unused.