Skip to content

feat: turn EDA findings into one-click-to-prep action cards - #172

Closed
lucastononro wants to merge 4 commits into
fix/108-hitl-approvalsfrom
fix/111-eda-action-cards
Closed

feat: turn EDA findings into one-click-to-prep action cards#172
lucastononro wants to merge 4 commits into
fix/108-hitl-approvalsfrom
fix/111-eda-action-cards

Conversation

@lucastononro

@lucastononro lucastononro commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

The eda agent writes a prose report.md flagging leakage risks, class imbalance, high-cardinality columns, multicollinearity — but the user had to read prose and then re-ask the agent to act. Now the eda agent ALSO emits its findings as structured items (finding type + affected columns + recommendation), rendered as canvas cards with an "Apply in prep" button that pre-fills the chat prompt with a concrete data_prep instruction — the EDA→prep handoff becomes a click instead of a paragraph.

Stacked on #171 (fix/108-hitl-approvals) → #170 (fix/106-resume-sessions).

Changes

Backend

  • New report-eda-findings capability skill (backend/skills/report-eda-findings/): one call per EDA pass with the full findings batch. Each finding: finding_type (12-value enum: leakage, class_imbalance, high_cardinality, multicollinearity, missing_values, outliers, duplicates, skewed_target, id_column, constant_column, datetime_leakage, other), columns, severity (info/warning/critical), summary, and recommendation phrased as an instruction data_prep can execute verbatim. The handler normalizes defensively (unknown type/severity coerced, scalar columns wrapped, text clipped, 50-finding cap, items without summary+recommendation dropped) and publishes a single persisted eda_findings event.
  • backend/agents/eda.yaml: skill declared + task step 7 — call it once, immediately after report.md, mirroring the same findings the prose narrates. The report.md/report_ready flow is untouched; this is an additive channel. No other agent gains the skill.

Frontend

  • New Findings tab in WorkspaceCanvas (auto-opens when findings arrive; only steals focus when no tab is active — same contract as report/metrics), rendering EdaFindingsPanel: severity-sorted cards with type badge, monospace column chips, summary, recommendation.
  • Apply in prep: pre-fills the chat draft with In data prep, address the EDA finding [type] on \cols`: `; multiple clicks stack instructions line-by-line into one prompt, which the user reviews and sends through the orchestrator as usual.
  • useSessionStream: eda_findings reducer case + restore-on-reload hydration (findings persisted as a system Message), deduped on (type + columns + summary) so backend resends / re-runs don't double the cards; findings state reset on session switch.

Test plan

Existing (no regression): full backend suite green — 326 passed, 8 skipped; tsc --noEmit, next lint, next build, ruff check all green.

New (backend/tests/test_eda_findings.py, 7 tests):

  • skill discoverable with the expected schema (required: [findings], per-item finding_type/summary/recommendation)
  • eda declares the skill; explicit default-path test that chat / orchestrator / data_prep / feature_eng / trainer / reviewer skill lists are unchanged — when the feature isn't triggered nothing else moves
  • handler publishes one normalized eda_findings event (count, stage, severity default)
  • malformed fields coerced (unknown type→other, bogus severity→warning, scalar columns wrapped, whitespace stripped) with invalid items dropped and reported
  • empty/invalid batches return is_error and publish nothing
  • 50-finding batch cap

Closes #111

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wp66uSq9saSpRq9Bbmjxj4

Greptile Summary

This PR adds a structured EDA findings channel alongside the existing report.md prose output. The EDA agent now emits findings as typed, severity-ranked items; the frontend renders them as canvas action cards with an "Apply in prep" button that pre-fills the chat draft with a concrete data_prep instruction.

  • Backend (report-eda-findings skill): new create_handler factory, defensive normalization (unknown types/severities coerced, scalar columns wrapped, 50-finding cap with a distinct capped counter separate from dropped), and 7 tests covering discovery, agent isolation, coercion, empty-batch rejection, and the cap.
  • Frontend (EdaFindingsPanel, WorkspaceCanvas, useSessionStream): findings state with ref-based dedup, live-SSE and reload-hydration paths, severity-sorted cards using a stable compound key, and an auto-open Findings tab that only steals focus when no tab is active.

Confidence Score: 5/5

Safe to merge. The change is purely additive — an extra structured channel alongside the unchanged prose report, with no modifications to existing event handling paths.

All new code paths are well-tested (7 new backend tests, all existing 326 pass). The backend skill is additive and isolated to the EDA agent. Frontend state management follows established patterns with correct dedup, session reset, and reload hydration. The only finding is a minor comment inaccuracy in the connectSSE stability annotation.

Files Needing Attention: No files require special attention. useSessionStream.ts has a comment inaccuracy in the stability annotation for appendEdaFindings, but the runtime invariant is intact.

Important Files Changed

Filename Overview
backend/skills/report-eda-findings/handler.py New skill handler; uses the established create_handler factory pattern (matching show-html). Defensive normalization, separate capped vs dropped counts, and proper is_error on empty batches are all correct.
backend/tests/test_eda_findings.py Seven tests covering skill discovery, agent isolation, normalization, coercion, empty-batch rejection, and cap behaviour; all use the correct _PublishRecorder pattern.
frontend/src/lib/useSessionStream.ts EDA findings state added with correct dedup-key ref, proper session-reset, and restore-on-reload path. Stability comment for appendEdaFindings inside the connectSSE dep block incorrectly documents its dep array as [] when it is [openCanvas].
frontend/src/components/workspace/EdaFindingsPanel.tsx New panel component using stable compound key (finding_type:columns:summary), severity-sorted rendering, and correct named export per component style guide.
frontend/src/components/workspace/WorkspaceCanvas.tsx Findings tab wired with correct auto-open effect (`setActiveTabId((prev) => prev

Reviews (2): Last reviewed commit: "Merge branch 'staging-v0.0.5' into fix/1..." | Re-trigger Greptile

Backend:
- New `report-eda-findings` capability skill: the eda agent publishes
  its report.md findings ALSO as structured items — finding type
  (leakage / class_imbalance / high_cardinality / multicollinearity /
  missing_values / outliers / duplicates / skewed_target / id_column /
  constant_column / datetime_leakage / other), affected columns,
  severity, summary, and a recommendation phrased as a verbatim
  data_prep instruction. Handler normalizes (unknown type/severity
  coerced, scalar columns wrapped, 50-finding cap) and publishes one
  persisted `eda_findings` event per batch.
- eda.yaml: skill declared + a task-list step 7 instructing the agent
  to call it once right after report.md, mirroring the prose findings.
  No other agent gains the skill — default behavior elsewhere unchanged.

Frontend:
- New Findings canvas tab (WorkspaceCanvas) rendering EdaFindingsPanel:
  severity-sorted cards with type badge, column chips, summary,
  recommendation, and an "Apply in prep" button.
- "Apply in prep" pre-fills the chat input with "In data prep, address
  the EDA finding [type] on `cols`: <recommendation>" — multiple clicks
  stack line-by-line so one prompt can carry several prep actions.
- useSessionStream: `eda_findings` reducer case + restore-on-reload
  hydration, deduped on (type + columns + summary).

Tests: 7 new (skill discovery + schema, eda-only skill declaration with
an explicit other-agents-unchanged check, normalization, malformed-field
coercion, empty/invalid batches error without publishing, batch cap).

Closes #111

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wp66uSq9saSpRq9Bbmjxj4
Comment thread frontend/src/components/workspace/EdaFindingsPanel.tsx
Comment thread frontend/src/components/workspace/EdaFindingsPanel.tsx Outdated
Comment thread backend/skills/report-eda-findings/handler.py
lucastononro and others added 3 commits July 29, 2026 16:23
- EdaFindingsPanel: stable content-derived card key (was the sorted-array
  index, which shifts when new findings arrive — resetting each card's
  applied state and allowing duplicate "Apply in prep" appends).
- EdaFindingsPanel: named export per components/ style guide.
- report-eda-findings handler: report items truncated by the 50-finding
  cap separately from schema-invalid drops, so the agent doesn't mistake
  the cap for a formatting problem and retry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	frontend/src/lib/useSessionStream.ts
@lucastononro

Copy link
Copy Markdown
Owner Author

Merged into integration branch staging-v0.0.5 (see the STAGING-v0.0.5.md ledger on that branch for merge order, Greptile follow-ups and test results). These changes will land on main via the staging merge — closing to clear the queue.

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