Files
STCourses/docs/superpowers/plans/2026-10-30-v1-1.md
T

5.3 KiB
Raw Blame History

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.