@lernapps/tooling 0.0.0-stage → 0.1.0
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.
- package/LICENSE +22 -0
- package/README.md +67 -2
- package/archetypes/shared/a11y.ts +38 -0
- package/archetypes/shared/hooks/pre-commit +22 -0
- package/archetypes/shared/hooks/pre-push +4 -0
- package/archetypes/shared/i18n.ts +25 -0
- package/archetypes/shared/install-hooks.ts +63 -0
- package/archetypes/shared/playwright.ts +54 -0
- package/archetypes/shared/preset.ts +81 -0
- package/archetypes/shared/storage.ts +167 -0
- package/archetypes/shared/tsconfig.json +27 -0
- package/check/validation-report.v1.schema.json +116 -0
- package/dist/a11y.mjs +30 -0
- package/dist/check/rules/accessible.mjs +18 -0
- package/dist/check/rules/app-content-guide.mjs +69 -0
- package/dist/check/rules/dependency-licence.mjs +82 -0
- package/dist/check/rules/entry-fitness-matches.mjs +22 -0
- package/dist/check/rules/entry-links-resolve.mjs +44 -0
- package/dist/check/rules/explainer-readable-without-js.mjs +66 -0
- package/dist/check/rules/links-resolve.mjs +10 -0
- package/dist/check/rules/lockfile-matches.mjs +57 -0
- package/dist/check/rules/no-request-before-click.mjs +17 -0
- package/dist/check/rules/no-tracking.mjs +17 -0
- package/dist/check/rules/own-data-only.mjs +66 -0
- package/dist/check/rules/pages-reachable.mjs +25 -0
- package/dist/check/rules/usable-at-360px.mjs +19 -0
- package/dist/check-cv4I6CCH.mjs +28 -0
- package/dist/cli.mjs +3118 -0
- package/dist/i18n.mjs +11 -0
- package/dist/lint.mjs +528 -0
- package/dist/plan-DWKayEnY.mjs +75 -0
- package/dist/playwright.mjs +47 -0
- package/dist/preset.mjs +60 -0
- package/dist/skills/lernapps-app/SKILL.md +49 -0
- package/dist/skills/lernapps-cli/SKILL.md +156 -0
- package/dist/skills/lernapps-cli/references/platform-rules.md +258 -0
- package/dist/skills/lernapps-commit/SKILL.md +39 -0
- package/dist/skills/lernapps-content-growth/SKILL.md +33 -0
- package/dist/skills/lernapps-content-questions/SKILL.md +133 -0
- package/dist/skills/lernapps-content-questions/references/question-types.md +69 -0
- package/dist/skills/lernapps-content-research/SKILL.md +50 -0
- package/dist/skills/lernapps-content-research/references/sources.md +16 -0
- package/dist/skills/lernapps-exercise-patterns/SKILL.md +74 -0
- package/dist/skills/lernapps-exercise-patterns/references/biology-geography.md +13 -0
- package/dist/skills/lernapps-exercise-patterns/references/chemistry.md +16 -0
- package/dist/skills/lernapps-exercise-patterns/references/computer-science.md +13 -0
- package/dist/skills/lernapps-exercise-patterns/references/figures.md +10 -0
- package/dist/skills/lernapps-exercise-patterns/references/history.md +13 -0
- package/dist/skills/lernapps-exercise-patterns/references/mathematics.md +19 -0
- package/dist/skills/lernapps-exercise-patterns/references/page-structures.md +8 -0
- package/dist/skills/lernapps-exercise-patterns/references/physics.md +18 -0
- package/dist/skills/lernapps-exercise-patterns/references/success.md +28 -0
- package/dist/skills/lernapps-explainer/SKILL.md +33 -0
- package/dist/skills/lernapps-explainer/references/blocks.md +83 -0
- package/dist/skills/lernapps-explainer/references/components.md +66 -0
- package/dist/skills/lernapps-explainer/references/exercises.md +115 -0
- package/dist/skills/lernapps-explainer/references/rules.md +285 -0
- package/dist/skills/lernapps-explainer/references/runtime.md +79 -0
- package/dist/skills/lernapps-explainer/references/structure.md +24 -0
- package/dist/skills/lernapps-explainer-design/SKILL.md +57 -0
- package/dist/skills/lernapps-explainer-design/references/rules.md +75 -0
- package/dist/skills/lernapps-explainer-self-assessment/SKILL.md +93 -0
- package/dist/skills/lernapps-github/SKILL.md +102 -0
- package/dist/skills/lernapps-interactive/SKILL.md +141 -0
- package/dist/skills/lernapps-interactive/references/frame.md +30 -0
- package/dist/skills/lernapps-interactive-design/SKILL.md +58 -0
- package/dist/skills/lernapps-listing/SKILL.md +44 -0
- package/dist/skills/lernapps-listing/references/keeping-updated.md +33 -0
- package/dist/skills/lernapps-quiz/SKILL.md +100 -0
- package/dist/skills/lernapps-quiz-design/SKILL.md +48 -0
- package/dist/status-CXoQBgfU.mjs +76 -0
- package/dist/storage.mjs +113 -0
- package/generator/app/.agents/skills/app-content/SKILL.md +63 -0
- package/generator/app/.github/ISSUE_TEMPLATE/inhaltsfehler.yml +25 -0
- package/generator/app/.github/workflows/pages.yml +61 -0
- package/generator/app/LICENSE +21 -0
- package/generator/app/renovate.json +4 -0
- package/generator/architecture.ts +212 -0
- package/generator/create.ts +462 -0
- package/generator/init.ts +186 -0
- package/generator/update.ts +429 -0
- package/guidance/AGENTS.md +26 -0
- package/guidance/increment-template.md +194 -0
- package/guidance/plan-front-matter.v1.schema.json +36 -0
- package/guidance/plan-template.md +233 -0
- package/guidance/subagent-brief.md +25 -0
- package/guidance/workflow-rules.md +109 -0
- package/package.json +135 -4
- package/review/verdict.v1.schema.json +134 -0
- package/skills/archetypes/lernapps-explainer/SKILL.md +33 -0
- package/skills/archetypes/lernapps-explainer/references/blocks.md +83 -0
- package/skills/archetypes/lernapps-explainer/references/components.md +66 -0
- package/skills/archetypes/lernapps-explainer/references/exercises.md +115 -0
- package/skills/archetypes/lernapps-explainer/references/rules.md +285 -0
- package/skills/archetypes/lernapps-explainer/references/runtime.md +79 -0
- package/skills/archetypes/lernapps-explainer/references/structure.md +24 -0
- package/skills/archetypes/lernapps-explainer-design/SKILL.md +57 -0
- package/skills/archetypes/lernapps-explainer-design/references/rules.md +75 -0
- package/skills/archetypes/lernapps-explainer-self-assessment/SKILL.md +93 -0
- package/skills/archetypes/lernapps-interactive/SKILL.md +141 -0
- package/skills/archetypes/lernapps-interactive/references/frame.md +30 -0
- package/skills/archetypes/lernapps-interactive-design/SKILL.md +58 -0
- package/skills/archetypes/lernapps-quiz/SKILL.md +100 -0
- package/skills/archetypes/lernapps-quiz-design/SKILL.md +48 -0
- package/skills/content/lernapps-content-questions/SKILL.md +133 -0
- package/skills/content/lernapps-content-questions/references/question-types.md +69 -0
- package/skills/content/lernapps-content-research/SKILL.md +50 -0
- package/skills/content/lernapps-content-research/references/sources.md +16 -0
- package/skills/content/lernapps-exercise-patterns/SKILL.md +74 -0
- package/skills/content/lernapps-exercise-patterns/references/biology-geography.md +13 -0
- package/skills/content/lernapps-exercise-patterns/references/chemistry.md +16 -0
- package/skills/content/lernapps-exercise-patterns/references/computer-science.md +13 -0
- package/skills/content/lernapps-exercise-patterns/references/figures.md +10 -0
- package/skills/content/lernapps-exercise-patterns/references/history.md +13 -0
- package/skills/content/lernapps-exercise-patterns/references/mathematics.md +19 -0
- package/skills/content/lernapps-exercise-patterns/references/page-structures.md +8 -0
- package/skills/content/lernapps-exercise-patterns/references/physics.md +18 -0
- package/skills/content/lernapps-exercise-patterns/references/success.md +28 -0
- package/skills/process/lernapps-app/SKILL.md +49 -0
- package/skills/process/lernapps-commit/SKILL.md +39 -0
- package/skills/process/lernapps-content-growth/SKILL.md +33 -0
- package/skills/process/lernapps-github/SKILL.md +102 -0
- package/skills/process/lernapps-listing/SKILL.md +44 -0
- package/skills/process/lernapps-listing/references/keeping-updated.md +33 -0
- package/skills/tooling/lernapps-cli/SKILL.md +156 -0
- 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`).
|