feat(content-lint): reusable Feldenkrais content-lint module (automated principle gate) #58

Open
KnallerKalle wants to merge 2 commits from feat/lesson-content-lint into dev
KnallerKalle commented 2026-08-12 22:25:08 +00:00 (Migrated from github.com)

Plan

Convert the Feldenkrais sacred principles (no correction/judgement, no strain, quality over quantity, the lesson is never "finished") from human-review-only into an automated, reusable content gate — so any lesson-content pipeline (seed lessons, AI-generated lessons, practitioner-authored content) can be machine-checked against the ATM domain "Common content errors to reject".

Outcome

Added src/lib/lesson-content-lint.ts — a pure, bilingual (DE/EN) linter exposing lintLessonText() / lintLesson() returning structured {rule, severity, message, evidence} findings. Seven rules map 1:1 to documented bad→good reframes:

rule flags reframe
timed-hold "Hold the position for 30 seconds." "stay as long as it is comfortable; rest whenever"
effort-strain "push", "try harder", "reach further" gravity-allied, reversible cues: "let the knee fall outward"
judgement "Good! Now…", "the right/wrong way" neutral noticing — drop "good"/"right"/"wrong"
scoring "rate out of 10" neutral reflection prompt
lesson-finished "You have completed the lesson", "Well done!" open-ended checkpoint ("the exploration continues")
prescription "You should feel a stretch" "Notice what you feel."
missing-rest-option (structural) a full lesson with no rest/comfort language rest must be a first-class, encouraged option

17 new unit tests prove each rule rejects the bad cue and accepts the reframed cue; a principle-compliant passage yields zero findings.

Impact on release goals

Release Hardening → new item "Feldenkrais principle gate (content lint in CI)" delivered [x]. The non-negotiables are now enforceable automatically across all content pipelines — directly de-risking the Phase-3 AI-generation roadmap item ("AI generation produces poor lessons" is the #1 Critical risk in the roadmap Risk Register) and every future launch lesson. This is the foundation for a CI step that blocks principle-violating content before it reaches users.

Blackbox

  • python3 scripts/blackbox_test.py --target testing → 11/12 (unchanged — additive only; no endpoint or runner touched)
  • Unit suite 97/97 green (was 80, +17 new content-lint tests); tsc --noEmit clean.
  • The single remaining blackbox red (GET /api/lessons) is the pre-existing blocker that PR #53 resolves (human merge), not a regression from this iteration.

Six-perspectives check

  • Product: amplifies the felt-change promise by guaranteeing no strain/judgement language ships; reusable across every content pipeline.
  • Engineering: minimal diff (2 new files), pure functions (no I/O), TDD red→green, full suite green, tsc clean, no existing route/component/test changed.
  • Psychology: autonomy-supportive — the missing-rest-option rule enforces rest is always offered; rejects scoring/strain that would damage intrinsic motivation.
  • Biomechanics: effort-strain rule specifically reframes effort cues toward gravity-allied, reversible movement.
  • Anatomy: guards against prescription ("you should feel a stretch") that predicts sensation unsafely.
  • Feldenkrais: directly encodes the sacred non-negotiables — no correction/judgement, no strain, quality over quantity, the lesson is never "finished".

Risk

Low. Additive only — two new files; no existing route, component, or test modified. The lint is pure (no I/O), safe to call from API routes, build steps, or tests. Detection is conservative and word-boundary aware to avoid over-matching neutral language (verified by the negative test cases). No file conflict with open PRs #52–#57 (different files; only .development/* docs overlap, which all PRs touch).

Checklist

  • Branch off latest dev (a167f28)
  • Conventional Commits (feat(content-lint):, docs:)
  • Patchlog entry appended (.development/patchlog.md)
  • Roadmap status updated (.development/roadmap.md)
  • No secrets / no large binaries
  • No Feldenkrais-principle violation (this PR enforces them)

This PR was created by an AI agent (OpenHands) on behalf of the ATM development automation. No merge performed — human review and merge, per workflow.

## Plan Convert the Feldenkrais sacred principles (no correction/judgement, no strain, quality over quantity, the lesson is never "finished") from **human-review-only** into an **automated, reusable content gate** — so any lesson-content pipeline (seed lessons, AI-generated lessons, practitioner-authored content) can be machine-checked against the ATM domain "Common content errors to reject". ## Outcome Added `src/lib/lesson-content-lint.ts` — a pure, bilingual (DE/EN) linter exposing `lintLessonText()` / `lintLesson()` returning structured `{rule, severity, message, evidence}` findings. Seven rules map 1:1 to documented bad→good reframes: | rule | flags | reframe | |---|---|---| | `timed-hold` | "Hold the position for 30 seconds." | "stay as long as it is comfortable; rest whenever" | | `effort-strain` | "push", "try harder", "reach further" | gravity-allied, reversible cues: "let the knee fall outward" | | `judgement` | "Good! Now…", "the right/wrong way" | neutral noticing — drop "good"/"right"/"wrong" | | `scoring` | "rate out of 10" | neutral reflection prompt | | `lesson-finished` | "You have completed the lesson", "Well done!" | open-ended checkpoint ("the exploration continues") | | `prescription` | "You should feel a stretch" | "Notice what you feel." | | `missing-rest-option` (structural) | a full lesson with no rest/comfort language | rest must be a first-class, encouraged option | 17 new unit tests prove each rule **rejects** the bad cue and **accepts** the reframed cue; a principle-compliant passage yields zero findings. ## Impact on release goals Release Hardening → new item **"Feldenkrais principle gate (content lint in CI)"** delivered `[x]`. The non-negotiables are now enforceable automatically across all content pipelines — directly de-risking the Phase-3 AI-generation roadmap item ("AI generation produces poor lessons" is the #1 Critical risk in the roadmap Risk Register) and every future launch lesson. This is the foundation for a CI step that blocks principle-violating content before it reaches users. ## Blackbox - [x] `python3 scripts/blackbox_test.py --target testing` → **11/12** (unchanged — additive only; no endpoint or runner touched) - Unit suite **97/97 green** (was 80, +17 new content-lint tests); `tsc --noEmit` clean. - The single remaining blackbox red (`GET /api/lessons`) is the **pre-existing blocker that PR #53 resolves** (human merge), not a regression from this iteration. ## Six-perspectives check - [x] **Product:** amplifies the felt-change promise by guaranteeing no strain/judgement language ships; reusable across every content pipeline. - [x] **Engineering:** minimal diff (2 new files), pure functions (no I/O), TDD red→green, full suite green, tsc clean, no existing route/component/test changed. - [x] **Psychology:** autonomy-supportive — the `missing-rest-option` rule enforces rest is always offered; rejects scoring/strain that would damage intrinsic motivation. - [x] **Biomechanics:** `effort-strain` rule specifically reframes effort cues toward gravity-allied, reversible movement. - [x] **Anatomy:** guards against prescription ("you should feel a stretch") that predicts sensation unsafely. - [x] **Feldenkrais:** directly encodes the sacred non-negotiables — no correction/judgement, no strain, quality over quantity, the lesson is never "finished". ## Risk **Low.** Additive only — two new files; no existing route, component, or test modified. The lint is pure (no I/O), safe to call from API routes, build steps, or tests. Detection is conservative and word-boundary aware to avoid over-matching neutral language (verified by the negative test cases). No file conflict with open PRs #52–#57 (different files; only `.development/*` docs overlap, which all PRs touch). ## Checklist - [x] Branch off latest `dev` (`a167f28`) - [x] Conventional Commits (`feat(content-lint):`, `docs:`) - [x] Patchlog entry appended (`.development/patchlog.md`) - [x] Roadmap status updated (`.development/roadmap.md`) - [x] No secrets / no large binaries - [x] No Feldenkrais-principle violation (this PR *enforces* them) --- _This PR was created by an AI agent (OpenHands) on behalf of the ATM development automation. No merge performed — human review and merge, per workflow._
This pull request has changes conflicting with the target branch.
  • .development/automation-state.json
  • .development/patchlog.md
  • .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/lesson-content-lint:feat/lesson-content-lint
git switch feat/lesson-content-lint

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/lesson-content-lint
git switch feat/lesson-content-lint
git rebase dev
git switch dev
git merge --ff-only feat/lesson-content-lint
git switch feat/lesson-content-lint
git rebase dev
git switch dev
git merge --no-ff feat/lesson-content-lint
git switch dev
git merge --squash feat/lesson-content-lint
git switch dev
git merge --ff-only feat/lesson-content-lint
git switch dev
git merge feat/lesson-content-lint
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!58
No description provided.