Skip to content

feat(questions): Decision flag, findQuestionBlocks, host footer slot - #1664

Merged
backnotprop merged 3 commits into
mainfrom
feat/question-decision-flag
Oct 2, 2026
Merged

backnotprop merged 3 commits into
mainfrom
feat/question-decision-flag

Conversation

@backnotprop

Copy link
Copy Markdown
Owner

What

  • core: a Decision: when answered line after the prompt sets ParsedQuestion.decisionOnAnswer; a Decision: [statement](https://...) line sets ParsedQuestion.decision (the link wins over the flag). Both stay out of context, other Decision: values stay prose, and neither changes the question key.
  • core: findQuestionBlocks(markdown) returns { key, directiveKind, startLine, endLine, text } per question block, with the same -2/-3 key de-dup as indexQuestionBlocks (one shared helper).
  • core: new @plannotator/core/markdown-structure subpath. The block splitter's structural rules (frontmatter, code fences, display math, directives, HTML blocks, reference links) moved out of ui's parser so parseMarkdownToBlocks and findQuestionBlocks share one copy. questionBlockParity.test.ts runs both over fenced, nested, quoted, HTML, math, frontmatter, reference-link, CRLF and unclosed cases.
  • ui (Viewer -> BlockRenderer -> QuestionBlock): a decision tag and row on flagged or linked cards, renderQuestionFooter for host actions (live in read-only cards too, so read-only now disables each input instead of the fieldset), questionAnswers (host-kept answers replace the annotation path), and an explicit save mode onSaveQuestionAnswer (draft in the card, Save answer / Cancel, no Skip).
  • guide-viewer manifest CSS hash rotated for the new classes. No version bumps.

Why: upstream ask from Workspaces (answers kept beside the document, some answers become project decisions). Plannotator passes none of the new props; its cards only change by showing a Decision line when a block has one.

Left out on purpose: the record lines inside the block (Other:, Answer:, Note:, Answered:) and writeQuestionAnswer, dropped with the owner's answer on where answers live.

- core: parse 'Decision: when answered' (decisionOnAnswer) and
  'Decision: [statement](https://...)' (decision) after the prompt; the
  key never changes
- core: findQuestionBlocks(markdown) -> { key, directiveKind, startLine,
  endLine, text } with the same -2/-3 de-dup as indexQuestionBlocks
- core: new markdown-structure subpath holds the block splitter's
  structural rules (frontmatter, fences, math, directives, HTML blocks,
  reference links), shared by ui's parser and findQuestionBlocks; a
  parity test runs both over tricky fixtures
- ui: decision tag/row on question cards, renderQuestionFooter slot,
  questionAnswers host prop, explicit save mode (onSaveQuestionAnswer)
- guide-viewer manifest CSS hash rotated (new card classes)
Optional Viewer prop (string or (question) => string), threaded through
BlockRenderer to QuestionBlock. Default stays "Save answer"; the card never
derives a label from decisionOnAnswer, since only the host records.
A resolved save cleared whatever draft was current, discarding an edit made
while the promise was pending; now only the submitted draft is cleared. A draft
edited back to the saved answer is dropped so a later host update shows.
@backnotprop
backnotprop merged commit 6d00eeb into main Oct 2, 2026
28 checks passed
@backnotprop
backnotprop deleted the feat/question-decision-flag branch October 2, 2026 02:48
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