@lernapps/tooling 0.1.1 → 0.1.3
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/README.md +1 -1
- package/dist/cli.mjs +32 -9
- package/dist/skills/lernapps-app/SKILL.md +5 -3
- package/dist/skills/lernapps-cli/SKILL.md +5 -5
- package/dist/skills/lernapps-content-growth/SKILL.md +1 -1
- package/dist/skills/lernapps-content-questions/references/question-types.md +1 -1
- package/dist/skills/lernapps-content-research/SKILL.md +3 -2
- package/dist/skills/lernapps-explainer/SKILL.md +2 -0
- package/dist/skills/lernapps-explainer-design/SKILL.md +1 -1
- package/dist/skills/lernapps-interactive-design/SKILL.md +1 -1
- package/dist/skills/lernapps-quiz-design/SKILL.md +1 -1
- package/generator/create.ts +5 -5
- package/generator/init.ts +21 -1
- package/generator/update.ts +4 -4
- package/guidance/increment-template.md +3 -3
- package/guidance/plan-template.md +4 -4
- package/guidance/subagent-brief.md +1 -1
- package/package.json +2 -2
- package/skills/archetypes/lernapps-explainer/SKILL.md +2 -0
- package/skills/archetypes/lernapps-explainer-design/SKILL.md +1 -1
- package/skills/archetypes/lernapps-interactive-design/SKILL.md +1 -1
- package/skills/archetypes/lernapps-quiz-design/SKILL.md +1 -1
- package/skills/content/lernapps-content-questions/references/question-types.md +1 -1
- package/skills/content/lernapps-content-research/SKILL.md +3 -2
- package/skills/process/lernapps-app/SKILL.md +5 -3
- package/skills/process/lernapps-content-growth/SKILL.md +1 -1
- package/skills/tooling/lernapps-cli/SKILL.md +5 -5
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ lernapps.net's own websites, and the update policy for dependencies.
|
|
|
39
39
|
- **The CLI `lernapps`:** `init` starts an app's plan in an empty folder and syncs the skills of the packages into the agent directories, `skills --archetype` adds those of the chosen archetype, `create` writes a new app for an archetype once the creator confirmed the plan, `check`
|
|
40
40
|
checks an app the same way in its git hooks and in CI, `update` moves an app to the runtime and tooling versions of the latest
|
|
41
41
|
tooling and replaces the app's `lernapps-*` skills with that tooling's (and an older app's single plan into
|
|
42
|
-
`.vibe/plans/`), `changes` tells what a change can affect, so that hooks and CI run only that, `screenshots` writes an image of every page and every figure of a built explainer or quiz, to show a creator what a learner sees (`npx lernapps screenshots --help`). `npx --yes @lernapps/tooling --help` before an app exists, `npx lernapps --help` in one.
|
|
42
|
+
`.vibe/plans/`), `changes` tells what a change can affect, so that hooks and CI run only that, `screenshots` writes an image of every page and every figure of a built explainer or quiz, to show a creator what a learner sees (`npx --no -- lernapps screenshots --help`). `npx --yes @lernapps/tooling --help` before an app exists, `npx --no -- lernapps --help` in one.
|
|
43
43
|
- **The actions in [`actions/`](actions/):** the app check, app publish and app preview actions of every app, and the site
|
|
44
44
|
actions with which lernapps.net's own websites are checked, published and previewed. Each says what it does in its
|
|
45
45
|
`action.yml`. The reusable workflow [`changes.yml`](.github/workflows/changes.yml) gives other workflows the
|
package/dist/cli.mjs
CHANGED
|
@@ -632,7 +632,7 @@ the app cannot be created, 2 on a usage error.
|
|
|
632
632
|
|
|
633
633
|
The package @lernapps/tooling comes from the npm registry. Before an app exists, run a command with
|
|
634
634
|
npx --yes @lernapps/tooling <command> ...
|
|
635
|
-
In an app, it is a development dependency: npx lernapps <command> ...
|
|
635
|
+
In an app, it is a development dependency: npx --no -- lernapps <command> ...
|
|
636
636
|
`;
|
|
637
637
|
/** The options of `lernapps check`, as node:util parseArgs takes them. */
|
|
638
638
|
const CHECK_OPTIONS = {
|
|
@@ -1441,7 +1441,7 @@ It needs the plan of the first version, confirmed by the creator: started from t
|
|
|
1441
1441
|
tooling is moved to .vibe/plans/01-first-version.md. Without a plan, it writes nothing and says what to do.
|
|
1442
1442
|
|
|
1443
1443
|
Run it in the folder lernapps init prepared, from the tooling init installed:
|
|
1444
|
-
npx lernapps create --archetype <name> [<dir>]
|
|
1444
|
+
npx --no -- lernapps create --archetype <name> [<dir>]
|
|
1445
1445
|
It needs git, and the npm registry for the npm install that follows. The app then depends on the version of
|
|
1446
1446
|
@lernapps/tooling that created it, and its workflows use the actions of that version's tag.
|
|
1447
1447
|
|
|
@@ -1527,7 +1527,7 @@ function contents(dir) {
|
|
|
1527
1527
|
if (name === ".git" || name === "skills-lock.json" && skills.size > 0) return [];
|
|
1528
1528
|
if (name === "node_modules" || name === "package-lock.json") return [];
|
|
1529
1529
|
if (name === "package.json" && readJson(join(dir, name)).lernapps?.init === true) return [];
|
|
1530
|
-
if (name === ".vibe") return
|
|
1530
|
+
if (name === ".vibe") return existsSync(join(dir, ".vibe/plans")) ? within(PLANS, (file) => PLAN_NAME.test(file)) : [];
|
|
1531
1531
|
if ((name === ".agents" || name === ".claude") && skills.size > 0) return within(name, (folder) => folder === "skills").concat(existsSync(join(dir, name, "skills")) ? within(`${name}/skills`, (skill) => skills.has(skill)) : []);
|
|
1532
1532
|
return [name];
|
|
1533
1533
|
});
|
|
@@ -1691,7 +1691,7 @@ function create(args) {
|
|
|
1691
1691
|
if (positionals.length > 1) throw new UsageError(`one <dir> at most, not ${positionals.join(" ")}`);
|
|
1692
1692
|
const dir = resolve(positionals[0] ?? ".");
|
|
1693
1693
|
const found = contents(dir);
|
|
1694
|
-
if (found.length > 0) throw new CreateError(`${dir} is not empty (${found.slice(0, 5).join(", ")}${found.length > 5 ? ", ..." : ""}): create the app in an empty folder; only .git, the first version's plan .vibe/plans/01-<short name>.md and what lernapps init wrote (its skills, package.json, package-lock.json and node_modules) may be there`);
|
|
1694
|
+
if (found.length > 0) throw new CreateError(`${dir} is not empty (${found.slice(0, 5).join(", ")}${found.length > 5 ? ", ..." : ""}): create the app in an empty folder; only .git, .vibe/ (the first version's plan .vibe/plans/01-<short name>.md, and its sketches) and what lernapps init wrote (its skills, package.json, package-lock.json and node_modules) may be there`);
|
|
1695
1695
|
const plan = confirmedPlan(dir, archetype, values.plan);
|
|
1696
1696
|
const architecture = ARCHITECTURE_ARCHETYPES.includes(archetype);
|
|
1697
1697
|
if (!existsSync(join(templates.root, archetype, "package.json"))) throw new CreateError(`${templates.root} has no template ${archetype}/ (version ${templates.version})`);
|
|
@@ -1765,6 +1765,7 @@ const INIT_USAGE = `Usage: lernapps init <short name> [--addon <package>]
|
|
|
1765
1765
|
|
|
1766
1766
|
Starts an app in the current folder, which must be empty except for .git. It needs git, Node and the npm registry; nothing
|
|
1767
1767
|
else. In order:
|
|
1768
|
+
git repository on the branch work, which the plan names (unless the folder is one already; no commit)
|
|
1768
1769
|
package.json names the folder, depends on @lernapps/tooling (this version) and the add-on
|
|
1769
1770
|
npm install installs them
|
|
1770
1771
|
.vibe/plans/01-<short name>.md
|
|
@@ -1802,6 +1803,26 @@ const SKILLS_BIN = () => {
|
|
|
1802
1803
|
const bin = readJson(manifest)["bin"];
|
|
1803
1804
|
return join(dirname(manifest), bin?.["skills"] ?? "bin/cli.mjs");
|
|
1804
1805
|
};
|
|
1806
|
+
/** The branch the plan works on (rule 8 of the plan template). */
|
|
1807
|
+
const WORK_BRANCH = "work";
|
|
1808
|
+
/**
|
|
1809
|
+
* Makes the folder a git repository on the branch `work`, which the plan names, unless it is one already: `create` and
|
|
1810
|
+
* the hooks need it, and the plan's first rule is to work there. Returns what it did, for the output; no commit.
|
|
1811
|
+
*/
|
|
1812
|
+
function ensureRepository(dir) {
|
|
1813
|
+
if (existsSync(join(dir, ".git"))) return void 0;
|
|
1814
|
+
const result = spawnSync("git", [
|
|
1815
|
+
"init",
|
|
1816
|
+
"--quiet",
|
|
1817
|
+
`--initial-branch=${WORK_BRANCH}`
|
|
1818
|
+
], {
|
|
1819
|
+
cwd: dir,
|
|
1820
|
+
encoding: "utf8"
|
|
1821
|
+
});
|
|
1822
|
+
if (result.error) throw new CreateError(`git cannot run: ${result.error.message}. Install git, then run init again`);
|
|
1823
|
+
if (result.status !== 0) throw new CreateError(`git init failed: ${`${result.stdout}${result.stderr}`.trim()}`);
|
|
1824
|
+
return `a git repository on the branch ${WORK_BRANCH}`;
|
|
1825
|
+
}
|
|
1805
1826
|
/** The names of the skills of the archetypes, with the archetype each belongs to (lernapps-<archetype>[-…]). */
|
|
1806
1827
|
function archetypeSkills() {
|
|
1807
1828
|
const dir = fromPackage("skills", "archetypes");
|
|
@@ -1858,6 +1879,7 @@ function init(args) {
|
|
|
1858
1879
|
const present = readdirSync(dir).filter((entry) => entry !== ".git");
|
|
1859
1880
|
if (present.length > 0) throw new CreateError(`${dir} is not empty (${present.slice(0, 5).join(", ")}${present.length > 5 ? ", ..." : ""}): start in a new, empty folder`);
|
|
1860
1881
|
const addon = values.addon;
|
|
1882
|
+
const repository = ensureRepository(dir);
|
|
1861
1883
|
writeJson(join(dir, "package.json"), {
|
|
1862
1884
|
name: slug(dir),
|
|
1863
1885
|
version: "0.0.0",
|
|
@@ -1883,7 +1905,7 @@ function init(args) {
|
|
|
1883
1905
|
mkdirSync(dirname(target), { recursive: true });
|
|
1884
1906
|
writeFileSync(target, readFileSync(template));
|
|
1885
1907
|
syncSkills(dir, archetypeSkills().map((skill) => skill.name));
|
|
1886
|
-
process.stdout.write(`lernapps init: ${relative$1(dir, target)} from ${relativeTemplate(template, dir)}; the skills of the packages are installed\nNext: read ${relative$1(dir, target)} completely and follow it\n`);
|
|
1908
|
+
process.stdout.write(`lernapps init: ${relative$1(dir, target)} from ${relativeTemplate(template, dir)}; the skills of the packages are installed${repository ? `; ${repository}` : ""}\nNext: read ${relative$1(dir, target)} completely and follow it\n`);
|
|
1887
1909
|
return 0;
|
|
1888
1910
|
}
|
|
1889
1911
|
const relative$1 = (from, to) => to.startsWith(from) ? to.slice(from.length + 1) : to;
|
|
@@ -1939,8 +1961,8 @@ moves the app within its version ranges; this moves the ranges, and what npm doe
|
|
|
1939
1961
|
|
|
1940
1962
|
Run it from the latest tooling, in the app's folder, e.g. to pick up a fixed runtime:
|
|
1941
1963
|
${LATEST}
|
|
1942
|
-
Run as the app's own tooling (npx lernapps update), it knows only the versions the app already has.
|
|
1943
|
-
Then run npx lernapps check, and commit package.json, package-lock.json, .github/workflows/ and what else it names.
|
|
1964
|
+
Run as the app's own tooling (npx --no -- lernapps update), it knows only the versions the app already has.
|
|
1965
|
+
Then run npx --no -- lernapps check, and commit package.json, package-lock.json, .github/workflows/ and what else it names.
|
|
1944
1966
|
|
|
1945
1967
|
Exit codes: 0 when the app is updated (or was up to date), 1 when it cannot be or only partly (the message says
|
|
1946
1968
|
what was not moved and why), 2 on a usage error.
|
|
@@ -2238,7 +2260,7 @@ function update(args) {
|
|
|
2238
2260
|
2
|
|
2239
2261
|
] });
|
|
2240
2262
|
if (install.error || install.status !== 0) throw new UpdateError(`npm install ${specs.join(" ")} failed${install.error ? `: ${install.error.message}` : ` (exit ${install.status})`}; its output is above. Fix the cause, then run lernapps update again`);
|
|
2241
|
-
if (installHooks([]) !== 0) throw new UpdateError("lernapps hooks failed (see above); run npx lernapps hooks again");
|
|
2263
|
+
if (installHooks([]) !== 0) throw new UpdateError("lernapps hooks failed (see above); run npx --no -- lernapps hooks again");
|
|
2242
2264
|
}
|
|
2243
2265
|
const changed = moveActions(`v${version}`);
|
|
2244
2266
|
if (changed.length > 0) lines.push(`the actions of lernapps/tooling in ${changed.join(", ")}: v${version}`);
|
|
@@ -2264,7 +2286,7 @@ function update(args) {
|
|
|
2264
2286
|
if (skills.some((line) => line.includes(".gitignore"))) files.push(".gitignore");
|
|
2265
2287
|
if (architecture.lines.length > 0) files.push(`${ARCHITECTURE}/`);
|
|
2266
2288
|
if (plan.some((line) => line.startsWith("plan: moved"))) files.push(".vibe/ (git add -A .vibe, to keep the move)");
|
|
2267
|
-
process.stdout.write(`Next: npx lernapps check, then commit ${files.slice(0, -1).join(", ")} and ${files.at(-1) ?? ""}\n`);
|
|
2289
|
+
process.stdout.write(`Next: npx --no -- lernapps check, then commit ${files.slice(0, -1).join(", ")} and ${files.at(-1) ?? ""}\n`);
|
|
2268
2290
|
return 0;
|
|
2269
2291
|
}
|
|
2270
2292
|
// src/screenshots.ts
|
|
@@ -2431,6 +2453,7 @@ async function screenshots(args) {
|
|
|
2431
2453
|
force: true
|
|
2432
2454
|
});
|
|
2433
2455
|
mkdirSync(out, { recursive: true });
|
|
2456
|
+
writeFileSync(join(out, ".gitignore"), "*\n");
|
|
2434
2457
|
const shots = [];
|
|
2435
2458
|
for (const [index, page] of pages.entries()) {
|
|
2436
2459
|
const images = [];
|
|
@@ -27,11 +27,13 @@ license: MIT
|
|
|
27
27
|
|
|
28
28
|
## What each archetype can do
|
|
29
29
|
|
|
30
|
+
The READMEs are files of the package `@lernapps/app-templates`, which `init` installed: read them from the folder, in full.
|
|
31
|
+
|
|
30
32
|
| Archetype | Learners … | Can and cannot (README of its template) |
|
|
31
33
|
|---|---|---|
|
|
32
|
-
| `quiz` | answer questions with options and feedback |
|
|
33
|
-
| `explainer` | read pages that explain, each with exercises |
|
|
34
|
-
| `interactive` | act in one app page, by turns or in real time |
|
|
34
|
+
| `quiz` | answer questions with options and feedback | `node_modules/@lernapps/app-templates/quiz/README.md` |
|
|
35
|
+
| `explainer` | read pages that explain, each with exercises | `node_modules/@lernapps/app-templates/explainer/README.md` |
|
|
36
|
+
| `interactive` | act in one app page, by turns or in real time | `node_modules/@lernapps/app-templates/interactive/README.md` |
|
|
35
37
|
|
|
36
38
|
## Choose the archetype
|
|
37
39
|
|
|
@@ -14,7 +14,7 @@ license: MIT
|
|
|
14
14
|
## Create
|
|
15
15
|
|
|
16
16
|
1. Only after the creator's yes to the plan (`explore-before-code`). In the plan's folder:
|
|
17
|
-
`npx lernapps create --archetype <archetype>`.
|
|
17
|
+
`npx --no -- lernapps create --archetype <archetype>`.
|
|
18
18
|
2. No git repo yet: `git init --initial-branch=work`. Then `npm install` (dependencies, git hooks), and commit
|
|
19
19
|
everything on `work`.
|
|
20
20
|
3. Needs git, Node ≥ 22.18, registry.npmjs.org. Blocked → ask the creator to allow it, run again. Never write the
|
|
@@ -29,20 +29,20 @@ license: MIT
|
|
|
29
29
|
|
|
30
30
|
## Check
|
|
31
31
|
|
|
32
|
-
- `npx lernapps check`: format, lint, types, unit tests, build, checks of the built app, end-to-end tests. The hooks
|
|
32
|
+
- `npx --no -- lernapps check`: format, lint, types, unit tests, build, checks of the built app, end-to-end tests. The hooks
|
|
33
33
|
run its parts (`--pre-commit`, `--pre-push`); CI runs it whole.
|
|
34
|
-
- Report: `node_modules/.cache/lernapps/validation-report.yaml`. Options: `npx lernapps check --help`.
|
|
34
|
+
- Report: `node_modules/.cache/lernapps/validation-report.yaml`. Options: `npx --no -- lernapps check --help`.
|
|
35
35
|
|
|
36
36
|
## Look at the app
|
|
37
37
|
|
|
38
38
|
A check says the rules hold; only a look says what a learner sees. Show the creator the pages before a push, and before
|
|
39
39
|
a submission they declare something about.
|
|
40
40
|
|
|
41
|
-
- Explainer or quiz: build (`npx vp build`), then `npx lernapps screenshots`. It writes one image of every page, one of
|
|
41
|
+
- Explainer or quiz: build (`npx vp build`), then `npx --no -- lernapps screenshots`. It writes one image of every page, one of
|
|
42
42
|
every figure, and an `index.html` that shows them in order to `screenshots/` (not part of the app: do not commit it).
|
|
43
43
|
Show the images, or the `index.html` where you can show HTML. Check every figure in its own image
|
|
44
44
|
(`…-figure-<n>.png`): a page image is scaled down, its details are not readable. `--desktop` adds 1280 px images.
|
|
45
|
-
Options: `npx lernapps screenshots --help`.
|
|
45
|
+
Options: `npx --no -- lernapps screenshots --help`. The folder ignores itself in git, so a later check never sees it.
|
|
46
46
|
- Interactive app: `screenshots` does not support it. Open the built app with the Playwright the tooling installs
|
|
47
47
|
(`import { chromium } from "playwright"`), at 390 px width, and take `page.screenshot({ fullPage: true })` of each
|
|
48
48
|
state the creator should see, from a short script outside the app.
|
|
@@ -15,7 +15,7 @@ Each slice is one Code task and ends in one commit:
|
|
|
15
15
|
3. Exercise: a pattern of the guide, varied. A new pattern goes into the guide in the same slice, with example and
|
|
16
16
|
data file.
|
|
17
17
|
4. Entry topic: the page or section path into the plan's entry draft (`entry-links-resolve`).
|
|
18
|
-
5. Check: `npx lernapps check` passes.
|
|
18
|
+
5. Check: `npx --no -- lernapps check` passes.
|
|
19
19
|
6. Commit, guide changes included.
|
|
20
20
|
|
|
21
21
|
- A new chapter or round: its slices in the order of the guide's procedure.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| `true-false` | `answer` (true or false) |
|
|
8
8
|
| `number` | `answer`, `tolerance` (0 = exact), `unit` if any; the learner may type a comma or a point |
|
|
9
9
|
| `ordering` | `items` in the right order; the page mixes them |
|
|
10
|
-
| `matching` | `pairs` as they belong
|
|
10
|
+
| `matching` | `pairs` as they belong, each pair an object `{ left, right }`; the page mixes the right side. `distractors` (1 to 4): wrong right entries that match no left one. `pairsFrom: material` instead of `pairs` takes them from the `labelled-figure` in `material` (marker left, text right; the figure needs `legend: false`) |
|
|
11
11
|
|
|
12
12
|
- Every question: `id`, `text`, `explanation`, at least one link in `links`. Optional quiz `sources`.
|
|
13
13
|
- Types without options carry their background in `explanation`.
|
|
@@ -15,8 +15,8 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
- Orientation for grade and order, not a condition. None found → say so once; go on.
|
|
17
17
|
- Only the Land's official document (Kerncurriculum, Lehrplan, Bildungsplan, Rahmenlehrplan) from the ministry or
|
|
18
|
-
state institute. No publisher, schoolbook or portal. No Land known → KMK-Bildungsstandards.
|
|
19
|
-
- Download and read it yourself.
|
|
18
|
+
state institute. No publisher, schoolbook or portal. No Land known → KMK-Bildungsstandards. The KMK has none for the subject or level (e.g. Informatik in Sekundarstufe II) → cite no unit, write "not checked" and follow the creator's material.
|
|
19
|
+
- Download and read it yourself. A document you cannot read here (a PDF and no tool to read it) → mark it "not checked"; never cite it from its title alone.
|
|
20
20
|
- Cite it under "Notes": title, issuer, year, address; page and unit (Inhaltsfeld, Lernbereich, Kompetenz).
|
|
21
21
|
- The creator's material differs → follow the material; say so in one sentence.
|
|
22
22
|
|
|
@@ -33,6 +33,7 @@ license: MIT
|
|
|
33
33
|
|
|
34
34
|
- Per competency one article or video (serlo.org, a channel the creator trusts, Wikipedia).
|
|
35
35
|
- Read [references/sources.md](references/sources.md) before you choose, cite or rely on a source.
|
|
36
|
+
- A text source (Wikipedia, a schoolbook site): take facts, never sentences. Copying a sentence needs the licence the page states; if you cannot read it, do not copy.
|
|
36
37
|
|
|
37
38
|
## 4. The creator's material and privacy
|
|
38
39
|
|
|
@@ -28,6 +28,8 @@ license: MIT
|
|
|
28
28
|
|
|
29
29
|
- A build problem is one line `file:line: place (language): what to do`. Fix where it points.
|
|
30
30
|
- Headings are `section` blocks, never Markdown headings.
|
|
31
|
+
- YAML: quote a text that has `: ` in it or looks like a number (`"8."`, `"01000001"`, `"0"`). Unquoted, YAML reads a map or a
|
|
32
|
+
number: the build stops, or the digits change. A table cell, a header cell too, is a text and never empty.
|
|
31
33
|
- A new chapter: a folder with `chapter.yaml`, listed in `src/app.yaml`, each page listed in `chapter.yaml`.
|
|
32
34
|
- `selfAssessment` in a `chapter.yaml`: written in Commit, skill
|
|
33
35
|
`lernapps-explainer-self-assessment`. An exercise it names renamed or moved → change the reference too.
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/explainer/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Map the content
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/interactive/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Parts
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/quiz/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Map the content
|
package/generator/create.ts
CHANGED
|
@@ -53,7 +53,7 @@ It needs the plan of the first version, confirmed by the creator: started from t
|
|
|
53
53
|
tooling is moved to .vibe/plans/01-first-version.md. Without a plan, it writes nothing and says what to do.
|
|
54
54
|
|
|
55
55
|
Run it in the folder lernapps init prepared, from the tooling init installed:
|
|
56
|
-
npx lernapps create --archetype <name> [<dir>]
|
|
56
|
+
npx --no -- lernapps create --archetype <name> [<dir>]
|
|
57
57
|
It needs git, and the npm registry for the npm install that follows. The app then depends on the version of
|
|
58
58
|
@lernapps/tooling that created it, and its workflows use the actions of that version's tag.
|
|
59
59
|
|
|
@@ -174,9 +174,9 @@ function contents(dir: string): string[] {
|
|
|
174
174
|
if (name === "node_modules" || name === "package-lock.json") return [];
|
|
175
175
|
if (name === "package.json" && readJson(join(dir, name)).lernapps?.init === true) return [];
|
|
176
176
|
if (name === ".vibe") {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
);
|
|
177
|
+
// the planning folder: the plans are checked (a first version has one), what the planning leaves beside them stays
|
|
178
|
+
// (the sketches of the plan, .vibe/sketches/)
|
|
179
|
+
return existsSync(join(dir, PLANS)) ? within(PLANS, (file) => PLAN_NAME.test(file)) : [];
|
|
180
180
|
}
|
|
181
181
|
if ((name === ".agents" || name === ".claude") && skills.size > 0) {
|
|
182
182
|
return within(name, (folder) => folder === "skills").concat(
|
|
@@ -384,7 +384,7 @@ export function create(args: string[]): number {
|
|
|
384
384
|
const found = contents(dir);
|
|
385
385
|
if (found.length > 0) {
|
|
386
386
|
throw new CreateError(
|
|
387
|
-
`${dir} is not empty (${found.slice(0, 5).join(", ")}${found.length > 5 ? ", ..." : ""}): create the app in an empty folder; only .git, the first version's plan .vibe/plans/01-<short name>.md and what lernapps init wrote (its skills, package.json, package-lock.json and node_modules) may be there`,
|
|
387
|
+
`${dir} is not empty (${found.slice(0, 5).join(", ")}${found.length > 5 ? ", ..." : ""}): create the app in an empty folder; only .git, .vibe/ (the first version's plan .vibe/plans/01-<short name>.md, and its sketches) and what lernapps init wrote (its skills, package.json, package-lock.json and node_modules) may be there`,
|
|
388
388
|
);
|
|
389
389
|
}
|
|
390
390
|
const plan = confirmedPlan(dir, archetype, values.plan);
|
package/generator/init.ts
CHANGED
|
@@ -24,6 +24,7 @@ export const INIT_USAGE = `Usage: lernapps init <short name> [--addon <package>]
|
|
|
24
24
|
|
|
25
25
|
Starts an app in the current folder, which must be empty except for .git. It needs git, Node and the npm registry; nothing
|
|
26
26
|
else. In order:
|
|
27
|
+
git repository on the branch work, which the plan names (unless the folder is one already; no commit)
|
|
27
28
|
package.json names the folder, depends on @lernapps/tooling (this version) and the add-on
|
|
28
29
|
npm install installs them
|
|
29
30
|
.vibe/plans/01-<short name>.md
|
|
@@ -61,6 +62,24 @@ const SKILLS_BIN = () => {
|
|
|
61
62
|
return join(dirname(manifest), bin?.["skills"] ?? "bin/cli.mjs");
|
|
62
63
|
};
|
|
63
64
|
|
|
65
|
+
/** The branch the plan works on (rule 8 of the plan template). */
|
|
66
|
+
export const WORK_BRANCH = "work";
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Makes the folder a git repository on the branch `work`, which the plan names, unless it is one already: `create` and
|
|
70
|
+
* the hooks need it, and the plan's first rule is to work there. Returns what it did, for the output; no commit.
|
|
71
|
+
*/
|
|
72
|
+
export function ensureRepository(dir: string): string | undefined {
|
|
73
|
+
if (existsSync(join(dir, ".git"))) return undefined;
|
|
74
|
+
const result = spawnSync("git", ["init", "--quiet", `--initial-branch=${WORK_BRANCH}`], {
|
|
75
|
+
cwd: dir,
|
|
76
|
+
encoding: "utf8",
|
|
77
|
+
});
|
|
78
|
+
if (result.error) throw new CreateError(`git cannot run: ${result.error.message}. Install git, then run init again`);
|
|
79
|
+
if (result.status !== 0) throw new CreateError(`git init failed: ${`${result.stdout}${result.stderr}`.trim()}`);
|
|
80
|
+
return `a git repository on the branch ${WORK_BRANCH}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
64
83
|
/** The names of the skills of the archetypes, with the archetype each belongs to (lernapps-<archetype>[-…]). */
|
|
65
84
|
export function archetypeSkills(): { name: string; archetype: string }[] {
|
|
66
85
|
const dir = fromPackage("skills", "archetypes");
|
|
@@ -129,6 +148,7 @@ export function init(args: string[]): number {
|
|
|
129
148
|
);
|
|
130
149
|
}
|
|
131
150
|
const addon = values.addon;
|
|
151
|
+
const repository = ensureRepository(dir);
|
|
132
152
|
writeJson(join(dir, "package.json"), {
|
|
133
153
|
name: slug(dir),
|
|
134
154
|
version: "0.0.0",
|
|
@@ -157,7 +177,7 @@ export function init(args: string[]): number {
|
|
|
157
177
|
archetypeSkills().map((skill) => skill.name),
|
|
158
178
|
);
|
|
159
179
|
process.stdout.write(
|
|
160
|
-
`lernapps init: ${relative(dir, target)} from ${relativeTemplate(template, dir)}; the skills of the packages are installed\nNext: read ${relative(dir, target)} completely and follow it\n`,
|
|
180
|
+
`lernapps init: ${relative(dir, target)} from ${relativeTemplate(template, dir)}; the skills of the packages are installed${repository ? `; ${repository}` : ""}\nNext: read ${relative(dir, target)} completely and follow it\n`,
|
|
161
181
|
);
|
|
162
182
|
return 0;
|
|
163
183
|
}
|
package/generator/update.ts
CHANGED
|
@@ -75,8 +75,8 @@ moves the app within its version ranges; this moves the ranges, and what npm doe
|
|
|
75
75
|
|
|
76
76
|
Run it from the latest tooling, in the app's folder, e.g. to pick up a fixed runtime:
|
|
77
77
|
${LATEST}
|
|
78
|
-
Run as the app's own tooling (npx lernapps update), it knows only the versions the app already has.
|
|
79
|
-
Then run npx lernapps check, and commit package.json, package-lock.json, .github/workflows/ and what else it names.
|
|
78
|
+
Run as the app's own tooling (npx --no -- lernapps update), it knows only the versions the app already has.
|
|
79
|
+
Then run npx --no -- lernapps check, and commit package.json, package-lock.json, .github/workflows/ and what else it names.
|
|
80
80
|
|
|
81
81
|
Exit codes: 0 when the app is updated (or was up to date), 1 when it cannot be or only partly (the message says
|
|
82
82
|
what was not moved and why), 2 on a usage error.
|
|
@@ -395,7 +395,7 @@ export function update(args: string[]): number {
|
|
|
395
395
|
}
|
|
396
396
|
// npm install <spec> runs no prepare script: the hooks of the new tooling, as npm install would install them
|
|
397
397
|
if (installHooks([]) !== 0)
|
|
398
|
-
throw new UpdateError("lernapps hooks failed (see above); run npx lernapps hooks again");
|
|
398
|
+
throw new UpdateError("lernapps hooks failed (see above); run npx --no -- lernapps hooks again");
|
|
399
399
|
}
|
|
400
400
|
const changed = moveActions(`v${version}`);
|
|
401
401
|
if (changed.length > 0) lines.push(`the actions of lernapps/tooling in ${changed.join(", ")}: v${version}`);
|
|
@@ -423,7 +423,7 @@ export function update(args: string[]): number {
|
|
|
423
423
|
if (architecture.lines.length > 0) files.push(`${ARCHITECTURE}/`);
|
|
424
424
|
if (plan.some((line) => line.startsWith("plan: moved"))) files.push(".vibe/ (git add -A .vibe, to keep the move)");
|
|
425
425
|
process.stdout.write(
|
|
426
|
-
`Next: npx lernapps check, then commit ${files.slice(0, -1).join(", ")} and ${files.at(-1) ?? ""}\n`,
|
|
426
|
+
`Next: npx --no -- lernapps check, then commit ${files.slice(0, -1).join(", ")} and ${files.at(-1) ?? ""}\n`,
|
|
427
427
|
);
|
|
428
428
|
return 0;
|
|
429
429
|
}
|
|
@@ -100,7 +100,7 @@ questions. -->
|
|
|
100
100
|
`lernapps-<archetype>-design` says, choose its pattern with skill `lernapps-exercise-patterns` (both loaded
|
|
101
101
|
in Explore), and say why the guide's patterns do not fit.
|
|
102
102
|
- [ ] Each new component or interactive exercise: a sketch (static SVG or image, or the steps). Words alone are not
|
|
103
|
-
enough.
|
|
103
|
+
enough. Keep sketch files in `.vibe/sketches/`.
|
|
104
104
|
- [ ] Show the creator, short: goal, new competencies by chapter, slices; in plain words what learners see and do,
|
|
105
105
|
what is new. At most 2 questions.
|
|
106
106
|
- [ ] **Checkpoint:** confirm the plan and the content method. Stop and wait for an explicit yes. Changes → change,
|
|
@@ -137,7 +137,7 @@ cannot. Something new goes into the guide in the slice that adds it. -->
|
|
|
137
137
|
Parallel slices: send each sub-agent `@lernapps/tooling/guidance/subagent-brief.md`, filled in.
|
|
138
138
|
- [ ] The content guide describes the app as it is now (`app-content-matches`). `grep -c "FILL IN"
|
|
139
139
|
.agents/skills/app-content/SKILL.md` prints 0.
|
|
140
|
-
- [ ] `npx lernapps check` passes.
|
|
140
|
+
- [ ] `npx --no -- lernapps check` passes.
|
|
141
141
|
- [ ] Every box of Explore, Plan and Code ticked.
|
|
142
142
|
- [ ] Set `phase: commit`: change the value line (`grep '^phase:'` prints `phase: commit`).
|
|
143
143
|
No checkpoint here: set it before you ask or report anything, then start Commit in the same message.
|
|
@@ -158,7 +158,7 @@ cannot. Something new goes into the guide in the slice that adds it. -->
|
|
|
158
158
|
|
|
159
159
|
- [ ] `grep '^phase:'` prints `phase: commit`; else set it.
|
|
160
160
|
- [ ] An explainer whose pages or exercises changed: load skill `lernapps-explainer-self-assessment`
|
|
161
|
-
(missing → `npx lernapps skills --archetype explainer`). Update the
|
|
161
|
+
(missing → `npx --no -- lernapps skills --archetype explainer`). Update the
|
|
162
162
|
self-assessment as it says (add one, if the app has none and the skill says so). Commit; the hooks check.
|
|
163
163
|
- [ ] Load skill `lernapps-github`. Push the branch, open the preview pull request, see its checks to green as it
|
|
164
164
|
says.
|
|
@@ -68,7 +68,7 @@ questions. -->
|
|
|
68
68
|
- [ ] Choose the archetype as skill `lernapps-app` says, from the kind of practice: read the README of each
|
|
69
69
|
archetype in question, tell the creator what the chosen one can and cannot do. Write it and its reason under
|
|
70
70
|
"Key decisions". Set `archetype`.
|
|
71
|
-
- [ ] Install the archetype's skills: `npx lernapps skills --archetype <archetype>`. Load skill
|
|
71
|
+
- [ ] Install the archetype's skills: `npx --no -- lernapps skills --archetype <archetype>`. Load skill
|
|
72
72
|
`lernapps-<archetype>-design`.
|
|
73
73
|
- [ ] Interview: ask the other topics of "Answers" in order. Skip a topic only when an earlier answer covers it; note
|
|
74
74
|
which. No answer → ask once more; still none → write your assumption with "(guess)". Done when every topic
|
|
@@ -133,7 +133,7 @@ questions. -->
|
|
|
133
133
|
- [ ] Write the Code tasks under "Code": pages or screens, their content, what each shows. Each ends in a commit.
|
|
134
134
|
After the first task that shows real content: the task "Show the creator a first look (`early-preview`)".
|
|
135
135
|
- [ ] Each screen, component or interactive exercise: a sketch (static SVG or image, or the steps with what
|
|
136
|
-
learners see after each). Words alone are not enough.
|
|
136
|
+
learners see after each). Words alone are not enough. Keep sketch files in `.vibe/sketches/`, which `create` leaves alone.
|
|
137
137
|
- [ ] Show the creator, short: goal, competencies by chapter, entry draft, tasks, sketches; the content method in
|
|
138
138
|
plain words (what learners see and do, what it cannot do). At most 2 questions.
|
|
139
139
|
- [ ] **Checkpoint:** confirm the plan and the content method, with the sketches shown. Stop and wait for an
|
|
@@ -173,7 +173,7 @@ checks and cannot; how a later agent adds a chapter. Becomes the content guide i
|
|
|
173
173
|
- [ ] <the tasks written in Plan; after each, commit on `work`; after the first with real content, show the
|
|
174
174
|
creator a first look (`early-preview`) and go on>
|
|
175
175
|
- [ ] The content guide matches what was built (`app-content-matches`).
|
|
176
|
-
- [ ] `npx lernapps check` passes.
|
|
176
|
+
- [ ] `npx --no -- lernapps check` passes.
|
|
177
177
|
- [ ] Look at a screenshot of every screen and state (start, each mode, pause, end), desktop and 360 px. Compare
|
|
178
178
|
each with the confirmed sketches.
|
|
179
179
|
- [ ] Every box of Explore, Plan and Code ticked.
|
|
@@ -195,7 +195,7 @@ checks and cannot; how a later agent adds a chapter. Becomes the content guide i
|
|
|
195
195
|
### Tasks
|
|
196
196
|
|
|
197
197
|
- [ ] `grep '^phase:'` prints `phase: commit`; else set it.
|
|
198
|
-
- [ ] An explainer: load skill `lernapps-explainer-self-assessment` (missing → `npx lernapps skills --archetype
|
|
198
|
+
- [ ] An explainer: load skill `lernapps-explainer-self-assessment` (missing → `npx --no -- lernapps skills --archetype
|
|
199
199
|
explainer`). Add the self-assessment as it says, or
|
|
200
200
|
write under "Key decisions" why the app has none. Commit; the hooks check.
|
|
201
201
|
- [ ] Load skill `lernapps-github`. Repo and Pages as it says: ask the repo name and every click only the creator can
|
|
@@ -18,7 +18,7 @@ Competencies, one slice each, in this order:
|
|
|
18
18
|
Change only: <the files of this chapter or round>. Do not change: the content guide, the plan, <the shared files>.
|
|
19
19
|
Write what the shared files need into your report instead.
|
|
20
20
|
|
|
21
|
-
Per slice: content, exercise, `npx lernapps check` green, one commit. Never bypass a hook.
|
|
21
|
+
Per slice: content, exercise, `npx --no -- lernapps check` green, one commit. Never bypass a hook.
|
|
22
22
|
|
|
23
23
|
Report: branch, commits, per competency the ids of its page or questions and exercises, the patterns used, what the
|
|
24
24
|
shared files need, what you could not verify.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lernapps/tooling",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Shared tooling of the lernapps.net apps and sites: the CLI lernapps, site actions, Renovate preset, guidance for building apps; documentation at https://lernapps.net/tooling/",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"@doctc/arc42": "0.38.0",
|
|
118
|
-
"@lernapps/site": "github:lernapps/lernapps.github.io#
|
|
118
|
+
"@lernapps/site": "github:lernapps/lernapps.github.io#96912a0b6691d90a538ac8336ac808152a7a2227",
|
|
119
119
|
"@types/node": "26.6.5",
|
|
120
120
|
"ajv": "8.20.0",
|
|
121
121
|
"vite-plus": "1.4.0"
|
|
@@ -28,6 +28,8 @@ license: MIT
|
|
|
28
28
|
|
|
29
29
|
- A build problem is one line `file:line: place (language): what to do`. Fix where it points.
|
|
30
30
|
- Headings are `section` blocks, never Markdown headings.
|
|
31
|
+
- YAML: quote a text that has `: ` in it or looks like a number (`"8."`, `"01000001"`, `"0"`). Unquoted, YAML reads a map or a
|
|
32
|
+
number: the build stops, or the digits change. A table cell, a header cell too, is a text and never empty.
|
|
31
33
|
- A new chapter: a folder with `chapter.yaml`, listed in `src/app.yaml`, each page listed in `chapter.yaml`.
|
|
32
34
|
- `selfAssessment` in a `chapter.yaml`: written in Commit, skill
|
|
33
35
|
`lernapps-explainer-self-assessment`. An exercise it names renamed or moved → change the reference too.
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/explainer/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Map the content
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/interactive/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Parts
|
|
@@ -15,7 +15,7 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
## Can and cannot
|
|
17
17
|
|
|
18
|
-
- The README of the template says it:
|
|
18
|
+
- The README of the template says it: `node_modules/@lernapps/app-templates/quiz/README.md` (in the folder `init` made).
|
|
19
19
|
Read it before this skill's mapping, if you have not yet.
|
|
20
20
|
|
|
21
21
|
## Map the content
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| `true-false` | `answer` (true or false) |
|
|
8
8
|
| `number` | `answer`, `tolerance` (0 = exact), `unit` if any; the learner may type a comma or a point |
|
|
9
9
|
| `ordering` | `items` in the right order; the page mixes them |
|
|
10
|
-
| `matching` | `pairs` as they belong
|
|
10
|
+
| `matching` | `pairs` as they belong, each pair an object `{ left, right }`; the page mixes the right side. `distractors` (1 to 4): wrong right entries that match no left one. `pairsFrom: material` instead of `pairs` takes them from the `labelled-figure` in `material` (marker left, text right; the figure needs `legend: false`) |
|
|
11
11
|
|
|
12
12
|
- Every question: `id`, `text`, `explanation`, at least one link in `links`. Optional quiz `sources`.
|
|
13
13
|
- Types without options carry their background in `explanation`.
|
|
@@ -15,8 +15,8 @@ license: MIT
|
|
|
15
15
|
|
|
16
16
|
- Orientation for grade and order, not a condition. None found → say so once; go on.
|
|
17
17
|
- Only the Land's official document (Kerncurriculum, Lehrplan, Bildungsplan, Rahmenlehrplan) from the ministry or
|
|
18
|
-
state institute. No publisher, schoolbook or portal. No Land known → KMK-Bildungsstandards.
|
|
19
|
-
- Download and read it yourself.
|
|
18
|
+
state institute. No publisher, schoolbook or portal. No Land known → KMK-Bildungsstandards. The KMK has none for the subject or level (e.g. Informatik in Sekundarstufe II) → cite no unit, write "not checked" and follow the creator's material.
|
|
19
|
+
- Download and read it yourself. A document you cannot read here (a PDF and no tool to read it) → mark it "not checked"; never cite it from its title alone.
|
|
20
20
|
- Cite it under "Notes": title, issuer, year, address; page and unit (Inhaltsfeld, Lernbereich, Kompetenz).
|
|
21
21
|
- The creator's material differs → follow the material; say so in one sentence.
|
|
22
22
|
|
|
@@ -33,6 +33,7 @@ license: MIT
|
|
|
33
33
|
|
|
34
34
|
- Per competency one article or video (serlo.org, a channel the creator trusts, Wikipedia).
|
|
35
35
|
- Read [references/sources.md](references/sources.md) before you choose, cite or rely on a source.
|
|
36
|
+
- A text source (Wikipedia, a schoolbook site): take facts, never sentences. Copying a sentence needs the licence the page states; if you cannot read it, do not copy.
|
|
36
37
|
|
|
37
38
|
## 4. The creator's material and privacy
|
|
38
39
|
|
|
@@ -27,11 +27,13 @@ license: MIT
|
|
|
27
27
|
|
|
28
28
|
## What each archetype can do
|
|
29
29
|
|
|
30
|
+
The READMEs are files of the package `@lernapps/app-templates`, which `init` installed: read them from the folder, in full.
|
|
31
|
+
|
|
30
32
|
| Archetype | Learners … | Can and cannot (README of its template) |
|
|
31
33
|
|---|---|---|
|
|
32
|
-
| `quiz` | answer questions with options and feedback |
|
|
33
|
-
| `explainer` | read pages that explain, each with exercises |
|
|
34
|
-
| `interactive` | act in one app page, by turns or in real time |
|
|
34
|
+
| `quiz` | answer questions with options and feedback | `node_modules/@lernapps/app-templates/quiz/README.md` |
|
|
35
|
+
| `explainer` | read pages that explain, each with exercises | `node_modules/@lernapps/app-templates/explainer/README.md` |
|
|
36
|
+
| `interactive` | act in one app page, by turns or in real time | `node_modules/@lernapps/app-templates/interactive/README.md` |
|
|
35
37
|
|
|
36
38
|
## Choose the archetype
|
|
37
39
|
|
|
@@ -15,7 +15,7 @@ Each slice is one Code task and ends in one commit:
|
|
|
15
15
|
3. Exercise: a pattern of the guide, varied. A new pattern goes into the guide in the same slice, with example and
|
|
16
16
|
data file.
|
|
17
17
|
4. Entry topic: the page or section path into the plan's entry draft (`entry-links-resolve`).
|
|
18
|
-
5. Check: `npx lernapps check` passes.
|
|
18
|
+
5. Check: `npx --no -- lernapps check` passes.
|
|
19
19
|
6. Commit, guide changes included.
|
|
20
20
|
|
|
21
21
|
- A new chapter or round: its slices in the order of the guide's procedure.
|
|
@@ -14,7 +14,7 @@ license: MIT
|
|
|
14
14
|
## Create
|
|
15
15
|
|
|
16
16
|
1. Only after the creator's yes to the plan (`explore-before-code`). In the plan's folder:
|
|
17
|
-
`npx lernapps create --archetype <archetype>`.
|
|
17
|
+
`npx --no -- lernapps create --archetype <archetype>`.
|
|
18
18
|
2. No git repo yet: `git init --initial-branch=work`. Then `npm install` (dependencies, git hooks), and commit
|
|
19
19
|
everything on `work`.
|
|
20
20
|
3. Needs git, Node ≥ 22.18, registry.npmjs.org. Blocked → ask the creator to allow it, run again. Never write the
|
|
@@ -29,20 +29,20 @@ license: MIT
|
|
|
29
29
|
|
|
30
30
|
## Check
|
|
31
31
|
|
|
32
|
-
- `npx lernapps check`: format, lint, types, unit tests, build, checks of the built app, end-to-end tests. The hooks
|
|
32
|
+
- `npx --no -- lernapps check`: format, lint, types, unit tests, build, checks of the built app, end-to-end tests. The hooks
|
|
33
33
|
run its parts (`--pre-commit`, `--pre-push`); CI runs it whole.
|
|
34
|
-
- Report: `node_modules/.cache/lernapps/validation-report.yaml`. Options: `npx lernapps check --help`.
|
|
34
|
+
- Report: `node_modules/.cache/lernapps/validation-report.yaml`. Options: `npx --no -- lernapps check --help`.
|
|
35
35
|
|
|
36
36
|
## Look at the app
|
|
37
37
|
|
|
38
38
|
A check says the rules hold; only a look says what a learner sees. Show the creator the pages before a push, and before
|
|
39
39
|
a submission they declare something about.
|
|
40
40
|
|
|
41
|
-
- Explainer or quiz: build (`npx vp build`), then `npx lernapps screenshots`. It writes one image of every page, one of
|
|
41
|
+
- Explainer or quiz: build (`npx vp build`), then `npx --no -- lernapps screenshots`. It writes one image of every page, one of
|
|
42
42
|
every figure, and an `index.html` that shows them in order to `screenshots/` (not part of the app: do not commit it).
|
|
43
43
|
Show the images, or the `index.html` where you can show HTML. Check every figure in its own image
|
|
44
44
|
(`…-figure-<n>.png`): a page image is scaled down, its details are not readable. `--desktop` adds 1280 px images.
|
|
45
|
-
Options: `npx lernapps screenshots --help`.
|
|
45
|
+
Options: `npx --no -- lernapps screenshots --help`. The folder ignores itself in git, so a later check never sees it.
|
|
46
46
|
- Interactive app: `screenshots` does not support it. Open the built app with the Playwright the tooling installs
|
|
47
47
|
(`import { chromium } from "playwright"`), at 390 px width, and take `page.screenshot({ fullPage: true })` of each
|
|
48
48
|
state the creator should see, from a short script outside the app.
|