From 5a0e633fbc9cbbc3ac3d670fefe8accad4b1e95c Mon Sep 17 00:00:00 2001 From: Aleksandr Shevchuk Date: Thu, 12 Nov 2026 21:45:23 +0200 Subject: [PATCH 1/3] feat(author): the skill names the build tool's schema command where npx cannot install --- design/author.md | 8 +++++++- skills/h5p-author/SKILL.md | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/design/author.md b/design/author.md index 4b8107e..10267cb 100644 --- a/design/author.md +++ b/design/author.md @@ -212,7 +212,13 @@ to 3,000. Twenty-four things the code does not say by itself: conditions; interface texts and the fields a layout sets left out. The weekly pack refresh runs `sync:skill`; `apps/skills`' test fails on a file out of date, and builds and plays every example. 28 content types have files, and the parts other content holds (Text, Image, Video); - any other type's fields are one `h5p-author schema` away. + any other type's fields are one `h5p-author schema` away. Where npm cannot install, SKILL.md + names that command for the one-file tool with the type's bundle, `node h5p-author.mjs schema + --libraries parts` (2026-11-12): given only the npx form, Haiku reading the skill by its + link with no registry ran the tool without `--libraries` in 4 of 4 runs and met Node's "Cannot + find package '@missing-elements/h5p-libraries'", and one of them gave the tool up and wrote a + Crossword from memory; given the command, 4 of 4 had the fields at once and built a package + the verifier passed (Crossword and Find the Words, two runs each). - **The editor is pinned, and not watched** (2026-11-01, the owner's choice, as for the content check). Nothing the editor does decides whether a package plays: the libraries and the platforms' validator do, both pinned here too. A change in the editor makes a build differ from what the diff --git a/skills/h5p-author/SKILL.md b/skills/h5p-author/SKILL.md index 477e4c7..f6360a2 100644 --- a/skills/h5p-author/SKILL.md +++ b/skills/h5p-author/SKILL.md @@ -66,7 +66,9 @@ a name made up for them. | H5P.GameMap | stages on a map, each with exercises (a map) | Media come from the user; never invent them. For a type not listed, run -`npx @missing-elements/h5p-author@latest schema ` and say it has no notes here. Never +`npx @missing-elements/h5p-author@latest schema ` and say it has no notes here. Where npx +cannot install, fetch the build tool and that type's bundle as step 3 says, unzip the bundle, and +run `node h5p-author.mjs schema --libraries parts` instead. Never read a library's semantics or code yourself: the type file and `schema` say what a source may write, and an agent that works it out from the library spends two to three times as much for the same package. From da70f4c4f8f7933c3e88d21ebc05b3f13ec478a1 Mon Sep 17 00:00:00 2001 From: Aleksandr Shevchuk Date: Thu, 12 Nov 2026 21:45:29 +0200 Subject: [PATCH 2/3] feat(author): the hand-over gives one web address, the build page's link --- design/author.md | 73 +++++++++++++++++++++----------------- skills/h5p-author/SKILL.md | 40 ++++++++++----------- 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/design/author.md b/design/author.md index 10267cb..91bb25a 100644 --- a/design/author.md +++ b/design/author.md @@ -589,45 +589,54 @@ to 3,000. Twenty-four things the code does not say by itself: gaps, the two checks report nothing; over the 524 distinct sources these tests stored, 199 of the two types with 765 gaps, only the 14 known to play wrong. Not tried: a text edited afterwards in H5P's own editor, whose rich-text widget may write an entity back as its character. -- **The hand-over carries the source, its link to the build page and where to say how it went** - (2026-11-12, #190). The owner wants people to try the skill and to hear from them. The build - page asks how it went, by email first, since a teacher may have no GitHub account, or in a - GitHub discussion; but a chat that builds the package itself hands it over in the chat, and its - user never sees that page. The organisation's site counts no visits, and the repository's - discussions held no feedback. So step 5 hands over, beside the package, the source as a file - under the package's name with `.source.json`, which the page opens too, and both lines step 3's - command prints: the page's link that carries the source and, under it, where to say how it - went, `https://missing-elements.github.io/h5p/build/#feedback-heading`, the page's own section, - so where feedback goes stays the site's to change, in one place. That address is a contract - with every installed copy, as `#source=` is: the page keeps the id. A fragment with no `source` - builds nothing (`sourceFromFragment` reads `source` alone), and in Chromium, 1280 and 390 px - wide, the section is in view once the page has settled. +- **The hand-over carries the source and one web address, the build page's link** (2026-11-12, + #190; cut to one address the same evening, the owner's call). The owner wants people to try + the skill and to hear from them. The build page asks how it went at its foot, by email first, + since a teacher may have no GitHub account, or in a GitHub discussion; but a chat that builds + the package itself hands it over in the chat, and its user sees that page only if the reply + sends them there. So step 5 hands over, beside the package, the source as a file under the + package's name with `.source.json`, which the page opens too, and the link step 3's command + prints, which carries the source: where the user plays the package in any browser, changes the + source and builds it again, and says how it went at the foot of the page. It is the reply's one + web address. + + 0.9.5 handed over a second line, printed by the same command under the link: `How did it go? + Say so by email or on GitHub: https://missing-elements.github.io/h5p/build/#feedback-heading`. + With it and the rest of step 5's list, a finished reply held two or three web addresses beside + the package's files, the link, that line and the pack's `libraries.txt` on GitHub, and with them + the preview command, three tools to go to next and, where the verifier ran, its report and + revision. The owner found that too many links and kept the link alone: the libraries' licences + stay a sentence, the preview command goes over only where there is no link, the screenshot + without the report. The page keeps the id `feedback-heading`, whose address installed copies of + 0.9.5 print; that fragment has no `source`, so it builds nothing (`sourceFromFragment` reads + `source` alone). Measured on Haiku in Claude Code's place (the skill, a shell, npm, the verifier left out), a three-question Question Set with the author and licence given. With 0.9.4's text, 2 of 3 runs - handed the source over as a file, unasked, and none a link or where to say how it went. With - the new text, all 14 runs handed over the source file and a link that decodes to the source - byte for byte, 1,230 to 1,460 characters for three questions. Where to say how it went was the - hard part, since a weak model shortens step 5's list as it writes it out: as an item of the - list, last or third, it reached 3 of 6 replies; told to end the reply with it, 3 of 4; printed - by step 3's command under the link, 3 of 4, and the fourth sent the user to the link's page to - say how it went, where every other miss said nothing. The command is kept: what a command - printed is what a weak model hands over, and the line goes wherever the link goes, the bundle - route included. With step 5 saying the line goes in every case, it reached 5 of 5, two plain - sources and three with a picture. + handed the source over as a file, unasked, and none a link. With 0.9.5's, all 14 runs handed + over the source file and a link that decodes to the source byte for byte, 1,230 to 1,460 + characters for three questions, and the feedback line, printed by the command, reached 5 of 5 + replies once step 5 said it goes in every case; as an item of step 5's list it had reached 3 of + 6, since a weak model shortens the list as it writes it out. With the one address, 3 of 3 runs + handed over the source file and the link, exact, as the reply's only web address, and none the + feedback line, the `libraries.txt` link, the next tools or the preview command; the replies ran + 2,250 to 2,737 characters, against 3,146 and 3,724. None of the three said to tell how it went + at the page's foot: what step 5 asks a chat to write itself is what a weak model drops, so + feedback on a package built in a chat now rests on its user scrolling the page. A link carries the text of a source and not the files it names (cubic's review): the page asks for those by name once it has the source, and a picture at a web address reaches it only where its host lets another site fetch it. So for a source that names a file, by any `path`, the - commands print the feedback line alone, and in the build page's route such a source goes over - whole, to be pasted, its files chosen on the page. It is decided by the source and not by its - type: nearly every type takes media, Multiple Choice, Question Set, Column, a book and slides - among them, and most sources name none. The source file goes over as before, the files it names - said by name, since a build reads them beside it; they are not copied, a video being large. - When the commands printed a line saying why there was no link, above the feedback line, 3 of 3 - runs with a picture passed on neither: they wrote the reason in their own words and left the - address out. With the feedback line printed alone, 3 of 3 passed it on, none gave a link, and 2 - of 3 named the picture. + commands print why there is no link instead (`No link: the source names files, which a link + cannot carry.`), and in the build page's route such a source goes over whole, to be pasted, its + files chosen on the page. It is decided by the source and not by its type: nearly every type + takes media, Multiple Choice, Question Set, Column, a book and slides among them, and most + sources name none. The source file goes over as before, the files it names said by name, since a + build reads them beside it; they are not copied, a video being large. 0.9.5's commands printed + the feedback line alone for such a source, since a reason printed above that line had cost the + address in 3 of 3 runs; with no address left to lose, the reason is printed. With the + one-address text, 2 of 2 runs with a picture gave no web address, and handed over the source + file and the preview command, the one way left there to play it. - **The skill names no product** (2026-11-12, the owner's call). Its routes were told apart by the apps they were measured in; they now say what each needs: a shell that reaches the npm registry, Node and a download where npm cannot install, or nothing that runs or fetches. What a diff --git a/skills/h5p-author/SKILL.md b/skills/h5p-author/SKILL.md index f6360a2..085aa22 100644 --- a/skills/h5p-author/SKILL.md +++ b/skills/h5p-author/SKILL.md @@ -155,12 +155,12 @@ for the user to play it before using it. **Where nothing can be fetched or run, the build page builds it.** No shell, no Node, or no download: [the build page](https://missing-elements.github.io/h5p/build/) builds the same package in the user's browser from the source alone, with no install. Give them a link that carries the source, written -with Node or Python, which need no network, and the line under it, where to say how it went. A -source that names files gets that line alone: a link carries its text, not the files: +with Node or Python, which need no network. A source that names files gets none: a link carries +its text, not the files: ```bash -node -e "const s=require('fs').readFileSync('source.json'),f=[];JSON.parse(s,(k,v)=>(k==='path'&&typeof v==='string'&&f.push(v),v));f.length||console.log('https://missing-elements.github.io/h5p/build/#source='+require('zlib').deflateRawSync(s).toString('base64url'));console.log('How did it go? Say so by email or on GitHub: https://missing-elements.github.io/h5p/build/#feedback-heading')" -python3 -c "import base64,json,zlib;s=open('source.json','rb').read();f=[];json.loads(s,object_hook=lambda o:(isinstance(o.get('path'),str) and f.append(o['path']),o)[1]);c=zlib.compressobj(9,zlib.DEFLATED,-15);d=c.compress(s)+c.flush();f or print('https://missing-elements.github.io/h5p/build/#source='+base64.urlsafe_b64encode(d).decode().rstrip('='));print('How did it go? Say so by email or on GitHub: https://missing-elements.github.io/h5p/build/#feedback-heading')" +node -e "const s=require('fs').readFileSync('source.json'),f=[];JSON.parse(s,(k,v)=>(k==='path'&&typeof v==='string'&&f.push(v),v));console.log(f.length?'No link: the source names files, which a link cannot carry.':'https://missing-elements.github.io/h5p/build/#source='+require('zlib').deflateRawSync(s).toString('base64url'))" +python3 -c "import base64,json,zlib;s=open('source.json','rb').read();f=[];json.loads(s,object_hook=lambda o:(isinstance(o.get('path'),str) and f.append(o['path']),o)[1]);c=zlib.compressobj(9,zlib.DEFLATED,-15);d=c.compress(s)+c.flush();print('No link: the source names files, which a link cannot carry.' if f else 'https://missing-elements.github.io/h5p/build/#source='+base64.urlsafe_b64encode(d).decode().rstrip('='))" ``` **A link is only what one of these commands printed here, handed over whole: no command run, no @@ -209,31 +209,27 @@ npx @missing-elements/h5p-verify@latest course.h5p --preview Run it in the background; it ends once its tab has closed. Ask the user to work through all of it, wrong answers included; its Download button saves a copy. Where the command does not run on -the user's computer, hand over the file and the command. If you already have a browser tool, -add `--no-open` and play the address it prints with that tool. Do not write a browser script to -do it: the person's own play is the check, and a script of your own costs more than the build. +the user's computer, hand over the file, and the command where step 3 printed no link. If you +already have a browser tool, add `--no-open` and play the address it prints with that tool. Do +not write a browser script to do it: the person's own play is the check, and a script of your +own costs more than the build. Deliver: - the `.h5p`, and its source as a file beside it, under the package's name with `.source.json` (`course.source.json`), copied as the package was; the build page opens it too. Name the files it names, if any: a build reads them beside it; -- what one of step 3's two commands printed here for this source, handed over whole: the build - page's link that carries it, where the user plays the package in any browser, changes the source - and builds it again (none for a source that names files, which a link cannot carry), and in - every case the line where they can say how it went. A link is only what one of them printed; - where neither runs, there is none; -- `report.json`, `screenshot.png` and the report's full `revision`, from the run that passed; - where it could not run, no report and call the package **unverified**; where it ran but failed, - give its report and reasons and say the package **failed verification**; -- the preview command, and the build's notes; +- the link one of step 3's two commands printed here for this source, handed over whole: the + build page, where the user plays the package in any browser, changes the source and builds it + again, and says how it went at the foot of the page. A link is only what one of them printed: + none for a source that names files, and none where neither runs. Give no other web address; +- `screenshot.png` from the run that passed; where it could not run, call the package + **unverified**; where it ran but failed, give its reasons and say the package **failed + verification**; +- the build's notes, and the preview command where there is no link; - what a pass means: it starts and draws, not that it is accurate, accessible or right for every LMS; - that it carries the editor libraries an H5P site's upload check asks for, so a Moodle with no library installed accepts it (the one site tried); -- that it carries H5P's libraries, each under its own licence, most MIT, listed in the pack's - [`libraries.txt`](https://github.com/missing-elements/h5p-offline-player/blob/main/packages/libraries/libraries.txt), - so the user checks those terms before they distribute it; -- where it goes next: the H5P Preview extension (`MissingElements.h5p-preview`) plays it in - VS Code, Cursor or VSCodium, `h5p-player-setup` puts it on a website, and `h5p-to-scorm` - makes it a SCORM zip for an LMS. +- that it carries H5P's libraries, each under its own licence, most MIT, so the user checks + those terms before they distribute it. From b665e4859f7be37edbd55267fcda7ec9a4737388 Mon Sep 17 00:00:00 2001 From: Aleksandr Shevchuk Date: Thu, 12 Nov 2026 23:37:35 +0200 Subject: [PATCH 3/3] fix(author): where nothing is built here, the hand-over is the build page route's cubic's review of #193: step 5's list gave no other web address and the preview command where there is no link, so read alone it took the page's address from a chat that has only the source to paste, and gave it a command for a package that does not exist. Step 5 now opens by sending that case to step 3's build page route (the link, or the whole source and the page's address), and step 3's paragraph for it names the address and holds only where nothing is built here. Haiku as a chat with no tools: 5 of 5 replies right before and after (source in a json block, the page's address, no link, no preview command, the picture named). In Claude Code's place: 2 of 2 Question Sets the exact link alone, the picture run no address and the preview command. --- design/author.md | 14 ++++++++++++++ skills/h5p-author/SKILL.md | 21 ++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/design/author.md b/design/author.md index 91bb25a..6763102 100644 --- a/design/author.md +++ b/design/author.md @@ -637,6 +637,20 @@ to 3,000. Twenty-four things the code does not say by itself: address in 3 of 3 runs; with no address left to lose, the reason is printed. With the one-address text, 2 of 2 runs with a picture gave no web address, and handed over the source file and the preview command, the one way left there to play it. + + Where nothing is built in the chat, step 3's build page route is the whole hand-over (cubic's + review of #193): the link a command printed or, where none was, the whole source in a `json` + block and the page's address, then the reply's one web address. Step 5 opens by saying so, and + step 3's paragraph for that case names the address and holds only where nothing is built: read + alone, step 5's list, which gives no other web address and the preview command where there is + no link, would take the page's address from a chat that has only the source, and hand it a + command for a package that does not exist. Haiku as a chat with no tools, the skill's text and + the type's file pasted in, had done right before: 5 of 5 replies, three Question Sets and two + Multiple Choice questions naming the user's picture, gave the source in one `json` block beside + the page's address, no link and no preview command, and named the picture to choose on the + page; with the change, 5 of 5 again. It is for a model that reads step 5's list to the letter. + In Claude Code's place it changed nothing: 2 of 2 Question Sets handed over the exact link + alone, and the picture run no address and the preview command. - **The skill names no product** (2026-11-12, the owner's call). Its routes were told apart by the apps they were measured in; they now say what each needs: a shell that reaches the npm registry, Node and a download where npm cannot install, or nothing that runs or fetches. What a diff --git a/skills/h5p-author/SKILL.md b/skills/h5p-author/SKILL.md index 085aa22..dfff72d 100644 --- a/skills/h5p-author/SKILL.md +++ b/skills/h5p-author/SKILL.md @@ -168,14 +168,15 @@ link.** Never write a `#source=` link yourself, from memory or after an example, for one: its text is compressed, so it cannot be typed, and one wrong character leaves the page nothing to build. -Where they print no link, with neither, or with no tool that runs anything at all (a chat's code -tool can be unavailable for hours), give no link: the page sees only what the user pastes, so put the **whole source in -your reply**, in one `json` code block, and tell them to paste it into the page. Never give the -page's address without the source, in the link or beside it: it builds nothing. The page lists -every problem by its path, with a button that copies them for the chat: fix them all and give a -new link, or the whole source again. A source that names files of its own waits for the user to -choose them there. Steps 4 and 5 are then the user's, on that page: the package is **unverified** -until they have played it there, and they download it from there. +Where nothing is built here and they print no link, with neither, or with no tool that runs +anything at all (a chat's code tool can be unavailable for hours), give no link: the page sees +only what the user pastes, so put the **whole source in your reply**, in one `json` code block, +and tell them to paste it into the page at https://missing-elements.github.io/h5p/build/. Never +give the page's address without the source, in the link or beside it: it builds nothing. The +page lists every problem by its path, with a button that copies them for the chat: fix them all +and give a new link, or the whole source again. A source that names files of its own waits for +the user to choose them there. Steps 4 and 5 are then the user's, on that page: the package is +**unverified** until they have played it there, and they download it from there. A source with a problem writes nothing: the build lists every problem by its path, so fix them all and run it again under the same name. Once a build has written its file it never writes @@ -201,7 +202,9 @@ removing what fails. Without a browser, say the package is **unverified**. ## 5. Review and hand over -Check answers and feedback against the material. Then let the user play it in their browser: +Check answers and feedback against the material. Where nothing was built here, step 3's build +page route is the whole hand-over: the link it printed, or the whole source and the page's +address. Otherwise let the user play it in their browser: ```bash npx @missing-elements/h5p-verify@latest course.h5p --preview