candle-annotator/openspec/changes/line-rectangle-annotations/tasks.md
Marko Djordjevic 65f00e6ce7 feat: complete prediction UI feedback tasks (11.2, 11.4, 11.5)
- Implement disagreement visual highlighting with distinct colors
  - Yellow highlight for 'missed_by_human' predictions
  - Orange for 'label_mismatch' disagreements
  - Warning icon on disagreement markers
- Add click-to-convert prediction feedback
  - Click disagreement predictions to create span annotations
  - Auto-fill with predicted label and times
  - Set source as 'model_confirmed' or 'model_corrected'
- Add dismiss action for false positive predictions
  - Alt+Click or Ctrl+Click to dismiss predictions
  - Saves negative annotation with label 'O'
  - Records original prediction in model_prediction field
- Filter predictions when 'Show only disagreements' is enabled
2026-02-16 11:40:55 +01:00

4.5 KiB

1. Enhance TrendLine Plugin

  • 1.1 Add hitTest(x, y) method to TrendLine class — calculate perpendicular distance from click point to line segment in pixel coordinates, return PrimitiveHoveredItem with annotation ID if within 10px tolerance
  • 1.2 Add setSelected(isSelected) method and selection state to TrendLine — when selected, renderer draws thicker line and circular endpoint handles (radius 6px, white fill, colored stroke)
  • 1.3 Add attached()/detached() lifecycle methods to TrendLine to store SeriesAttachedParameter reference (needed for hitTest coordinate conversion)
  • 1.4 Add preview line support — dashed stroke style and reduced opacity when an isPreview option is set

2. Create RectangleDrawingPrimitive Plugin

  • 2.1 Create src/plugins/rectangle-drawing.ts implementing ISeriesPrimitive<Time> with renderer, pane view, and data model for two corner points {time, price}
  • 2.2 Implement RectangleDrawingPaneRenderer.draw() — filled semi-transparent rectangle with border, using useBitmapCoordinateSpace for HiDPI scaling
  • 2.3 Implement hitTest(x, y) — convert pixel to data coordinates, check if within rectangle time/price bounds
  • 2.4 Add setSelected(isSelected) and selection visual feedback (thicker border, increased opacity)
  • 2.5 Add preview mode support — dashed border and reduced opacity for preview rectangles during drawing
  • 2.6 Add autoscaleInfo() to include rectangle price range in chart scaling
  • 2.7 Set z-order to "bottom" so rectangles render behind candlesticks

3. Wire Up Drawing Interaction in CandleChart

  • 3.1 Add state for drawing mode: drawingState: {tool: 'line'|'rectangle', firstPoint: {time, price}} | null and previewPrimitive: TrendLine | RectangleDrawingPrimitive | null
  • 3.2 Subscribe to chart.subscribeClick() — on first click when line/rectangle tool active, record first point and attach preview primitive; on second click, save annotation via API, detach preview, attach permanent primitive
  • 3.3 Subscribe to chart.subscribeCrosshairMove() — when drawing in progress, update preview primitive's endpoint via updatePoints() or equivalent
  • 3.4 Handle Escape key — detach preview primitive and clear drawing state
  • 3.5 Manage TrendLine primitives for saved line annotations — create/attach on load, detach on delete, update on edit

4. Wire Up Rectangle Primitives in CandleChart

  • 4.1 On annotation fetch, create RectangleDrawingPrimitive instances for label_type: "rectangle" annotations and attach to series
  • 4.2 On chart switch, detach old rectangle primitives and create new ones for the new chart's annotations
  • 4.3 Handle rectangle selection — on click hit detected via primitive hitTest(), call setSelected() and track selected annotation ID
  • 4.4 Handle rectangle deletion — when delete tool active and hit detected, send DELETE API call, detach primitive, refresh annotations

5. Update Toolbox

  • 5.1 Add "rectangle" tool button to Toolbox (using existing RectangleHorizontal lucide icon import, which is already present)
  • 5.2 Wire rectangle button to onToolChange('rectangle') with same toggle behavior as other tools

6. Remove SVG Overlay

  • 6.1 Remove SvgOverlay import and JSX from CandleChart.tsx
  • 6.2 Delete src/components/SvgOverlay.tsx
  • 6.3 Move line annotation primitive management into CandleChart (replace what SvgOverlay was doing — loading saved lines, managing line primitives on annotation fetch/delete)

7. Line Endpoint Dragging

  • 7.1 Implement drag detection — when a selected line's endpoint handle is clicked (via hitTest near endpoint), enter drag mode
  • 7.2 On crosshair move during drag, call trendLine.updatePoints() to reposition the dragged endpoint in real-time
  • 7.3 On click to release drag, persist updated geometry via PATCH /api/annotations/{id}

8. Verification

  • 8.1 Verify existing saved line annotations render correctly with TrendLine plugin (visual parity with old SVG rendering)
  • 8.2 Verify line drawing, preview, selection, dragging, and deletion all work end-to-end
  • 8.3 Verify rectangle drawing, preview, selection, and deletion work end-to-end
  • 8.4 Verify chart zoom/pan correctly repositions both line and rectangle primitives
  • 8.5 Verify tool switching between line, rectangle, span, label, and delete modes works correctly
  • 8.6 Verify annotations persist and reload correctly on chart switch