Skip to content

fix(questions): answers saved under a 0.28.1 label still show their pick - #1702

Merged
backnotprop merged 2 commits into
mainfrom
fix/question-legacy-answer-labels
Oct 5, 2026
Merged

backnotprop merged 2 commits into
mainfrom
fix/question-legacy-answer-labels

Conversation

@backnotprop

Copy link
Copy Markdown
Owner

Target: 0.28.2. This fixes the issue the pre-tag smoke found in #1699. No version bump.

Bug

0.28.1 used a wrapped plain bullet's first line as its label, for example **One per session:** "ramos · cloud-3", "ramos · cloud-4". Each agent shows. 0.28.2 labels the same choice One per session. An answer saved on 0.28.1 stores the old label, so on 0.28.2 it restored as "Answered" with no option selected and Other empty. The card matches selected.includes(choice.label) exactly.

Fix

  • Plain-bullet choices now carry aliases (optional and additive on QuestionChoice). These are the bullet's full text, its first line, that line's label split at —, and the uncut label. They are the same names recommendation matching already uses.
  • The new canonicalQuestionAnswer(question, answer) in @plannotator/core/question-block maps a stored label that matches an alias to the choice's current label. Labels that match no choice are kept as they are, and when nothing maps the same object is returned.
  • Every place that reads answers goes through it:
    • the card (QuestionBlock): the old answer shows its option selected, and the next change stores the current label;
    • the Questions panel rows (buildQuestionPanelRows);
    • WebMCP read_document (questionViews);
    • the "Answers to your questions" export section (questionExportItems now passes the choices).
  • An untouched old answer therefore exports under the current label, and it also gets "(your recommendation)" when it matches.
  • The status was already correct ("Answered" counts any pick). questionKey is unchanged.
  • Low-priority item from the smoke: a recommendation that names a lettered option (**Recommendation:** b. Default off…) now marks the one choice whose label starts with b. or b). When two labels share the letter, nothing is marked.

Tests

  • packages/core/question-block.test.ts:
    • a 0.28.1 label maps to the current one;
    • current labels, and labels naming no choice, are left alone;
    • the key is unchanged;
    • the export prints Answer: One per session (your recommendation);
    • lettered recommendations, including the case where two labels share a letter.
  • packages/ui/components/blocks/QuestionBlock.test.tsx (DOM, already in the DOM_TESTS step): a saved 0.28.1-style answer on the Q4 block restores with its option selected, exports under the current label, shows in the panel row, and re-saves with current labels after a change. This test fails without the card fix.
  • packages/editor/webmcp/documentTools.questions.test.ts: read_document reports the current label.

Results:

  • Typecheck is clean.
  • bun test packages/core packages/ui packages/editor: 1706 pass, 0 fail.
  • With DOM_TESTS=1: 2745 pass, 7 fail. The 7 failures are unrelated: 3 live paste-service tests need the network, and 4 DocBadges tests fail only in the full run (they pass alone).
  • The DOM allowlist and skill-reference tests pass.
  • guides-show build:viewer followed by check:manifest reports "in sync", so the viewer build is unchanged.

0.28.1 read a wrapped plain bullet's first line as its label (for example
'**One per session:** "ramos · cloud-3", … Each agent shows'); 0.28.2
labels it 'One per session'. An answer saved on 0.28.1 restored as
Answered with nothing picked.

- Plain-bullet choices carry aliases: their full text, first line, that
  line's dash-split label and the uncut label (the names recommendation
  matching already used).
- canonicalQuestionAnswer maps a stored label naming a choice by an alias
  to the current label. The card, the Questions panel, WebMCP read_document
  and the export section all read answers through it, so an untouched old
  answer exports under the current label (with '(your recommendation)'),
  and the next edit stores the current label. questionKey is unchanged.
- A recommendation naming a lettered option ('b. Default off…') marks the
  one choice whose label starts with that letter and '.' or ')'.
… only for plain bullets

- canonicalQuestionAnswer maps a stored label only when exactly one choice
  claims it: exact names first (its 0.28.1 label, first line, full text),
  then normalized ones (case, emphasis, punctuation), where a choice's
  current label counts as a claim too. Two bullets that shared a first line,
  or names that differ only in case, leave the answer as stored.
- The lettered recommendation rule applies to plain-bullet choices only,
  is case-sensitive, and runs after the existing matching: per part inside
  the multi split, then on the whole text. Task-list blocks match exactly as
  on 0.28.1 (32 lettered task-list cases compared against main's parser).
@backnotprop
backnotprop merged commit f9ba94a into main Oct 5, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant