Repository navigation
fix(author): a licence's version and a gap's marks are said where a chat reads, and what the build can prove wrong is a problem - #188
Merged
Conversation
…hat reads, and what the build can prove wrong is a problem A licence written with its version, "CC BY 4.0", is a problem that names the licence it read and where the version goes. A backslash before / or : in a Fill in the Blanks gap is a problem with the gap written out as the library takes it, the two characters as entities. A gap of Drag the Words whose tip or feedback matches twice is a problem with the word the learner would drag. SKILL.md and the two type files say the same before a source is written. Closes #187
…nt each stored source once
Contributor
There was a problem hiding this comment.
1 issue found across 8 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/author/lib/types.mjs">
<violation number="1" location="packages/author/lib/types.mjs:743">
P2: `*word\+Feedback:extra*` passes this guard because H5P finds only one `tips` match, yet its lexer treats `:extra` as the tip and truncates the correct feedback to `Feedback`. Detect a colon after `\+` or `\-` even when it is the only colon, and cover this case in the layout tests.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| const tips = part.match(/(:([^\\*]+))/g) ?? [] | ||
| const right = part.match(/(\\\+([^\\*:]+))/g) ?? [] | ||
| const wrong = part.match(/(\\-([^\\*:]+))/g) ?? [] | ||
| if (tips.length < 2 && right.length < 2 && wrong.length < 2) continue |
Contributor
There was a problem hiding this comment.
P2: *word\+Feedback:extra* passes this guard because H5P finds only one tips match, yet its lexer treats :extra as the tip and truncates the correct feedback to Feedback. Detect a colon after \+ or \- even when it is the only colon, and cover this case in the layout tests.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/author/lib/types.mjs, line 743:
<comment>`*word\+Feedback:extra*` passes this guard because H5P finds only one `tips` match, yet its lexer treats `:extra` as the tip and truncates the correct feedback to `Feedback`. Detect a colon after `\+` or `\-` even when it is the only colon, and cover this case in the layout tests.</comment>
<file context>
@@ -642,6 +642,120 @@ const imageHotspotQuestion = {
+ const tips = part.match(/(:([^\\*]+))/g) ?? []
+ const right = part.match(/(\\\+([^\\*:]+))/g) ?? []
+ const wrong = part.match(/(\\-([^\\*:]+))/g) ?? []
+ if (tips.length < 2 && right.length < 2 && wrong.length < 2) continue
+ let word = part.slice(1, -1)
+ for (const matches of [tips, right, wrong]) if (matches.length) word = word.replace(String(matches), '')
</file context>
Contributor
There was a problem hiding this comment.
All reported issues were addressed
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…code; a tip after the feedback is taken
This was referenced Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #187.
Haiku with a shell and the skill built each of the 32 content types that need no media twice: 64 packages, all built, all passing
h5p-verify, and four played wrong with no word from either. Two were a text's own marks: a Fill in the Blanks asked for the answers 1/2, 10:30 and km/h, where*10:30*is the answer 10 with the tip 30 and*km/h*takes km or h; and a Drag the Words with a colon in a gap's feedback, where the learner drags the word with its tip still in it. In the chat position, of 30 first replies on 0.9.3, none wrote the licence's version in its own field, and the build's own problem for it had every reply drop the version (#187 has the numbers).What changes
SKILL.md, step 2, for the chat that has no type file:"license": "CC BY", "licenseVersion": "4.0", andCC0 1.0is one code, as it stands;/separates answers and:starts a tip, in a gap of H5P.DragText:starts a tip, and where one belongs to the answer itself it is written/or:. A backslash escapes nothing.*km/h*takes km/h where*km/h*takes km or h; in Drag the Words:stands once in a gap, before the tip, and feedback holds none.license: "CC BY 4.0" holds the version too: write "license": "CC BY" and "licenseVersion": "4.0". A name that is no licence gets the list as before./or:in a gap's answers is a problem, the gap written out as the library takes it:params.questions[0]: `*1\/2*`: a backslash escapes nothing in a gap, so H5P.Blanks takes "1\" or "2" here. In an answer write `/` as `/` and `:` as `:`: `*1/2*`. An answer that is a backslash and no more is left alone.params.textField: gap 1, `*hablo:primera persona\+Correcto: termina en -o.\-No: la fo…`: its feedback holds a `:`, where H5P.DragText ends the feedback and starts another tip, and it then leaves them in the word: the learner would drag "hablo:primera persona: termina en -o.: la forma es «hablo».". Write `:` once in a gap, before the tip, and none in the feedback. A colon in the tip itself is none: the tip runs on over it.LAYOUTS['H5P.Blanks'],LAYOUTS['H5P.DragText']), so they run wherever the type sits, in a Column or a Question Set too, and incheckContenton saved content. Each finds its gaps as its library does:handleBlanksandparseSolutionof H5P.Blanks 1.14,parseTextandlexof H5P.DragText 1.10.design/author.mdsays why, and what was measured.*10:30*as written is not refused. It is a tip to the library and may be one to its author, and a build cannot tell which. Nor is a Drag the Words gap with one colon after\+or\-and no tip before it: played,*habla\+Bien.:tercera persona*has the feedback "Bien." and the tip "tercera persona", a tip written after the feedback, which the build cannot tell from a colon meant for the feedback.cubic's review
\+with no tip before it (P2,types.mjs): not refused, as above. Refusing it would refuse a source that plays as its author meant; the type file andSKILL.mdsay feedback holds no colon, and the layout's test now holds a tip written after the feedback to be taken.CC0 1.0is one code (P2SKILL.md, P2 and P3design/author.md): right. The sentence now names CC BY and its family and saysCC0 1.0is one code; the design note says the same; a test holdsCC0 1.0to build as it is, and"CC0"with"licenseVersion": "1.0"to two problems. Checked on Haiku in the chat position with the new sentence: 11 of 11 right: "CC0 1.0" kept whole 4 of 4, "CC BY 4.0" split 4 of 4, "CC BY-SA" with no version left without one 3 of 3.js/incomplete-multi-character-sanitization,types.mjs): a Blanks gap's tags are taken out until none is left, where the library takes them out in one pass; the two differ only for a tag written inside a tag.The entity
"Nothing escapes a gap's marks" is not so, which the first cut of this assumed:
parseSolutiondecodes each answer's entities, and:is no colon as the gap is split. Played in the verifier's browser:*10:30*,*km/h*,*1/2:a fraction*and*3:1/3 to 1:…*: the key is 10:30, km/h, 1/2 and 3:1 or "3 to 1"; those answers typed score 4 of 4; "10", "km" and "1" typed are wrong.*7:45*and:in feedback: the word is drawn 7:45 and scores, the feedback shows a colon, and no attribute or text in the frame holds the entity as written. The key in its xAPI statement does:7:45.*10:30*,*km/h*and*1/2*: each is one word, and the right one. Neither character is a mark there, so the skill's line names the two other types only.Tested
pnpm --filter @missing-elements/h5p-author testpasses, 184 tests with the browser one, and so does the typecheck. The tags in a Blanks gap are taken out until none is left, where the library takes them out in one pass, for CodeQL'sjs/incomplete-multi-character-sanitization(a tag inside a tag is the only difference). New: the licence's four messages; the two checks' problems word for word, in a Column too; and what both must take, alternatives, a tip, an answer that is a backslash, a tip that holds a colon, the entities.pnpm --filter @missing-elements/h5p-skills testpasses, 77 tests: every type file is current with the generator, and every example builds and plays.False alarms. The two checks over the 94 real packages of the owner's corpus and the demo, 53 of these two types in them with 266 gaps: nothing reported. Over the 524 distinct sources these tests stored, 199 of the two types with 765 gaps: only the 14 known to play wrong.
Haiku as a chat, the skill's text and no tool, each reply built with this branch, played, and the library's own key held against the request. First replies that wrote a source:
0.9.3's column counts 30 replies for the licence, which
SKILL.mdalone decides, and for the rest the 20 written with 0.9.3's own files.Uin 5 of 5. A licence named without a version got none in 5 of 5; with the version inSKILL.md's example, as first written, 3 of 7 added "4.0", which is why it is in the sentence and not the example.distractorswritten as a list twice and a field of the chat's own making once, and the three Mark the Words, for the task description the type requires.The replies that had gone wrong, the build's problems pasted back in the build page's words: 8 of 8 right in one round, 4 Blanks with the answers asked for and 4 Drag the Words, and the licence right in all. With 0.9.3's problems, 1 of 12 gaps fixed and the version dropped in 12 of 12.
Where the build cannot prove it, a first reply with
*10:30*: the type file handed back beside the licence's problem had 1 of 3 write the entities; the two others built and play wrong, as before.The first twenty chats of the last round were started with another line than the earlier rounds' and 6 asked a question before writing; 0.9.3's text under that line did the same in 2 of 10, and this branch's text under the old line in 0 of 10. The counts above are of replies that wrote a source.
Not verified
To release
h5p-author 0.9.4, a patch: no export added or removed. A source that built still builds unless it holds one of the two gaps, which played wrong. Then the site's pin moves to it, for
/h5p/skill/and the build page. Installed copies of the skill neednpx skills update -gand a new upload to the Claude app.