@lernapps/tooling 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +67 -2
  3. package/archetypes/shared/a11y.ts +38 -0
  4. package/archetypes/shared/hooks/pre-commit +22 -0
  5. package/archetypes/shared/hooks/pre-push +4 -0
  6. package/archetypes/shared/i18n.ts +25 -0
  7. package/archetypes/shared/install-hooks.ts +63 -0
  8. package/archetypes/shared/playwright.ts +54 -0
  9. package/archetypes/shared/preset.ts +81 -0
  10. package/archetypes/shared/storage.ts +167 -0
  11. package/archetypes/shared/tsconfig.json +27 -0
  12. package/check/validation-report.v1.schema.json +116 -0
  13. package/dist/a11y.mjs +30 -0
  14. package/dist/check/rules/accessible.mjs +18 -0
  15. package/dist/check/rules/app-content-guide.mjs +69 -0
  16. package/dist/check/rules/dependency-licence.mjs +82 -0
  17. package/dist/check/rules/entry-fitness-matches.mjs +22 -0
  18. package/dist/check/rules/entry-links-resolve.mjs +44 -0
  19. package/dist/check/rules/explainer-readable-without-js.mjs +66 -0
  20. package/dist/check/rules/links-resolve.mjs +10 -0
  21. package/dist/check/rules/lockfile-matches.mjs +57 -0
  22. package/dist/check/rules/no-request-before-click.mjs +17 -0
  23. package/dist/check/rules/no-tracking.mjs +17 -0
  24. package/dist/check/rules/own-data-only.mjs +66 -0
  25. package/dist/check/rules/pages-reachable.mjs +25 -0
  26. package/dist/check/rules/usable-at-360px.mjs +19 -0
  27. package/dist/check-cv4I6CCH.mjs +28 -0
  28. package/dist/cli.mjs +3118 -0
  29. package/dist/i18n.mjs +11 -0
  30. package/dist/lint.mjs +528 -0
  31. package/dist/plan-DWKayEnY.mjs +75 -0
  32. package/dist/playwright.mjs +47 -0
  33. package/dist/preset.mjs +60 -0
  34. package/dist/skills/lernapps-app/SKILL.md +49 -0
  35. package/dist/skills/lernapps-cli/SKILL.md +156 -0
  36. package/dist/skills/lernapps-cli/references/platform-rules.md +258 -0
  37. package/dist/skills/lernapps-commit/SKILL.md +39 -0
  38. package/dist/skills/lernapps-content-growth/SKILL.md +33 -0
  39. package/dist/skills/lernapps-content-questions/SKILL.md +133 -0
  40. package/dist/skills/lernapps-content-questions/references/question-types.md +69 -0
  41. package/dist/skills/lernapps-content-research/SKILL.md +50 -0
  42. package/dist/skills/lernapps-content-research/references/sources.md +16 -0
  43. package/dist/skills/lernapps-exercise-patterns/SKILL.md +74 -0
  44. package/dist/skills/lernapps-exercise-patterns/references/biology-geography.md +13 -0
  45. package/dist/skills/lernapps-exercise-patterns/references/chemistry.md +16 -0
  46. package/dist/skills/lernapps-exercise-patterns/references/computer-science.md +13 -0
  47. package/dist/skills/lernapps-exercise-patterns/references/figures.md +10 -0
  48. package/dist/skills/lernapps-exercise-patterns/references/history.md +13 -0
  49. package/dist/skills/lernapps-exercise-patterns/references/mathematics.md +19 -0
  50. package/dist/skills/lernapps-exercise-patterns/references/page-structures.md +8 -0
  51. package/dist/skills/lernapps-exercise-patterns/references/physics.md +18 -0
  52. package/dist/skills/lernapps-exercise-patterns/references/success.md +28 -0
  53. package/dist/skills/lernapps-explainer/SKILL.md +33 -0
  54. package/dist/skills/lernapps-explainer/references/blocks.md +83 -0
  55. package/dist/skills/lernapps-explainer/references/components.md +66 -0
  56. package/dist/skills/lernapps-explainer/references/exercises.md +115 -0
  57. package/dist/skills/lernapps-explainer/references/rules.md +285 -0
  58. package/dist/skills/lernapps-explainer/references/runtime.md +79 -0
  59. package/dist/skills/lernapps-explainer/references/structure.md +24 -0
  60. package/dist/skills/lernapps-explainer-design/SKILL.md +57 -0
  61. package/dist/skills/lernapps-explainer-design/references/rules.md +75 -0
  62. package/dist/skills/lernapps-explainer-self-assessment/SKILL.md +93 -0
  63. package/dist/skills/lernapps-github/SKILL.md +102 -0
  64. package/dist/skills/lernapps-interactive/SKILL.md +141 -0
  65. package/dist/skills/lernapps-interactive/references/frame.md +30 -0
  66. package/dist/skills/lernapps-interactive-design/SKILL.md +58 -0
  67. package/dist/skills/lernapps-listing/SKILL.md +44 -0
  68. package/dist/skills/lernapps-listing/references/keeping-updated.md +33 -0
  69. package/dist/skills/lernapps-quiz/SKILL.md +100 -0
  70. package/dist/skills/lernapps-quiz-design/SKILL.md +48 -0
  71. package/dist/status-CXoQBgfU.mjs +76 -0
  72. package/dist/storage.mjs +113 -0
  73. package/generator/app/.agents/skills/app-content/SKILL.md +63 -0
  74. package/generator/app/.github/ISSUE_TEMPLATE/inhaltsfehler.yml +25 -0
  75. package/generator/app/.github/workflows/pages.yml +61 -0
  76. package/generator/app/LICENSE +21 -0
  77. package/generator/app/renovate.json +4 -0
  78. package/generator/architecture.ts +212 -0
  79. package/generator/create.ts +462 -0
  80. package/generator/init.ts +186 -0
  81. package/generator/update.ts +429 -0
  82. package/guidance/AGENTS.md +26 -0
  83. package/guidance/increment-template.md +194 -0
  84. package/guidance/plan-front-matter.v1.schema.json +36 -0
  85. package/guidance/plan-template.md +233 -0
  86. package/guidance/subagent-brief.md +25 -0
  87. package/guidance/workflow-rules.md +109 -0
  88. package/package.json +133 -4
  89. package/review/verdict.v1.schema.json +134 -0
  90. package/skills/archetypes/lernapps-explainer/SKILL.md +33 -0
  91. package/skills/archetypes/lernapps-explainer/references/blocks.md +83 -0
  92. package/skills/archetypes/lernapps-explainer/references/components.md +66 -0
  93. package/skills/archetypes/lernapps-explainer/references/exercises.md +115 -0
  94. package/skills/archetypes/lernapps-explainer/references/rules.md +285 -0
  95. package/skills/archetypes/lernapps-explainer/references/runtime.md +79 -0
  96. package/skills/archetypes/lernapps-explainer/references/structure.md +24 -0
  97. package/skills/archetypes/lernapps-explainer-design/SKILL.md +57 -0
  98. package/skills/archetypes/lernapps-explainer-design/references/rules.md +75 -0
  99. package/skills/archetypes/lernapps-explainer-self-assessment/SKILL.md +93 -0
  100. package/skills/archetypes/lernapps-interactive/SKILL.md +141 -0
  101. package/skills/archetypes/lernapps-interactive/references/frame.md +30 -0
  102. package/skills/archetypes/lernapps-interactive-design/SKILL.md +58 -0
  103. package/skills/archetypes/lernapps-quiz/SKILL.md +100 -0
  104. package/skills/archetypes/lernapps-quiz-design/SKILL.md +48 -0
  105. package/skills/content/lernapps-content-questions/SKILL.md +133 -0
  106. package/skills/content/lernapps-content-questions/references/question-types.md +69 -0
  107. package/skills/content/lernapps-content-research/SKILL.md +50 -0
  108. package/skills/content/lernapps-content-research/references/sources.md +16 -0
  109. package/skills/content/lernapps-exercise-patterns/SKILL.md +74 -0
  110. package/skills/content/lernapps-exercise-patterns/references/biology-geography.md +13 -0
  111. package/skills/content/lernapps-exercise-patterns/references/chemistry.md +16 -0
  112. package/skills/content/lernapps-exercise-patterns/references/computer-science.md +13 -0
  113. package/skills/content/lernapps-exercise-patterns/references/figures.md +10 -0
  114. package/skills/content/lernapps-exercise-patterns/references/history.md +13 -0
  115. package/skills/content/lernapps-exercise-patterns/references/mathematics.md +19 -0
  116. package/skills/content/lernapps-exercise-patterns/references/page-structures.md +8 -0
  117. package/skills/content/lernapps-exercise-patterns/references/physics.md +18 -0
  118. package/skills/content/lernapps-exercise-patterns/references/success.md +28 -0
  119. package/skills/process/lernapps-app/SKILL.md +49 -0
  120. package/skills/process/lernapps-commit/SKILL.md +39 -0
  121. package/skills/process/lernapps-content-growth/SKILL.md +33 -0
  122. package/skills/process/lernapps-github/SKILL.md +102 -0
  123. package/skills/process/lernapps-listing/SKILL.md +44 -0
  124. package/skills/process/lernapps-listing/references/keeping-updated.md +33 -0
  125. package/skills/tooling/lernapps-cli/SKILL.md +156 -0
  126. package/skills/tooling/lernapps-cli/references/platform-rules.md +258 -0
@@ -0,0 +1,285 @@
1
+ # Explainer rules
2
+
3
+ - Quiz-type exercises: the rules of skill `lernapps-content-questions`.
4
+ - The rules for planning pages, figures and numbers: skill `lernapps-explainer-design`.
5
+
6
+ ## `explainer-only-content`: Write only the content
7
+
8
+ ```rule
9
+ id: explainer-only-content
10
+ scope: archetype:explainer
11
+ severity: error
12
+ ```
13
+
14
+ - Write: YAML of app, chapters, pages, data; images in `src/images/`; components with logic and tests in
15
+ `src/components/`.
16
+ - `src/main.ts`, `index.html`, `e2e/explainer.e2e.ts`, config as generated (`keep-the-preset`). Any other file in
17
+ `src/` fails the build.
18
+ - Not expressible → "Where I had to guess", never code around the runtime.
19
+
20
+ ## `explainer-content-valid`: The content validates
21
+
22
+ ```rule
23
+ id: explainer-content-valid
24
+ scope: archetype:explainer
25
+ severity: error
26
+ ```
27
+
28
+ - Schema-valid; ids unique per level; references exist (data file, image, component, page or section link);
29
+ placeholders declared; formulas only from the command list.
30
+ - Build names each problem with file, line, block path.
31
+
32
+ ## `explainer-structure-complete`: Every chapter and page listed once
33
+
34
+ ```rule
35
+ id: explainer-structure-complete
36
+ scope: archetype:explainer
37
+ severity: error
38
+ ```
39
+
40
+ - At least one chapter.
41
+ - Every chapter folder in `chapters` of `src/app.yaml`, every page file in `pages` of its `chapter.yaml`, exactly
42
+ once, in reading order.
43
+
44
+ ## `explainer-structure-depth`: Chapter, page, two section levels
45
+
46
+ ```rule
47
+ id: explainer-structure-depth
48
+ scope: archetype:explainer
49
+ severity: error
50
+ ```
51
+
52
+ - Sections at most two deep. No heading levels set: they follow from nesting. More levels = two apps.
53
+
54
+ ## `explainer-structure-by-sections`: Structure only by sections
55
+
56
+ ```rule
57
+ id: explainer-structure-by-sections
58
+ scope: archetype:explainer
59
+ severity: error
60
+ ```
61
+
62
+ - Every heading = a `section` block with `id`, `title`.
63
+ - A Markdown heading (`#`, `##`, underlined) in a text fails the build.
64
+
65
+ ## `explainer-stable-ids`: Keep the ids
66
+
67
+ ```rule
68
+ id: explainer-stable-ids
69
+ scope: archetype:explainer
70
+ severity: warning
71
+ ```
72
+
73
+ - Short, telling ids ("prozentwert", "regel") for chapters, pages, sections, exercises; keep them when texts
74
+ change (entry topics, teachers' links).
75
+ - New content, new ids; never reuse a removed one.
76
+
77
+ ## `explainer-navigation`: Every page in one chain
78
+
79
+ ```rule
80
+ id: explainer-navigation
81
+ scope: archetype:explainer
82
+ severity: error
83
+ ```
84
+
85
+ - Navigation is the runtime's: from the order lists; every page in one chain, reachable from the start page.
86
+ - Prose links: paths from the app root.
87
+ - `lernapps check` finds unreachable pages (`pages-reachable`) and entry topics with a missing `#<section>`
88
+ (`entry-links-resolve`).
89
+
90
+ ## `explainer-languages`: German first, every language complete
91
+
92
+ ```rule
93
+ id: explainer-languages
94
+ scope: archetype:explainer
95
+ severity: error
96
+ ```
97
+
98
+ - `languages`, German first.
99
+ - Every learner text (content, data files, component props) in each, no other. Build fails otherwise.
100
+
101
+ ## `explainer-readable-without-js`: Every page readable without JavaScript
102
+
103
+ ```rule
104
+ id: explainer-readable-without-js
105
+ scope: archetype:explainer
106
+ severity: error
107
+ ```
108
+
109
+ - Every fact in a block, visible without JS. No meaning only inside an exercise or component.
110
+ - Every component a `nojs` text: what it shows, its content.
111
+ - `lernapps check` opens every explainer page again with JS off, bundle and deployed (listing and review too):
112
+ headings, formulas, figures visible, figures named; every "Lösung" and `nojs` text not empty.
113
+
114
+ ## `explainer-formulas-static`: Formulas as formulas
115
+
116
+ ```rule
117
+ id: explainer-formulas-static
118
+ scope: archetype:explainer
119
+ severity: error
120
+ ```
121
+
122
+ - Every formula in a `formula` block or `$…$`; never plain text (`W = G * p / 100`) or a picture. MathML for
123
+ screen readers.
124
+
125
+ ## `explainer-generated-sound`: The property test passes
126
+
127
+ ```rule
128
+ id: explainer-generated-sound
129
+ scope: archetype:explainer
130
+ severity: error
131
+ ```
132
+
133
+ - `given`, `where`: `where` holds often; answer defined and in format for every draw; no mistake can equal it.
134
+ - Failure names the seed: narrow `given` or change the mistake; never the comparator.
135
+
136
+ ## `vue-component-props-valid`: Props as the component declares them
137
+
138
+ ```rule
139
+ id: vue-component-props-valid
140
+ scope: archetype:explainer
141
+ severity: error
142
+ ```
143
+
144
+ - `defineProps<{ … }>()` with types; each block passes exactly the declared props, of their types.
145
+
146
+ ## `vue-component-nojs`: Every component block has its `nojs` text
147
+
148
+ ```rule
149
+ id: vue-component-nojs
150
+ scope: archetype:explainer
151
+ severity: error
152
+ ```
153
+
154
+ - Every non-exercise `vue-component` block: `nojs` in every language (exercise: from `describe`): what it shows
155
+ and does, with content; same meaning without JS.
156
+ - Schema requires it; `lernapps check` finds empty or hidden ones (`explainer-readable-without-js`).
157
+
158
+ ## `vue-component-exercise-contract`: An exercise component has its logic module
159
+
160
+ ```rule
161
+ id: vue-component-exercise-contract
162
+ scope: archetype:explainer
163
+ severity: error
164
+ ```
165
+
166
+ - Emits `answer` → `src/components/<Name>.ts` with pure, deterministic `generate(seed, props)`,
167
+ `check(task, answer)`, `solution(task)`, `wrong(task)`, `reason(task, answer, props, lang)`; property test passes.
168
+ - Emits no `answered` (the old contract): the explainer draws "Prüfen" and checks; a component draws none.
169
+ - Block lists `examples` with at least one `accepted` and one `rejected`, `{ answer, seed? }` in the shape of
170
+ `check` (no seed: seeds 1–50), incl. another correct answer where the text allows.
171
+ - Declares prop `seed: number`, shows `generate(seed, props)`. The explainer gives the seed, shows "Aufgabe Nr.",
172
+ "Neue Aufgabe", keeps `?<id>=<n>`: never draw a seed or offer "next" inside.
173
+ - Also exports `describe(task, props, lang)` → `{ task, solution }` (restricted Markdown, task exactly as shown) and
174
+ `about = { task, answer, correct, mistakes }` (texts by language). The tutor reads only these (the tutor page, no-JS
175
+ text).
176
+ - Any exercise may carry `examples: { accepted, rejected }`; `generated`: expressions of `given` and `answer`, per
177
+ seed (e.g. `reverse(answer)`).
178
+ - With `template`, `params`, `mistakes` and `show` (all four or none, rule `vue-component-tutor-table`): `check`
179
+ accepts the solution and rejects each mistake's answer, `params` gives the same names for every task, each
180
+ placeholder of `template` is one of them.
181
+
182
+ ## `vue-component-tutor-table`: An exercise component declares its exercise for the tutor
183
+
184
+ ```rule
185
+ id: vue-component-tutor-table
186
+ scope: archetype:explainer
187
+ severity: hint
188
+ ```
189
+
190
+ - The logic module also exports `template(props, lang)`: the task once, `{name}` for each input;
191
+ `params(task, props, lang)`: the inputs by name (`{ G: 1260, p: 15 }`), numbers or texts, the same names for every
192
+ task; `mistakes(task, props)`: per `about.mistakes`, in order, the answer it gives, `undefined` where none;
193
+ `show(answer, task, props, lang)`: an answer as text, short ("C", "3 Kästchen").
194
+ - The tutor page then has the task once, the mistakes as F1, F2 … and a table of every number (inputs, solution,
195
+ each mistake), like `generated`. Without them: each number's `describe` as far as 64 kB allow, and the build's hint
196
+ names the block.
197
+ - Example: `src/components/ProzentFeld.ts` of the template.
198
+
199
+ ## `vue-component-tested`: A test per component
200
+
201
+ ```rule
202
+ id: vue-component-tested
203
+ scope: archetype:explainer
204
+ severity: error
205
+ ```
206
+
207
+ - `src/components/<Name>.test.ts` per component, testing its logic: other right answers the text allows, typical
208
+ wrong ones with reasons, edge cases. Run by `lernapps check`.
209
+
210
+ ## `vue-component-no-network`: No network
211
+
212
+ ```rule
213
+ id: vue-component-no-network
214
+ scope: [archetype:explainer, archetype:interactive]
215
+ severity: error
216
+ ```
217
+
218
+ - No request, no URL import: props or bundle.
219
+
220
+ ## `vue-component-no-html-injection`: No code or HTML from strings
221
+
222
+ ```rule
223
+ id: vue-component-no-html-injection
224
+ scope: [archetype:explainer, archetype:interactive]
225
+ severity: error
226
+ ```
227
+
228
+ - No `eval`, `new Function`, `innerHTML`, `v-html`: the template renders.
229
+
230
+ ## `vue-component-imports`: Imports only from the allowed packages
231
+
232
+ ```rule
233
+ id: vue-component-imports
234
+ scope: [archetype:explainer, archetype:interactive]
235
+ severity: error
236
+ ```
237
+
238
+ - Only `vue`, `@lernapps/app-templates`, `@lernapps/tooling/storage`, `i18n`, `a11y`, own folder. Types from
239
+ anywhere.
240
+ - Interactive: also the app's `src/` files and its `dependencies`.
241
+
242
+ ## `vue-component-browser-globals`: Browser globals only once mounted
243
+
244
+ ```rule
245
+ id: vue-component-browser-globals
246
+ scope: [archetype:explainer, archetype:interactive]
247
+ severity: error
248
+ ```
249
+
250
+ - `window`, `document`, `localStorage` etc. only in `onMounted` or later unmount hooks (server render has none).
251
+
252
+ ## `vue-component-size`: Within 20 kB
253
+
254
+ ```rule
255
+ id: vue-component-size
256
+ scope: archetype:explainer
257
+ severity: error
258
+ ```
259
+
260
+ - Own code max 20 kB gzip. More → split, or a new block: write it into the retrospective.
261
+
262
+ ## `explainer-open-points`: An open task checks what the material teaches
263
+
264
+ ```rule
265
+ id: explainer-open-points
266
+ scope: archetype:explainer
267
+ severity: warning
268
+ ```
269
+
270
+ - 2 to 5 points, each one sentence a learner can check with yes or no; together what a good answer needs.
271
+ - A point of the content names its section (`source`), and its content is there; a point of form has `kind: form`.
272
+ - The model answer has every point, in the words of the class.
273
+
274
+ ## `explainer-scope-matches`: The scope says what the pages teach
275
+
276
+ ```rule
277
+ id: explainer-scope-matches
278
+ scope: archetype:explainer
279
+ severity: warning
280
+ ```
281
+
282
+ - `scope` of each page in your own words, never copied from the material; `scope` in `src/app.yaml` with what does not
283
+ belong to it.
284
+ - Each page's scope says what the page teaches, no more and no less; "Gehört nicht dazu" names what a learner or tutor
285
+ might expect but the material does not teach.
@@ -0,0 +1,79 @@
1
+ # Explainer runtime
2
+
3
+ ## Build
4
+
5
+ - Reads, validates, renders every page to static HTML.
6
+ - Problem → one line `file:line: place (language): what to do`, e.g.
7
+ `src/prozent/prozentwert.yaml:12: blocks[0].blocks[1].text: a Markdown heading ("Regel"); use a section block with the title "Regel"`.
8
+ Fix where it points.
9
+
10
+ ## Pages
11
+
12
+ - No JS: complete; text, formulas as MathML, figures, tables, navigation, sources. Exercise: task + `<details>`
13
+ "Lösung"; `generated`: three worked tasks; component: its `nojs` text; `open-task`: task, points with "Nachlesen",
14
+ model answer under "Lösung".
15
+ - JS: controls, "Prüfen", feedback with focus. Solution only after an answer; wrong → why, retry or "Lösung". An
16
+ exercise component gets "Prüfen" from the explainer too, under it.
17
+ `generated`: live task, "Neue Aufgabe", deep link `/<chapter>/<page>/?<exercise>=<n>#<exercise>`. Components
18
+ hydrate. `open-task`: "Deine Lösung" (type, or paper and photo), "Vergleichen" shows the points as tick boxes and
19
+ opens the model answer, "Antwort ändern".
20
+ - Video: no JS and before a click, title as a link to youtube.com, channel and a note that playing sends data to
21
+ YouTube/Google; nothing loads from another server. "Video abspielen" loads the player from youtube-nocookie.com.
22
+ - Stores on the device, per app, only the assistant the learner switched on for the tutor, once ticked, "Videos
23
+ immer direkt laden" (every player loads without the click until unticked), and the last result of each
24
+ self-assessment the learner did. While the tab is open (sessionStorage), the answer of each open task: way, text and
25
+ ticks, so that a reload loses nothing; never the photo.
26
+ - Self-assessment (`selfAssessment` per chapter, JS only): a chapter's on its page, the app's (every chapter's) on
27
+ the start page; its exercises without "Prüfen", checked together at "Auswerten"; the result per content page. With
28
+ `via=tutor` it keeps nothing and ends in "Zurück zum Tutor". Skill `lernapps-explainer-self-assessment`.
29
+
30
+ ## Addresses
31
+
32
+ - Page `/<chapter>/<page>/`; section `#<section>`, subsection `#<section>/<sub>`; exercise `#<exercise>`.
33
+ - Glossary `/glossar/`. Other languages: same tree under `/<language>/`.
34
+ - Tutor page of a page: `/<chapter>/<page>/tutor/`, its Markdown beside it (`index.md`).
35
+ - Scope (from `scope` in the content): `/<chapter>/<page>/scope/` (the page's), `/<chapter>/scope/` (the chapter's),
36
+ `/scope/` (the whole); for the tutor only, linked from the tutor page. `scope` is no chapter id.
37
+ - Self-assessment: `/einschaetzung/` (the app's), `/<chapter>/einschaetzung/` (a chapter's), each with its tutor page
38
+ `tutor/`. `einschaetzung` is no chapter or page id.
39
+ - Unknown address → 404 page to the start page. Moving or removing a page: change the entry topics in the same
40
+ increment.
41
+
42
+ ## Tests
43
+
44
+ - From the runtime (`e2e/explainer.e2e.ts`, `explainerTests()`), every page, every language, run by
45
+ `lernapps check`.
46
+ - No JS: headings vs nesting, sections, formulas, figures, anchors, navigation chain, languages, every solution,
47
+ every `nojs` text.
48
+ - JS (German, 360 px): one exercise per type and page accepts its answer, rejects a wrong one; components hydrate
49
+ without error; a video sends no request to another server before its click, and loads its player after it; each
50
+ self-assessment: a run with every answer right, one without an answer (kept, to the tutor, deleted), and one a tutor
51
+ opened.
52
+ - `lernapps check` also opens every page without JS (`explainer-readable-without-js`), bundle and deployed app.
53
+
54
+ ## A runtime test fails
55
+
56
+ - Content validates (build passes) but a test fails = template bug: act as skill `lernapps-cli` says; go on with
57
+ content.
58
+ - Never change the runtime in `node_modules` (`explainer-only-content`). The fix arrives with `lernapps update`.
59
+
60
+ ## Tutor
61
+
62
+ - Optional: the learner's own KI assistant helps with a page and with each exercise. The build writes a tutor page
63
+ per page from the content; the app sends nothing.
64
+ - The tutor reads the page's blocks as text (figures by `alt` and `caption`, a video as a link with title and channel)
65
+ and every exercise: task, answer format, solution, `hint` and typical mistakes with their messages. `generated`: template, `steps`, `mistakes` and each task
66
+ number's values; question: options with `info`, `explanation`; component: `about`, and with `template`, `params`, `mistakes`, `show`
67
+ the same table as `generated` (else `describe` per task number, as far as 64 kB allow).
68
+ `open-task`: task, points as P1, P2 … with their sources, model answer. It neither calculates nor invents: these
69
+ must be complete and right.
70
+ - The scope: the whole learning path in your own words, from the material, as continuous prose with the exact
71
+ content (facts, terms, reasons, examples), beside what it describes. `scope` in each page's YAML: what the page
72
+ teaches; optionally `scope` in `chapter.yaml`; and in `src/app.yaml`
73
+ `scope: { text, out: [...] }`: what the app is about and where its weight lies, and what does not belong to it (what
74
+ belongs to it is what the pages say). With
75
+ the app's scope the build requires a scope on every page. The tutor judges open answers by it, never from general
76
+ knowledge.
77
+ - `src/app.yaml`: `tutor.rules`, the app's rules for the tutor; never send it to another address.
78
+ - Task numbers 1 to N (max 67) are what learner, tutor and address (`?<id>=<n>`) share; changing a generator changes
79
+ what a number points to. `seed`, `via`, `uebung`, `abschnitt` are no exercise ids.
@@ -0,0 +1,24 @@
1
+ # Structure
2
+
3
+ | Level | File | Holds |
4
+ |---|---|---|
5
+ | App | `src/app.yaml` | `title`, `intro`, `languages`, order of `chapters`, `sources` |
6
+ | Chapter | `src/<chapter>/chapter.yaml` | `title`, `summary`, order of its `pages` |
7
+ | Page | `src/<chapter>/<page>.yaml` | `title`, `description`, `blocks` |
8
+ | Section | `section` block in a page | `id`, `title`, `blocks`; one more section level inside |
9
+ | Scope | `scope` in app, chapter and page (optional) | the whole learning path for the tutor, beside each page (`runtime.md`) |
10
+
11
+ - Chapters mandatory. One chapter: hidden in navigation; addresses keep it (`/<chapter>/<page>/`).
12
+ - Order lists complete: `chapters`, `pages` list every folder or file exactly once. No sorting by name.
13
+ - Ids: lowercase, digits, hyphens; unique per level; stable once published. Not chapter ids: `data`, `images`,
14
+ `glossar`, `components`, `assets`, `scope`.
15
+ - Depth: page, section, subsection; headings follow from nesting (h1–h3). Boxes (`example`, `note`) take the next
16
+ level, hold no sections. More levels = two apps.
17
+ - Navigation generated: contents on start and chapter pages, breadcrumbs, previous/next across chapters, page
18
+ contents from three sections, glossary from `definition` blocks.
19
+
20
+ ## Entry topics
21
+
22
+ - Path of a page or section relative to the app's `url`: `prozent/prozentwert/`, `prozent/prozentwert/#regel`
23
+ (`entry-links-resolve`; `lernapps check --entry` checks the section).
24
+ - From the stable ids (`explainer-stable-ids`).
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: lernapps-explainer-design
3
+ description: Use in Explore right after choosing the `explainer` archetype - how the content of a lernapps.net explainer maps onto chapters, pages, blocks and exercises, which the plan then applies.
4
+ license: MIT
5
+ ---
6
+
7
+ # Designing an explainer
8
+
9
+ ## What an explainer is
10
+
11
+ - Chapters of pages that explain a topic, with exercises on every page. Every page is complete without JavaScript;
12
+ with it, exercises check answers and give feedback.
13
+ - Generated around your content: navigation, contents, glossary, a tutor prompt per page, other languages.
14
+ - You will write the content as YAML; a Vue component only where no block fits.
15
+
16
+ ## Can and cannot
17
+
18
+ - The README of the template says it: <https://raw.githubusercontent.com/lernapps/app-templates/main/explainer/README.md>.
19
+ Read it before this skill's mapping, if you have not yet.
20
+
21
+ ## Map the content
22
+
23
+ - A chapter of competencies → an app chapter. A competency → a page or a section.
24
+ - Depth: chapter, page, section, subsection. Need more levels → two apps.
25
+ - The content structure → the same sections on every page, with fixed ids and titles (e.g. "Regel", "Beispiel",
26
+ "Übung").
27
+ - Shared material → a data file (`src/data/<name>.yaml`), each fact once.
28
+ - A pattern → a block or an exercise with fixed parts, varied in its drawn values or the records it picks.
29
+ - One chapter only: it is hidden in the navigation; its pages keep their addresses.
30
+
31
+ ## Blocks
32
+
33
+ - Text: prose (restricted Markdown), `definition` (also in the glossary), `example` and `note` boxes, `quote`,
34
+ `code`.
35
+ - Formulas: `formula` and inline `$…$`, LaTeX subset incl. chemistry (`\ce`), rendered as MathML.
36
+ - Figures: drawn (`hundred-grid`, `bar`), an image (`images/<name>.svg`, with source and licence), a
37
+ `labelled-figure` with numbered markers, a `table`, a `timeline`.
38
+ - Exercises: the six question types of the quiz; `generated` (a new task per seed, with drawn values, typical
39
+ mistakes, hint and steps); a component.
40
+ - Something no block can show or check → a component: read a value off a scale, label a figure, drag into place,
41
+ build a circuit. Logic in its own module, tested; a text for readers without JavaScript.
42
+ - Wanted, not only allowed: all that makes the content attractive - figures, drawings, labelled figures, tables,
43
+ timelines, videos; a component where no block fits.
44
+
45
+ ## Decide
46
+
47
+ - Languages: German; English as a second language is supported. Each declared language complete.
48
+ - The tutor: the build writes it from the content. Plan only app-specific tutor rules, if any.
49
+
50
+ ## Gotchas
51
+
52
+ - Each component costs a module, a test and a no-JS text: plan one only where it teaches what no block can.
53
+
54
+ ## Read when
55
+
56
+ - [references/rules.md](references/rules.md): before you write "Content method"; it holds the rules for pages,
57
+ figures, numbers, mistakes and components.
@@ -0,0 +1,75 @@
1
+ # Explainer rules for planning
2
+
3
+ ## `topic-has-exercises`: Every page has exercises
4
+
5
+ ```rule
6
+ id: topic-has-exercises
7
+ scope: archetype:explainer
8
+ severity: error
9
+ ```
10
+
11
+ - Every page has at least one exercise that practises what the page explains, with solution or feedback; best in a
12
+ last section "Übung".
13
+ - The schema requires it; start, chapter and glossary pages are generated. The review judges the fit.
14
+
15
+ ## `prefer-built-in-block`: A component only where no block fits
16
+
17
+ ```rule
18
+ id: prefer-built-in-block
19
+ scope: archetype:explainer
20
+ severity: hint
21
+ ```
22
+
23
+ - Built-in blocks and exercises first. A component only for what none can express; say why in the plan.
24
+
25
+ ## `explainer-figure-hides-answer`: The figure does not give the answer away
26
+
27
+ ```rule
28
+ id: explainer-figure-hides-answer
29
+ scope: archetype:explainer
30
+ severity: error
31
+ ```
32
+
33
+ - A task's figure shows the given values, never the answer.
34
+
35
+ ## `explainer-figure-explains`: The figure shows what the text says
36
+
37
+ ```rule
38
+ id: explainer-figure-explains
39
+ scope: archetype:explainer
40
+ severity: hint
41
+ ```
42
+
43
+ - Each figure shows what the text next to it explains. The caption says what to look at; `alt` says what it shows.
44
+
45
+ ## `explainer-plausible-numbers`: Numbers that fit the story
46
+
47
+ ```rule
48
+ id: explainer-plausible-numbers
49
+ scope: archetype:explainer
50
+ severity: warning
51
+ ```
52
+
53
+ - Ranges fit the thing: prices in whole cents, people whole, a bicycle 150–1500 €.
54
+ - Preconditions rule out misfits (90.91 people).
55
+
56
+ ## `explainer-mistakes-diagnosed`: Typical mistakes with their message
57
+
58
+ ```rule
59
+ id: explainer-mistakes-diagnosed
60
+ scope: archetype:explainer
61
+ severity: hint
62
+ ```
63
+
64
+ - Computed tasks list real mistakes. Each message says what went wrong and how to fix it ("Du hast vergessen, durch
65
+ 100 zu teilen", not "Falsch").
66
+
67
+ ## `explainer-quote-sourced`: Quotes exact, with their origin
68
+
69
+ ```rule
70
+ id: explainer-quote-sourced
71
+ scope: archetype:explainer
72
+ severity: warning
73
+ ```
74
+
75
+ - Quote exactly. Name its origin (author, work, year), source and licence.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: lernapps-explainer-self-assessment
3
+ description: Use in Commit of a lernapps.net explainer, once its content and its forms of teaching are final, to add, change or leave out its self-assessment (selfAssessment in each chapter.yaml) - which exercises it asks, how many on each of its pages, and what the build checks. Also when a build problem names selfAssessment.
4
+ license: MIT
5
+ ---
6
+
7
+ # Self-assessment of an explainer
8
+
9
+ ## What it is
10
+
11
+ - Two kinds of page: a content page of the app (`/<chapter>/<page>/`), and a step, one page of the
12
+ self-assessment with a few exercises.
13
+ - Optional, for the learner and for the app. Before learning, the learner answers exercises of the content pages,
14
+ without the page around them, a few on each step.
15
+ - No exercise is checked alone. "Auswerten" checks all of them together. The result per content page:
16
+ "Kannst du wahrscheinlich schon" (all right), "Schau sie dir noch einmal an" (at least half), "Lies sie genau"
17
+ (less), "Nicht abgefragt" (none of its exercises asked).
18
+ - JavaScript only: without it, it is not offered. The last result stays on the device; a new run replaces it.
19
+ - The chapter is the unit: each chapter declares its own in its `chapter.yaml` (at `<chapter>/einschaetzung/`,
20
+ offered on the chapter's page). The app's (at `einschaetzung/`, offered on the start page) is every chapter's
21
+ together; you write nothing for it. In an app with one chapter, the app's is the chapter's.
22
+ - The learner may take the result to their KI tutor. The tutor then guides chapter by chapter: to the pages that do
23
+ not stick, then into a new round of the chapter's self-assessment. The build writes the tutor's page; you write
24
+ nothing for the tutor.
25
+
26
+ ## Decide
27
+
28
+ - Default: one in every chapter.
29
+ - None in a chapter whose pages teach what no exercise can check (an open activity, a discussion, making something):
30
+ the tutor goes through it page by page. None in any chapter: write the reason under "Key decisions" and tell the
31
+ creator in one sentence.
32
+ - Leave a page out when its competency cannot be checked by one of its exercises. The result says "Nicht
33
+ abgefragt"; that is right for such a page.
34
+
35
+ ## Choose the exercises
36
+
37
+ - Read each content page's competency under "Notes" ("Ich kann …"). No "Notes": take it from the page's title,
38
+ description and rule. Ask the exercises that check it best.
39
+ - Prefer what draws a new task in each run: `generated`, or an exercise component (a `vue-component` block whose
40
+ component emits an answer, by its anchor). Then `number`, `ordering`, `matching`, `multiple-choice`,
41
+ `single-choice`. A content page asked only by exercises that can be guessed (`true-false`, a `single-choice` or a
42
+ small `matching`) gives a weak result: add a `generated`, a component or a `number` one of the same page.
43
+ - Each must be clear without its page: no "wie im Beispiel oben", no figure that stands elsewhere on the page. A
44
+ question carries its figure in `material`. Not clear alone → take another exercise of the page, or leave the page
45
+ out.
46
+ - An exercise component shows its task without "Prüfen", feedback or task number. Take it only when its task is
47
+ clear in the component itself (the task text is in the component, not in a block around it), and when it needs
48
+ nothing the page has to play or show first.
49
+ - 2 or 3 exercises per content page asked: with one alone, the page is never "Kannst du wahrscheinlich schon". A page
50
+ with one fitting `generated` exercise or exercise component: list it twice, each listing draws a task of its own.
51
+ A question is listed once.
52
+
53
+ ## Write it
54
+
55
+ - Steps: 2 to 5 exercises each, best 3; fewer or more gives a build hint. Keep the order of the course, also within a
56
+ content page.
57
+ - About 3 to 8 exercises per chapter; the app's, every chapter's together, at most about 15 to 20: about ten minutes.
58
+ - Each exercise by its page and id: `/<chapter>/<page>/#<exercise>`, of the chapter's own pages.
59
+
60
+ ```yaml
61
+ # src/prozent/chapter.yaml
62
+ selfAssessment:
63
+ pages:
64
+ - exercises:
65
+ - /prozent/prozentwert/#prozentwert-ueben
66
+ - /prozent/prozentsatz/#welche-rechnung
67
+ - /prozent/prozentsatz/#prozentsatz-ueben
68
+ - exercises:
69
+ - /prozent/grundwert/#klammern
70
+ - /prozent/grundwert/#grundwert-ueben
71
+ ```
72
+
73
+ - In the content guide (`.agents/skills/app-content/SKILL.md`), in the procedure for a new chapter or page, add the
74
+ step: "1 bis 3 ihrer Übungen in `selfAssessment` aufnehmen, wie Skill `lernapps-explainer-self-assessment` sagt."
75
+ None in the app → the content guide says why.
76
+
77
+ ## Check
78
+
79
+ - Build and `lernapps check`: one line per problem (the hint on the size of a step names its file and place), e.g.
80
+ `src/prozent/chapter.yaml:9: selfAssessment.pages[0].exercises[0]: /prozent/prozentwert/#prozent-raten names no exercise of src/prozent/prozentwert.yaml; …`.
81
+ Fix where it points.
82
+ - Do one run yourself in `npm run dev` at `/einschaetzung/`, and one at `/<chapter>/einschaetzung/?via=tutor`: it
83
+ ends in "Zurück zum Tutor". For each exercise: no "oben", "im Beispiel" or other
84
+ reference to its page; its figure shows with it; the task is the whole question. For each content page asked: one
85
+ exercise at least that cannot be guessed. Then write the commit.
86
+ - The end-to-end tests do three runs of each self-assessment: every answer right; none; one a tutor opened.
87
+
88
+ ## Gotchas
89
+
90
+ - An exercise renamed or moved → change its reference in the same commit.
91
+ - `einschaetzung` is reserved: no chapter or page may have that id.
92
+ - Never `selfAssessment` in `src/app.yaml` (build problem): the app's comes from the chapters.
93
+ - Nothing about a real learner in any file (`no-learner-data-in-texts`).