docs: boocode-lift-analysis, openspec change docs, codesight cache, deps
- Add boocode-lift-analysis.md: comprehensive 30-repo lift matrix across 25 domains - Add openspec/ change docs: domain2-code-intelligence, domain3-multi-agent, impeccable-wave, streaming-codeblocks - Update .gitignore: .impeccable/, .omo/, bun.lock, DESIGN.md, PRODUCT.md - Update dependencies in package.json + pnpm-lock.yaml - Update .codesight/ analysis cache
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Error boundary on MarkdownRenderer
|
||||
|
||||
`MarkdownRenderer` SHALL be wrapped in a `<MessageBoundary>` that catches render errors from remark-gfm or react-markdown and shows a compact "Content rendering failed" fallback with a retry button.
|
||||
|
||||
#### Scenario: Markdown render throws
|
||||
- **WHEN** `react-markdown` or `remark-gfm` throws during rendering
|
||||
- **THEN** the error boundary catches the exception and renders a fallback UI
|
||||
- **AND** the fallback shows "Content rendering failed" with a Retry button
|
||||
- **AND** clicking Retry re-mounts `MarkdownRenderer` with the same content
|
||||
|
||||
### Requirement: Error boundary on CodeBlock
|
||||
|
||||
`CodeBlock` SHALL be wrapped in a `<MessageBoundary>` that catches errors from Shiki's `codeToHtml` and renders a plain-text `<pre>` fallback with the source code.
|
||||
|
||||
#### Scenario: Shiki highlight fails
|
||||
- **WHEN** `codeToHtml` throws (e.g., unknown language, WASM load failure)
|
||||
- **THEN** the error boundary catches the exception and renders a plain `<pre>` block with the original code
|
||||
|
||||
### Requirement: Loading skeleton for streaming messages
|
||||
|
||||
Messages with `status === 'streaming'` and no content yet SHALL render a pulse-animated skeleton placeholder instead of an empty bubble.
|
||||
|
||||
#### Scenario: Streaming message starts with no content
|
||||
- **WHEN** a `message_started` frame arrives with `role: 'assistant'`
|
||||
- **THEN** a skeleton placeholder renders (animated pulse bar) until the first `delta` frame arrives with content
|
||||
|
||||
### Requirement: Keyboard-navigable ToolCallLine
|
||||
|
||||
`ToolCallLine` SHALL support full keyboard navigation: `Tab` to focus, `Enter`/`Space` to toggle expand/collapse, `Escape` to collapse if expanded.
|
||||
|
||||
#### Scenario: User navigates tool call via keyboard
|
||||
- **WHEN** the user presses `Tab` to focus a `ToolCallLine`
|
||||
- **THEN** a visible focus ring appears
|
||||
- **AND** pressing `Enter` toggles expand/collapse
|
||||
- **AND** pressing `Escape` collapses it if expanded
|
||||
|
||||
### Requirement: Keyboard-navigable ToolCallGroup
|
||||
|
||||
`ToolCallGroup` SHALL support the same keyboard navigation as `ToolCallLine`. The group header SHALL be the focusable element.
|
||||
|
||||
#### Scenario: User navigates tool group via keyboard
|
||||
- **WHEN** the user presses `Tab` to focus a `ToolCallGroup` header
|
||||
- **THEN** a visible focus ring appears
|
||||
- **AND** pressing `Enter` toggles expand/collapse of the group
|
||||
|
||||
### Requirement: Consistent aria-label protocol
|
||||
|
||||
Every interactive element in `ActionRow` (Copy, Resend, Regenerate, Fork, Delete, Restore, Pin) SHALL have an `aria-label` attribute that matches its `title` text.
|
||||
|
||||
#### Scenario: Action row button has aria-label
|
||||
- **WHEN** an ActionRow button renders
|
||||
- **THEN** it SHALL have an `aria-label` matching its `title`
|
||||
- **AND** the label SHALL be unique within the message bubble
|
||||
Reference in New Issue
Block a user