diff --git a/design/author.md b/design/author.md index 499e2e0..4b8107e 100644 --- a/design/author.md +++ b/design/author.md @@ -15,7 +15,7 @@ already holds text to the content check's rules, from the pack an untrusted chec `apps/skills` plays every example untrusted too. Measured on a five-question quiz, at four characters a token: `content.json` was about 3,470 tokens to write by hand, after reading 3,900 to 9,500 of a type's semantics; the source is 1,000 to 1,800 tokens, written from a type file of 200 -to 3,000. Nineteen things the code does not say by itself: +to 3,000. Twenty-four things the code does not say by itself: - **One generator, three ways to run it.** The third, `saved`, checks content as H5P stores it (*Saved content is checked as the build checks what it writes*, below). `ContentGenerator` was the sweep's @@ -583,6 +583,51 @@ to 3,000. Nineteen 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. + + 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. + + 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. +- **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 + name carried is kept as what an agent can observe: the registry's errors, a sandbox that + downloads only what a browsing tool has opened, a code tool that can be unavailable for hours. + This file keeps the apps' names where it records what was measured in them. Not built: editing an existing package, which a tool beside it does with `checkContent` as its check; layout for Drag and Drop and Crossword; and any judgement of whether content is right, which diff --git a/skills/h5p-author/SKILL.md b/skills/h5p-author/SKILL.md index d2e0424..477e4c7 100644 --- a/skills/h5p-author/SKILL.md +++ b/skills/h5p-author/SKILL.md @@ -110,12 +110,11 @@ from what you know of the type: the build says, for each place that is wrong, wh Build the best way this environment allows, and tell the user which you take: -- **Here, with npm**: a shell that reaches the npm registry (Claude Code, a terminal). The - command below. -- **Here, from two files**: Node runs and files can be fetched, but npm cannot install, as in - ChatGPT. *If it cannot install here*, below. -- **In the user's browser**: nothing here runs, or nothing fetches, as in Gemini or a chat with - no tools. *The build page*, below, with no attempt here first. +- **Here, with npm**: a shell that reaches the npm registry, as in a terminal. The command below. +- **Here, from two files**: Node runs and files can be fetched, but npm cannot install, as in a + chat's sandbox that reaches the web and no registry. *If it cannot install here*, below. +- **In the user's browser**: nothing here runs, or nothing fetches, as in a chat with no tools + or one that cannot open a web address. *The build page*, below, with no attempt here first. Take the first that applies, and the next if it fails. @@ -126,9 +125,10 @@ npx @missing-elements/h5p-author@latest build source.json course.h5p ``` **If it cannot install here, build from files instead.** No network for npm (`EAI_AGAIN`, -`ENOTFOUND`, a registry's 403, 404 or 503, as in ChatGPT): do not retry, try another way to -install it, or end with commands for the user to run once npm works. Where Node runs and you can -fetch a file (in ChatGPT, open each address with the browsing tool, then download it), fetch the +`ENOTFOUND`, a registry's 403, 404 or 503): do not retry, try another way to install it, or end +with commands for the user to run once npm works. Where Node runs and you can fetch a file (where +the sandbox downloads only what a browsing tool has opened, open each address with that tool +first, then download it), fetch the build tool and the bundle of the source's own `type`, the libraries a build of that type reads, at the addresses https://missing-elements.github.io/h5p/skill/ lists for them. In both addresses and commands below, `` is that machine name, such as `H5P.Blanks`: another type's bundle @@ -153,11 +153,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: +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: ```bash -node -e "console.log('https://missing-elements.github.io/h5p/build/#source=' + require('zlib').deflateRawSync(require('fs').readFileSync('source.json')).toString('base64url'))" -python3 -c "import base64,zlib;c=zlib.compressobj(9,zlib.DEFLATED,-15);d=c.compress(open('source.json','rb').read())+c.flush();print('https://missing-elements.github.io/h5p/build/#source='+base64.urlsafe_b64encode(d).decode().rstrip('='))" +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')" ``` **A link is only what one of these commands printed here, handed over whole: no command run, no @@ -165,8 +166,8 @@ 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. -With neither, or no tool that runs anything at all (in ChatGPT, data analysis can be unavailable -for hours), give no link: the page sees only what the user pastes, so put the **whole source in +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 @@ -212,7 +213,14 @@ do it: the person's own play is the check, and a script of your own costs more t Deliver: -- the `.h5p` and the source; +- 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**;