Render inline code in decision question text #276
- MA
## Why The Planner writes inline code with backticks in decision prompts, option labels and descriptions. The card showed them literally, e.g. "the current single `.bak` behavior".
## What changed - New pure tokenizer `inlineSegments()` / `plainInlineText()` (single-backtick pairs only; empty or unmatched backticks stay literal) with unit tests. - New `InlineCode` component renders matched spans as `<code class="inline-code">`. No markdown renderer, no `dangerouslySetInnerHTML`. Stored text is unchanged. - Applied to the decision card (prompt, option label, description, resolved / discarded / expired summaries), the chat decision prompt entry, and the resolved-decision popover. - Accessible names and "Previously: …" use `plainInlineText`, so no stray backticks are read out. - `.inline-code` in `apps/web/src/theme.css` uses the same tokens as inline code in the document (inset, radius-sm, mono, inherited size) with `font-weight: 400` so code in the bold prompt is not heavy.
## Screenshots Before (desktop):

After (desktop):

After (phone 390x844):

## Design-contract review
Reviewed and renewed the exact question-card and resolved-popover source hashes. Changes wrap text in `InlineCode` and remove backticks from accessible labels; the dynamic style/class boundaries are unchanged.
## Testing
- After rebasing onto current main: 151 question tests pass, TypeScript passes, and `bun run ci` passes. - Full GitHub validation, browser integration, and container checks run on the updated branch before merge. - Original visual inspection used the real app with a temporary backtick fixture; screenshots above show that rendering.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- MA
**Review:** Changes needed (minor; visuals look good)
Checked in a browser (desktop 1440x900, phone 390x844) with a backtick fixture. Spans render as inset-chip mono at the inherited size, prompt/option/description wrap cleanly, and the card design is otherwise unchanged. Tokens only (`--color-inset`, `--radius-sm`, `--font-mono`). The two design-contract hashes are the only CI failure and the change is safe.
**Findings** 1. Uncovered place: `apps/web/src/conversation-plan/evidence-popover.tsx:48` renders `row.label` (option text, or `thread.question` per `evidence.ts:90`) as plain text, so backticks show literally in the evidence hover on the same decision. Wrap in `<InlineCode>`. `excerpt-correction.tsx:88,162` (thread.question in a status message and a native `<option>`) cannot render elements; use `plainInlineText` there so stray backticks are not shown. 2. Tokenizer, multi-backtick runs (`inline-segments.ts:11-24`): "``a`b``" gives "``a" + code(b) + "`" and "```x```" gives "``" + code(x) + "``", leaving stray backticks around a chip. Either match equal-length runs (CommonMark) or treat runs of 2+ as literal and skip the whole run. Add tests for both. 3. Escapes: `\`x\`` renders `\` plus code "x\" (backslash inside the chip). Either honour `\`` or document it as unsupported with a test. 4. Whitespace: "` a `" renders a padded chip with leading/trailing spaces. CommonMark trims one space; consider trimming, and treat whitespace-only as literal like the empty case. 5. Joined strings tokenise across items: `question-view.tsx:499/505` (`chosen = choices.join(", ")`) and `:812` (`labels.join(", ")`) run the tokenizer over the joined string, so a lone backtick in one label can pair with one in the next and swallow the separator. Map `plainInlineText` per label, then join. For the resolved line, render each choice with `<InlineCode>` separately. 6. Tests: only 5 cases, none for the items above (multiple backticks, escapes, whitespace, adjacent spans). No component-level coverage that aria-labels are backtick-free; consider a pure test on the label builders.
Accessible names otherwise look right: the `Related` button labels, `Decision prompt:` group label and "Previously:" use plain text; the radio option names come from content and exclude backticks.
- MA
Addressed in 23270f45: 1. `evidence-popover.tsx` row label now uses `InlineCode`; `excerpt-correction.tsx` status message and `<option>` use `plainInlineText`. 2-4. Tokenizer follows CommonMark: N-length runs close at the next run of exactly N, unmatched runs stay literal, one space trimmed per side when both present, whitespace-only stays literal, `\`` outside a span is a literal backtick, backslashes inside a span are literal. 5. `question-view.tsx` now tokenizes each choice/label separately (`InlineCodeList`, `plainInlineList`); never the joined string. 6. Tests cover every case above plus adjacent spans, per-item list reading, and backtick-free label builders (142 pass in `packages/question`).
`question-view.tsx` hash for the design-contract exception is now `5db9f37e2663a774eeb11cfde3a2fcf93dd06dc0ed6f077af42b5f8bc9e9b431` (PR body updated). `bun run ci` still fails only on the two hashes. Visuals are unchanged, so screenshots were not retaken.
lavaman131referenced 77ba1362c02clast month on GitHub
lavaman131referenced 168b4551040flast month on GitHub
MaggieAppletonhead-ref-force-pushed 8c33f7441245last month on GitHub
MaggieAppletonhead-ref-force-pushed 833557be8028last month on GitHub
- MA
I rechecked the latest failed `ci` run on this head. The only failing job is `format, lint, types, tests`, and it stops in `Format, lint, and enforce design tokens`; `container` and `e2e` both pass. The failure is the reviewed design-contract exception renewal for `packages/question/src/react/question-view.tsx` and `packages/editor/src/resolved-layer.tsx`, which would require updating `scripts/design-contract/exceptions/` entries. I did not push a `[ci-fix]` commit because this workflow is not allowed to change those protected exception manifests. Next human action: land the design-contract review/update for those hashes, or push a new head that avoids needing the exception change.
> Generated by [PR CI fixer](https://github.com/githubnext/chopin/actions/runs/37618971100) · gpt54 · 81 AIC · ⌖ 4.53 AIC · ⊞ 15.1K · [◷](https://github.com/search?q=repo%3Agithubnext%2Fchopin+%22gh-aw-workflow-call-id%3A+githubnext%2Fchopin%2Fpr-ci-fix%22&type=issues)
<!-- gh-aw-agentic-workflow: PR CI fixer, engine: codex, model: gpt-5.4, id: 37618971100, workflow_id: pr-ci-fix, run: https://github.com/githubnext/chopin/actions/runs/37618971100 --> <!-- gh-aw-workflow-call-id: githubnext/chopin/pr-ci-fix -->
MaggieAppletonhead-ref-force-pushed 16baac565f6flast month on GitHub
MaggieAppletonhead-ref-force-pushed e554b3777eeblast month on GitHub
MaggieAppletonhead-ref-force-pushed 1bd9558c583elast month on GitHub
- MA
I rechecked the latest failed `ci` run for `1bd9558c583e51efdfdb1b3e4f5ea4bd9f69d3ec`. The head still matches the recorded candidate, `container` and `e2e` are green, and the only failing job is `format, lint, types, tests`, stopping in `Format, lint, and enforce design tokens`. The blocker is still the reviewed design-contract exception renewal for `packages/question/src/react/question-view.tsx` and `packages/editor/src/resolved-layer.tsx`, which would require changing `scripts/design-contract/exceptions/` entries that this workflow is not allowed to edit. I did not queue a `[ci-fix]` commit. Local reproduction and verification are also blocked in this runner because `bun` and `mise` are not installed, so I could not run `bun install --frozen-lockfile`, `bun run fix`, or `bun run ci` here. Next human action: review and renew the exact design-contract exception if the ownership change is approved, or push a new head that avoids needing the exception update.
`babysit-head:1bd9558c583e51efdfdb1b3e4f5ea4bd9f69d3ec`
> Generated by [PR CI fixer](https://github.com/githubnext/chopin/actions/runs/37627207812) · gpt54 · 43.1 AIC · ⌖ 3.21 AIC · ⊞ 15.1K · [◷](https://github.com/search?q=repo%3Agithubnext%2Fchopin+%22gh-aw-workflow-call-id%3A+githubnext%2Fchopin%2Fpr-ci-fix%22&type=issues)
<!-- gh-aw-agentic-workflow: PR CI fixer, engine: codex, model: gpt-5.4, id: 37627207812, workflow_id: pr-ci-fix, run: https://github.com/githubnext/chopin/actions/runs/37627207812 --> <!-- gh-aw-workflow-call-id: githubnext/chopin/pr-ci-fix -->
MaggieAppletonauto-rebase-enabledlast month on GitHub
MaggieAppletonhead-ref-force-pushed 1b86f49c49e1last month on GitHub
MaggieAppletonhead-ref-force-pushed a7108f2df93blast month on GitHub
MaggieAppletonhead-ref-force-pushed 5b0f68fb65d2last month on GitHub
MaggieAppletonmerged 1727ba904ecclast month on GitHub
MaggieAppletonhead-ref-deletedlast month on GitHub