docs: v1.1 plan (motion, studio import editing, perf, AI schema)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-30 20:21:39 +01:00
co-authored by Claude Opus 5.5
parent 58e0b20c95
commit fd5c72afc2
+92
View File
@@ -0,0 +1,92 @@
# STCourses v1.1 Plan
> **For agentic workers:** each work package below is owned by one agent in its own git worktree (branch `feat/v11-<id>`, created from `main`). The agent writes its own detailed TDD plan at `docs/superpowers/plans/2026-10-30-v11-<id>.md` in the format of `docs/superpowers/plans/2026-10-30-stcourses.md`, then executes it. Spec: `docs/superpowers/specs/2026-10-30-stcourses-design.md`. Project rules: `CLAUDE.md`.
**Goal:** five improvements to v1:
- navigation motion (from user feedback);
- editing imported courses in the studio;
- a smaller first load;
- the deferred AI schema work;
- cleaning up stale dev scripts.
## Global Constraints
- Everything in `CLAUDE.md` "Project rules" applies.
- Motion:
- only light, purposeful motion: 120–220 ms, ease-out;
- opacity and short (≤ 8 px) translate only;
- no bounce, no scale-pop, no parallax;
- `prefers-reduced-motion: reduce` turns all of it off;
- motion must never delay input or block navigation.
- No new colours or fonts.
- Every DB change is a new portable migration that runs on SQLite and Postgres.
- Every change keeps `bun test`, `bun run typecheck` and the Postgres run green.
## Work packages
### M — Navigation motion (branch `feat/v11-motion`)
User feedback: "the navigation between courses, pages and steps could need some light animations and not switch as hard."
Scope:
- route changes in the shell;
- library to course;
- lesson to lesson, including previous/next and the floating action bar;
- module expand/collapse in the sidebar;
- deck slide changes;
- hint/fold open/close;
- progress bar fills;
- toasts and overlays.
Approach:
- Use the View Transitions API (`document.startViewTransition`) where the browser supports it, with a CSS-only fallback (a fade-in of the new content).
- Keep the sidebar and header stable during lesson changes, so they don't flash. Only the lesson column transitions.
- Restore scroll position correctly.
- Lesson content should appear as a quick fade plus a 4–6 px rise.
- `<details>` folds animate their height with the `interpolate-size` / `::details-content` pattern where supported, and open instantly otherwise.
Acceptance:
- headless-Chrome screenshots or recordings of mid-transition frames;
- no layout shift of the sidebar;
- a reduced-motion test shows no animation;
- no added JS dependency over 5 KB.
### S — Edit imported courses in the studio (branch `feat/v11-studio-import`)
Resolves the v1 TODO `TODO(studio): convert imported course to a studio-managed repo` (ruling R9).
Scope:
- Add an owner-only action, "Make editable in the studio", for imported courses under `<dataDir>/courses/<id>`.
- It creates `<dataDir>/studio/repos/<id>.git` from the course folder.
- Large media are NOT committed into git: they stay referenced in place, and the manifest paths keep working.
- Use `.gitignore` plus a media reference, or Git LFS only if it's already available. Document the choice.
- After conversion the course is served from the studio's published worktree. The original import folder is kept read-only as the media source, or moved under `<dataDir>/media/<id>`; pick one and document it.
- The id stays the same, so learners' progress and notes are kept.
- Visibility stays restricted until the owner changes it.
Acceptance: convert a synthetic imported course, edit a lesson title, publish, and confirm the learner sees the change, existing progress and notes survive, and media still play with Range requests.
### P — Smaller first load plus cleanup (branch `feat/v11-perf`)
v1 ships one JS file of about 1.8 MB plus 1.47 MB of CSS and fonts.
Scope:
- Code-split per feature route (lazy chunks for studio, import, AI and admin; the learner reader and library stay in the main chunk).
- Load the heavy libraries only where they are used:
- pdf.js only in the deck viewer;
- sanitize-html only where lesson HTML is rendered.
- Fonts: latin plus latin-ext subsets only, `font-display: swap`, and only the weights actually used.
- Long-cache headers for hashed assets in production.
Targets for the initial library page in a production build: at most 600 KB of JS gzip, and at most 350 KB of fonts and CSS. Measure and report before and after.
Cleanup:
- remove or update the stale per-package dev scripts (`packages/*/dev/serve.ts`, `scripts/dev.ts`), now superseded by `apps/server`;
- update READMEs and `docs/operations.md`.
### A — Deferred AI contract requests 3–5 (branch `feat/v11-ai`)
From `docs/contract-requests/ai.md`:
- (3) Tool calls as structured fields on `ChatMessage`, with providers updated (Anthropic tool_use/tool_result blocks, OpenAI tool_calls).
- (4) A per-course mentor setting stored in its own table instead of the generic `ai_settings` JSON. Migrate existing rows.
- (5) A citations column on `ai_messages`, so the UI renders citations from data rather than re-parsing text.
New migrations go in the AI package's migrations directory and must run on both DBs, with an upgrade test from the v1 schema. Also encrypt MCP `env`/`headers` at rest with the same AES-GCM/HKDF scheme as BYOK keys, never returning them in full to the UI (only masked). This was a v1 deferred minor.
## Order
M, S and A run in parallel. P starts after M is merged, because both touch the web shell and bundling. Each package gets a task review (and fix rounds) before merging, and a final whole-branch review runs on `main` at the end.