Repository navigation
fix(host): refuse an ask_user card outside two to four answers (#2771) - #2772
Conversation
…FlowLab#2771) Fixes ThinkFlowLab#2771 The card's own parameter description says "Two to four answers", while the host sliced the normalised labels to six and refused only the empty array: a one-option card was stored and its single option came back as the user's answer, and a seventh option disappeared without a word. Both ends are now refused with one sentence naming the rule, counted on the labels that survived the empty-label filter, so five given with two blanks stays a three-button card. Two to four options keep the card and the answer string byte for byte, and no read path or stored legacy card is touched. Docs-not-needed: docs/subsystems/core-host.md does not state how many options an ask_user card takes; the count lives in the tool's own parameter description, which the code now matches.
|
@Birfy — review request at tip The PR is now ready (it was opened as draft because this is a T1 change and the advisory had not landed yet). FlyBot Test's advisory is PASS at this exact tip: a third full What is in it: one source change — Red first on the base, twice, same shape: 7 tests / 4 pass / 3 fail — one, six and seven options answered No further writes from us at this tip — no rebase, no second push — unless a review asks for a change. |
|
Verdict: PASS at 75e5f61 Ran at this tip: The first run is the tip as fetched. The second reverted only What I checked independently:
Not run: the full |
Fixes #2771
Owner: Dev-3
Reviewer: Birfy
Written-by: Dev-3
Bot: Dev-3
Claim-Id: 64cc0994fa0b439f80667b03c5b45fd2
Base: f2ef4df
Risk tier: T1
The defect
core/src/host/tools.jsdeclared the count and then did something else with it: theoptionsparameter saidTwo to four answers(:626), the normaliser dropped empty labels,.slice(0, 6)cut whatever was left, and the only size check wasoptions.length === 0(:654). Measured on the live basef2ef4dfawith the fixture below — call the registeredask_usertool, then readstate.questionsback through/api/botstate:A one-option card is stored and its single option comes back as the user's answer; a seventh option reaches nothing and the tool still answers that the card is on screen. The group path
askInGroup(:681) receives the same array, so a question handed out from a group behaved identically.What changed
core/src/host/tools.js:646-655— the normalisation and the empty-label filter stay;.slice(0, 6)and thelength === 0refusal are replaced by one check on the labels that survived the filter, in the slot the old refusal held (before thehandedFromGroupbranch, soaskInGroupinherits it). Fewer than two or more than four returnsGive two to four answers.and writes no card; two to four options store exactly what they stored before.core/test/questions.test.js— five cases on the existingstart()fixture: one option refused, six refused, seven refused (not cut to six), two and four unchanged to the byte (the answer string plus the stored card with its identity fields removed), and five given with two blank labels counted as three and accepted.changelog.d/2771-ask-user-two-to-four-answers.fixed.md— the user-visible entry.patches/ds-bot/0002-flybot-api-host.patchandpatches/ds-bot/topics.json— regenerated.test/questions.test.jsis an upstream file, so its first edit needed a topic; it joins0002, which already ownssrc/host/tools.js, andgeneraterewrote that patch. The test file is not infiles/.Read paths are untouched:
cardText, the questions renderer,answer-questionand the inbox still read and answer a stored one-option card, and the fixtures that model those legacy cards are unchanged.Verification at the tip
Tip SHA:
75e5f61235e6f0d378d59486dc093aeba6fc1354(treee25b86c8ab3823b2d6cc88d86aa12a982a4d5038)Ran:
cd core && node --import ./test/harness-resolve.mjs --test --test-timeout=120000 test/questions.test.js→ 7 tests / 7 pass / 0 fail, twice in a row, same shape.cd core && node --import ./test/harness-resolve.mjs --test --test-concurrency=4 "test/*.test.js"→ 2571 tests / 2481 pass / 90 fail. The clean basef2ef4dfain the same clone gives 2566 / 2476 / 90, and the failing-file set is identical (diffclean): those 90 files cannot loadesbuild/jsdomin this fresh clone (nocore/node_modules, registry 404s). Every test that loads is unchanged apart from the five new cases.node core/scripts/check-arch-docs.mjs→arch-docs: OK (5 changed file(s)); the branch commit carries theDocs-not-needed:trailer.node scripts/ds-bot-patches.mjs check→ok core/ equals ds-bot/ + patches/ds-bot/.node .github/scripts/changelog.mjs check→ 17 fragments well formed.oxlint -c core/.oxlintrc.json core/src/host/tools.js core/test/questions.test.js→ 0 errors, 2 warnings, both the pre-existingno-control-regexattools.js:85.Not run (and why):
npm run verify— itsnpm cicannot reach a registry on this box (404 on the configured mirror) and this clone has nocore/node_modules, so the harness comes fromDSH_HARNESSand the steps were run individually.node core/scripts/build-client.mjs --check— needs the same missingesbuild; this diff touches neithercore/src/client/norcore/client.js.dev/bench.sh) — needs the same install; this diff changes one refusal in a tool handler, not a route, turn or delivery path.Red first
On the live base
f2ef4dfawith only the test file added (source change reverted),node --test test/questions.test.jsfails exactly three of the five new cases, twice in a row with the same shape:The two guards stay green on that base — the two-and-four card is already byte-identical today, and five given with two blanks is already three buttons — which is what makes them controls rather than two more reds.
Checkpoint
{ "pr": 2772, "claim": "Dev-3", "issue": 2771, "summary": "The card's own description said two to four answers while the host sliced the labels to six and refused only the empty array, so a one-option card was stored and its single option came back as the user's answer, and a seventh option vanished with no word. Both ends are now refused with one sentence naming the rule, counted on the labels that survived the empty-label filter, so five given with two blanks stays a three-button card. Two to four options keep the card and the answer string byte for byte, and no read path or stored legacy card is touched. Five cases cover it.", "files": ["core/src/host/tools.js", "core/test/questions.test.js", "changelog.d/2771-ask-user-two-to-four-answers.fixed.md", "patches/ds-bot/0002-flybot-api-host.patch", "patches/ds-bot/topics.json"], "checks": { "ran": "cd core && node --import ./test/harness-resolve.mjs --test --test-timeout=120000 test/questions.test.js", "result": "green", "at": "75e5f61235e6f0d378d59486dc093aeba6fc1354" }, "next": "none — ready for review" }