Skip to content

feat(lab2): course route with level navigation + MSW fixtures [2/4]#73488

Draft
stephenliang wants to merge 11 commits into
stephen/lab2-studio-oceans-pr1from
stephen/lab2-studio-oceans-pr2
Draft

feat(lab2): course route with level navigation + MSW fixtures [2/4]#73488
stephenliang wants to merge 11 commits into
stephen/lab2-studio-oceans-pr1from
stephen/lab2-studio-oceans-pr2

Conversation

@stephenliang

@stephenliang stephenliang commented Jun 25, 2026

Copy link
Copy Markdown
Member

Add /courses/:name/units/:u/lessons/:l/levels/:p route with permissive Zod schemas for script_structure and level_properties endpoints. Query-key cache reuse across in-lesson navigation. Position→activeId→levelId join (resolveCourseLevel), appName-keyed lab entrypoint resolver (fish→oceans, standalone_video→stub). Level navigation with prev/next links and live-region position indicator.

Lab2-studio-oceans tasks §3 (3.1–3.9). No Rails changes.

Stack: [1/4] #73487[2/4] ← this PR → [3/4] #73490 → [4/4] #73496

Links

  • Design: openspec/changes/lab2-studio-oceans/design.md (on proposal branch)

Testing story

  • Unit tests for resolveCourseLevel, getLabEntrypointByAppName, LevelNavigation
  • Integration test: in-lesson navigation reuses cache, shell not remounted
  • MSW fixtures for course-scoped endpoints
  • yarn typecheck + ./tools/hooks/pre-commit pass

Deployment notes

Standard merge-and-deploy. New route only activates when navigated to directly — no existing routes affected.

🤖 Generated with Claude Code

Spec-driven change for the Lab2 host/loader role in
frontend/apps/studio, with AI for Oceans as the first course:
proposal, design (decisions, data flow, test strategy), four
capability specs (lab-base, course-level-routes,
milestone-reporting, oceans-course), and TDD task list.

Committed for PR review only: openspec/ is normally untracked via
.git/info/exclude; files are force-added and the PR will be
discarded after review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@stephenliang stephenliang force-pushed the stephen/lab2-studio-oceans-pr1 branch from c53f1be to fe03c1f Compare June 25, 2026 23:54
@stephenliang stephenliang force-pushed the stephen/lab2-studio-oceans-pr2 branch from f8a31ad to 51feef7 Compare June 25, 2026 23:54
stephenliang and others added 9 commits June 25, 2026 19:54
Scaffold the labs/base package (@code-dot-org/lab) from wilkie's
music-lab prototype (frontend/packages/labs/music), adapted to
prop-driven levelId + map (no redux, no theme provider). Includes Lab
shell with ErrorBoundary, Loading, metrics reporter, and
LevelPropertiesContext. Wire into the existing oceans project route as
an integration proof. Add cross-package lint rule preventing oceans
from importing @code-dot-org/lab directly.

Lab2-studio-oceans tasks §1-2 (1.1–2.2).

Co-authored-by: wilkie <david.wilkinson@code.org>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ack, metrics attributes, dead code

Key fixes:
- Key ErrorBoundary on levelId so error state resets on level change
- Use static ERROR_MESSAGE constant for fallback to avoid stale-state capture
- Conditionally render alert region only when errorMessage is non-empty
- Fix defaultOnError signature to accept componentStack
- Remove dead isLoading prop from Loading
- Remove duplicate useMaybeLevelProperties (identical to useLevelProperties)
- Include all 4 metric dimensions in getCommonAttributes
- Remove redundant object spreads in metric methods
- Add tests for conditional alert and error recovery

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lert"

The separate errorMessage state and live-region div persisted a stale
alert after the ErrorBoundary recovered via key={levelId} remount.
Consolidate to a single <p role="alert"> as the ErrorBoundary fallback —
it unmounts with the boundary on recovery, eliminating the false
announcement. Also removes redundant aria-live/aria-atomic (implicit
on role="alert") and replaces getByTestId with getByText in recovery
test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverts accidental removal of comments that explain non-obvious behavior:
createFileRoute auto-wiring, lazy-load code-splitting, MSW fixture
registration coupling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds lint-config/eslint/lab.mjs extending react.mjs with a
no-restricted-imports rule preventing embeddable labs from depending on
the framework package. Updates oceans, music, ailab, and the lab codegen
template to use it. Verified via turbo gen lab smoke test. Also removes
openspec change files from this PR (they belong in the proposal branch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ntent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@stephenliang stephenliang force-pushed the stephen/lab2-studio-oceans-pr1 branch from a824702 to 5f9b09b Compare June 26, 2026 02:55
Add the /courses/:name/units/:u/lessons/:l/levels/:p route with:
- Permissive Zod schemas for script_structure and level_properties
  endpoints (passthrough for unknown serializer fields)
- Query key factory excluding levelPosition for in-lesson cache reuse
- Position→activeId→levelId join (resolveCourseLevel)
- AppName-keyed lab entrypoint resolver (fish→oceans, standalone_video→stub)
- Level navigation with prev/next links, live-region position indicator
- MSW fixtures captured from production for all 8 oceans levels
- Signed-out auth stub in enableMocks for standalone MSW mode
- A11y: aria-live position announcements, label-in-name buttons,
  correct heading hierarchy on fallback states

Lab2-studio-oceans tasks §3 (3.1–3.9).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@stephenliang stephenliang force-pushed the stephen/lab2-studio-oceans-pr2 branch from 51feef7 to fd5b25d Compare June 26, 2026 02:56
@stephenliang stephenliang force-pushed the stephen/lab2-studio-oceans-pr1 branch 2 times, most recently from d4629d0 to 3a12612 Compare June 29, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant