feat(catalog): serve the public catalog in the authored onboarding arc (L1→L8) #83

Open
KnallerKalle wants to merge 5 commits from feat/catalog-onboarding-arc into dev
KnallerKalle commented 2026-08-15 16:35:35 +00:00 (Migrated from github.com)

Plan

Make GET /api/lessons (the documented unauthenticated discovery entry point) serve the authored onboarding arc oldest-first (L1→L8) instead of newest-first, so a first-time visitor's first impression is the introduction lesson, not the integration lesson.

Outcome

getPublicCatalog() now sorts oldest-first in src/lib/lessons-catalog.ts (the seed lessons encode the arc in created_at: L1 2026-01-01 → L8 2026-01-08). The obsolete "newest-first" unit test was replaced with arc assertions (first = l1-introduction-to-awareness, last = l8-walking-awareness).

Coverage gap found and closed: the public catalog had zero blackbox coverage — the suite only exercised the teacher view /api/lessons/list. Added blackbox tests 2d/2e/2f/2g: reachability, non-emptiness, L1-leads, full arc order.

Blackbox 16b made idempotent (separate test: commit with justification): 16b asserted "all pre-existing lessons survive" with a sentinel set that included the previous run's copy of the byte-identical test PDF — which the endpoint legitimately replaces (exactly the behaviour 16d asserts). It therefore failed on every second run. Verified on testing: the missing UUID differed between runs (f9ec55cf… then b4a419fb…) while real library content was untouched — proof the victim was per-run residue, not a destructive-import P0. 16b now excludes only the test document's own copies ("Lektion 777" marker) from its sentinel set; seeds, the Yanai collection and teacher lessons remain fully guarded.

Impact on release goals

  • Closes the last [~] Core Platform item → Core Platform 5/5 COMPLETE. With Launch Lessons 8/8 already merged, the authored arc is now both complete and presented in teaching order.
  • The catalog opens on L1 "Einführung in die Wahrnehmung" — the authored first step — directly serving the D1 retention goal (clean, low-friction first lesson being the most visible thing in the app).
  • Blackbox coverage of the public discovery endpoint: 0 → 4 assertions; the suite is now idempotent (51 checks) and its 16-family destructive-import guard is precise instead of noisy (a genuine regression would now stand out).

Blackbox

  • python3 scripts/blackbox_test.py --target testing
  • Result: 49/51 pass — the only failures are 2f/2g, red by design on dev (testing deploys dev, which is still newest-first: first='l8-walking-awareness', order=['l8'…'l1']). They are the new assertions this PR exists to satisfy.
  • In-branch verification (local prod build): 2d–2g green, with a control run on clean dev showing the 9 locally non-servable checks (DB-seed/AI-backend paths) fail identically on both — i.e. no regression from this change.
  • Unit: 218/218 across 24 files; tsc --noEmit exit 0. TDD discipline held: RED confirmed before implementation (2 unit failures for the correct reason; 2f/2g red on testing).
  • 16b verified green on two consecutive testing runs.
  • After human merge → dev deploy, please re-run --target testing and confirm 2f/2g flip to green (51/51).

Six-perspectives check

  • Product: the discovery page now leads with the share-worthy entry point (the felt "Aha" of the first lesson) instead of burying it; no dark patterns.
  • Engineering: two-line semantic change (sort direction) behind a now-complete test surface; minimal diff; conventional commits; RED→GREEN.
  • Psychology: autonomy-supportive — the arc invites (perception first, integration last) rather than controls; no streak/pressure framing introduced.
  • Biomechanics: teaching order matches the method's differentiation-then-integration structure (L8 integrates the anchors of L1–L7).
  • Anatomy: no content change; lesson text untouched.
  • Feldenkrais: no correction/judgement language added; the arc presents an open invitation, never a curriculum to complete.

Risk

Low. A sort-direction flip on a read path, covered by unit + blackbox assertions. Teacher-facing /api/lessons/list is intentionally unchanged (its UI exposes a user-controlled sort, so recency stays the sensible default there). Related open PR #76 (stable lesson ids on re-import) edits the same file's test-16 block — trivially rebasable, either merge order works.

Checklist

  • Branch off latest dev (ea812cd)
  • Conventional Commits
  • Patchlog entry appended
  • Roadmap status updated
  • No secrets / no large binaries

This PR was created by an AI agent (OpenHands) on behalf of the ATM maintainers. Human merge required.

## Plan Make `GET /api/lessons` (the documented unauthenticated discovery entry point) serve the authored onboarding arc oldest-first (L1→L8) instead of newest-first, so a first-time visitor's first impression is the introduction lesson, not the integration lesson. ## Outcome `getPublicCatalog()` now sorts oldest-first in `src/lib/lessons-catalog.ts` (the seed lessons encode the arc in `created_at`: L1 2026-01-01 → L8 2026-01-08). The obsolete "newest-first" unit test was replaced with arc assertions (first = `l1-introduction-to-awareness`, last = `l8-walking-awareness`). **Coverage gap found and closed:** the public catalog had **zero** blackbox coverage — the suite only exercised the teacher view `/api/lessons/list`. Added blackbox tests **2d/2e/2f/2g**: reachability, non-emptiness, L1-leads, full arc order. **Blackbox 16b made idempotent (separate `test:` commit with justification):** 16b asserted "all pre-existing lessons survive" with a sentinel set that included the *previous run's* copy of the byte-identical test PDF — which the endpoint legitimately replaces (exactly the behaviour 16d asserts). It therefore failed on every second run. Verified on testing: the missing UUID differed between runs (`f9ec55cf…` then `b4a419fb…`) while real library content was untouched — proof the victim was per-run residue, not a destructive-import P0. 16b now excludes only the test document's own copies ("Lektion 777" marker) from its sentinel set; seeds, the Yanai collection and teacher lessons remain fully guarded. ## Impact on release goals - **Closes the last `[~]` Core Platform item → Core Platform 5/5 COMPLETE.** With Launch Lessons 8/8 already merged, the authored arc is now both complete *and* presented in teaching order. - The catalog opens on **L1 "Einführung in die Wahrnehmung"** — the authored first step — directly serving the D1 retention goal (clean, low-friction first lesson being the most visible thing in the app). - Blackbox coverage of the public discovery endpoint: **0 → 4 assertions**; the suite is now idempotent (51 checks) and its 16-family destructive-import guard is precise instead of noisy (a genuine regression would now stand out). ## Blackbox - [x] `python3 scripts/blackbox_test.py --target testing` - Result: **49/51 pass** — the only failures are **2f/2g, red by design on `dev`** (testing deploys `dev`, which is still newest-first: `first='l8-walking-awareness'`, `order=['l8'…'l1']`). They are the new assertions this PR exists to satisfy. - **In-branch verification (local prod build): 2d–2g green**, with a control run on clean `dev` showing the 9 locally non-servable checks (DB-seed/AI-backend paths) fail **identically on both** — i.e. no regression from this change. - Unit: **218/218 across 24 files**; `tsc --noEmit` exit 0. TDD discipline held: RED confirmed before implementation (2 unit failures for the correct reason; 2f/2g red on testing). - 16b verified green on **two consecutive** testing runs. - After human merge → dev deploy, please re-run `--target testing` and confirm 2f/2g flip to green (51/51). ## Six-perspectives check - [x] **Product:** the discovery page now leads with the share-worthy entry point (the felt "Aha" of the first lesson) instead of burying it; no dark patterns. - [x] **Engineering:** two-line semantic change (sort direction) behind a now-complete test surface; minimal diff; conventional commits; RED→GREEN. - [x] **Psychology:** autonomy-supportive — the arc invites (perception first, integration last) rather than controls; no streak/pressure framing introduced. - [x] **Biomechanics:** teaching order matches the method's differentiation-then-integration structure (L8 integrates the anchors of L1–L7). - [x] **Anatomy:** no content change; lesson text untouched. - [x] **Feldenkrais:** no correction/judgement language added; the arc presents an open invitation, never a curriculum to complete. ## Risk Low. A sort-direction flip on a read path, covered by unit + blackbox assertions. Teacher-facing `/api/lessons/list` is intentionally unchanged (its UI exposes a user-controlled sort, so recency stays the sensible default there). **Related open PR #76** (stable lesson ids on re-import) edits the same file's test-16 block — trivially rebasable, either merge order works. ## Checklist - [x] Branch off latest `dev` (ea812cd) - [x] Conventional Commits - [x] Patchlog entry appended - [x] Roadmap status updated - [x] No secrets / no large binaries --- *This PR was created by an AI agent (OpenHands) on behalf of the ATM maintainers. Human merge required.*
This pull request has changes conflicting with the target branch.
  • .development/automation-state.json
  • .development/roadmap.md
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/catalog-onboarding-arc:feat/catalog-onboarding-arc
git switch feat/catalog-onboarding-arc

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feat/catalog-onboarding-arc
git switch feat/catalog-onboarding-arc
git rebase dev
git switch dev
git merge --ff-only feat/catalog-onboarding-arc
git switch feat/catalog-onboarding-arc
git rebase dev
git switch dev
git merge --no-ff feat/catalog-onboarding-arc
git switch dev
git merge --squash feat/catalog-onboarding-arc
git switch dev
git merge --ff-only feat/catalog-onboarding-arc
git switch dev
git merge feat/catalog-onboarding-arc
git push origin dev
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Kalle/ATM!83
No description provided.