fix(author): a source's own fields no longer hide its content, for a chat with no skill text

Merged
AL
1d ago
+763-64

Closes #174.

A chat given a link to the skill and none of its text writes a source's outer shape its own way. The build checked a source's own fields, then the type's name, then the content, and stopped at each, so every layer cost a round in which nothing inside was looked at. Now what the outer shape plainly means is taken, said once with what to write, and the content is checked in the same build.

Measured

The weakest Claude model, Haiku 5.5, as Gemini in Chrome was: the request as worded ("create interactive book using <a link to the skill's folder>. topic - …"), no skill text, each reply built, what the build page copies pasted back, up to four rounds. Six content types, two runs each, both rows from the same 12 first replies. Right means it builds, holds what was asked for, and plays (h5p-verify).

Right at onceBy round 2By round 3By round 4Gave up
0.7.0, the live page0 of 123684
This PR, and the page handing the type's file back for a type named loosely0 of 1210120

Both books and both sets of cards gave up under 0.7.0, on the type's name. The second row needs the build page's part too, a follow-up in missing-elements.github.io once this is released: its rule for the type files is the source's type as written, which finds no file for interactive-book.

Gemini's own first source, which was seven problems of the outer shape and then thirty of the content, is now seven in all:

contentType: is not a field of a source: the content type is its type: write "type": "H5P.InteractiveBook"
metadata: is not a field of a source: title, license, authors are written beside type, not in an object: write "title": …, "license": …, "authors": … at the top
language: expected a BCP 47 language tag, such as "en" or "de-AT"
params.chapters[0]: is the params of sub-content, without the sub-content around them: write params.chapters[0] as { "library": "H5P.Column", "metadata": { "title": … }, "params": { "content": … } }
params.chapters[0].content[0]: is sub-content, but here it goes inside an object, in its field content: write params.chapters[0].content[0] as { "content": { "library": "H5P.AdvancedText", "params": { … } } }

What changes

A source read for a build (lib/build.mjs, sourceOf). With the pack's names, it takes:

  • the content type under contentType or library, or named loosely as type: interactive-book, Question Set, dialogcards. A name that is no type has the nearest offered: the library pack has no content type book; nearest: H5P.InteractiveBook;
  • the title, language, licence and authors in metadata, as H5P keeps them, and in no other object: Question Set's introPage has a title too;
  • the content's fields beside type, with no params around them.

Each is a problem, so a source that was refused is refused still. The content is then generated and checked in the same build, with a stand-in for what is missing. readSource keeps its contract: a source's own problems, thrown, without the pack's names.

Names (lib/names.mjs, new). A library written loosely is the one library of the same letters and digits, in any case, with or without H5P. and a version; a number with no point is no version, so "Question Set 2" is no Question Set. Titles are not tried, "Multiple Choice" or "Image Choice": the pack's index has none, and reading them means fetching every part, 147 of them and some 15 MB, to name one type. Names are read without a regular expression that backtracks, and a text over 64 characters is no name.

Sub-content that names its library under type or contentType (lib/generator.mjs, lib/libraries.mjs). { "contentType": "H5P.AdvancedText", "params": { … } } and { "type": "H5P.MultiChoice", "question": … }, in a library field and in the place of the group that holds one: one problem that shows what to write, and what is inside checked, named by where the source has it. Only where one of the two names a library the field takes, at the major written where the field takes it; the loader loads that library, as it is named or loosely, so what is inside is checked against its fields. No other key: in the 328 sources the tests stored, every name found under another one was a text that reads like one, a card's answer "table", a title "Text". A title beside the parameters that is no field of the library is the sub-content's own, in a library field's place or in its group's, which had been two problems a chapter. library written loosely is taken too.

Tested

  • pnpm --filter @missing-elements/h5p-author test: 178 pass, the page's build in Chromium among them. New tests for each shape, for what is not guessed (two keys that name a type or a library, a name under another key, saved content), and for the names. Each of twelve mutations of the new code fails a test, and so does undoing any of the ten fixes from the review.
  • pnpm --filter @missing-elements/h5p-skills test: 77 pass, so every type file's example still builds and plays. The author's typecheck passes.
  • Nothing that built changes. The 32 type files' examples and the quiz format's four variants build the same package as with 0.7.0: every entry, the notes and the translation reports.
  • 263 sources the earlier tests stored, written by Haiku with the skill's text: 259 have the same problems, and none builds with one build and not the other. The four that differ are books whose chapters had a title beside them, 13 problems now 7.
  • The problems the model was given in the measurement are those of this commit: all 14 failed rounds were built again and compared.

To release

h5p-author 0.7.1: no new export, and no source that built is refused or builds otherwise. Then the build page's pull request, which moves its pin and hands the type's file back for a type named loosely or under another key.