Skip to content

feat(frontend): render discovered tasks distinctly + INFO drift filter (PR 3 of 5 for goldfive#423) - #291

Merged
pedapudi merged 1 commit into
mainfrom
feat/plan-descriptive-growth-pr3-frontend-rendering
May 14, 2026
Merged

pedapudi merged 1 commit into
mainfrom
feat/plan-descriptive-growth-pr3-frontend-rendering

Conversation

@pedapudi

Copy link
Copy Markdown
Owner

Summary

PR 3 of 5 for the plan-descriptive-growth feature (goldfive#423). Wires harmonograf end-to-end so operators can see which tasks the framework discovered reactively at delegation-observed time vs. tasks the planner authored up front. PR 1 added the data model (Task.discovered: bool + discovery_identity_hash); this PR is the rendering layer.

  • Plan view: discovered task cards render with a dashed tertiary-color border + a small "DISC" pill in the bottom-right. Non-discovered cards render byte-identically to before (back-compat baseline test pins this). A "+N discovered" badge surfaces on the panel summary when the count is non-zero.
  • Interventions panel: INFO-severity NEW_WORK_DISCOVERED rows (framework-synthesised, per design doc §4.6) render at 60% opacity via data-observational="true". A "Hide observational discoveries (N)" toggle in the header lets users hide them entirely (off by default — users SHOULD see them). WARNING-severity discoveries (sub-agent-authored via report_new_work_discovered) render normally.
  • Server round-trip: convert.py + storage/sqlite.py now pass discovered + discovery_identity_hash through pb → storage → pb in both directions. Without this the frontend would see the markers on initial wire but lose them on reconnect via GetSessionPlanHistory.
  • Proto stubs: regenerated frontend/src/pb/** via make proto-ts. The PR 1 bump on main updated only the submodule pointer and forgot to regen the stubs; this PR catches them up. Also surfaces the other goldfive PRs bundled into the same submodule pointer (JUSTIFIED_DEVIATION, CAPABILITY_MISMATCH, CONFUSION removal).

Visual rendering changes

Plan view (bottom of harmonograf UI) — before this PR, all task cards rendered uniformly. After this PR:

  • A discovered task card gains a dashed border (orange/tertiary) and a small "DISC" pill at bottom-right.
  • A "+1 discovered" pill appears next to the plan summary header on the right side of the panel.
  • Plans with no discovered tasks render unchanged.

Interventions panel — before this PR, all NEW_WORK_DISCOVERED rows rendered identically regardless of severity. After this PR:

  • An INFO-severity row renders at lower contrast (0.6 opacity).
  • The header gains a "Hide observational discoveries (N)" checkbox when at least one such row exists.
  • Toggling on hides only the observational rows; WARNING rows stay visible.

Browser-verified against a synthesised test DB with tasks.discovered=1 rows. Screenshot showed the dashed first-card border, "+1 discovered" pill, NEW_WORK_DISCOVERED row in the interventions list, and the filter toggle all rendering as designed.

Per-component breakdown

File Change
frontend/src/gantt/types.ts Task.discovered?: boolean
frontend/src/rpc/goldfiveEvent.ts convertGoldfiveTask passes discovered through
frontend/src/components/TaskStages/TaskStagesGraph.tsx --discovered class + DISC pill SVG group
frontend/src/components/TaskStages/TaskStagesGraph.css dashed-border + DISC badge styles
frontend/src/components/TaskStages/TaskPlanPanel.tsx +N discovered badge next to summary
frontend/src/components/Interventions/InterventionsList.tsx isObservationalDiscovery + filter toggle + data-observational
frontend/src/components/Interventions/InterventionsList.css filter chrome + 0.6-opacity observational row
frontend/src/pb/** regenerated proto stubs (PR 1 bump + same-batch goldfive PRs)
server/harmonograf_server/convert.py both directions of Task round-trip
server/harmonograf_server/storage/sqlite.py new columns + ALTER TABLE migration

Test coverage

  • TaskStagesGraph.test.tsx — 5 new tests in a discovered-task rendering (goldfive#423) block:
    • Baseline: plan with no discovered tasks renders no DISC badge / no accent class.
    • Single discovered task gets the class + badge + data-discovered="true" + data-testid.
    • Mixed plan: only discovered tasks get flagged.
    • Legacy fixture (no discovered field at all) renders as non-discovered.
    • Tooltip hint includes "discovered at runtime".
  • InterventionsList.test.tsx — 5 new tests in a observational discovery filter (goldfive#423) block:
    • INFO-severity new_work_discovered rows flag data-observational.
    • WARNING-severity rows do NOT.
    • Toggle is suppressed when no observational rows exist.
    • Toggle defaults to off; observational rows visible.
    • Flipping the toggle hides only observational rows; actionable rows stay.
  • goldfiveEvent.test.ts — 1 new test for Task.discovered round-trip through convertGoldfiveTask (forecast vs. discovered fixtures).
  • test_convert_round_trip.py — 4 new tests + 1 extended:
    • test_pb_to_storage_preserves_discovered_overlay (pure converter)
    • test_storage_to_pb_preserves_discovered_overlay (inverse)
    • test_storage_round_trip_preserves_discovered_overlay (parametrised over memory + sqlite)
    • test_storage_round_trip_legacy_plan_defaults_discovered_false (legacy frame → defaults)
    • Extended test_sqlite_migration_adds_columns_no_data_loss to assert the discovery fields too.

Test plan

  • pnpm test — all new frontend tests pass (722 passing; 2 pre-existing failures in TrajectoryView.headerMath.test.tsx are NOT caused by this PR — verified by stashing the diff and re-running).
  • pnpm exec tsc --noEmit — clean.
  • pnpm exec eslint on changed files — clean.
  • pnpm build — clean.
  • pytest server/tests/ — 453 passing (including 15/15 in test_convert_round_trip.py).
  • Browser verification: stack running against a worktree-isolated test DB; plan view shows the discovery accent + "+1 discovered" badge; interventions panel shows the toggle + dimmed row.

Constraints honoured

…r (PR 3 of 5 for goldfive#423)

Plan-descriptive-growth overlay (goldfive#423) installs tasks reactively
at delegation-observed time. PR 1 added the data model (Task.discovered
bool + discovery_identity_hash); this PR wires harmonograf end-to-end so
operators can SEE which tasks were discovered vs. forecast.

Frontend (plan view):
- TaskStagesGraph: discovered cards render with a dashed tertiary-color
  border and a "DISC" pill in the bottom-right; non-discovered cards
  render byte-identically to before. Cross-axis with execution status —
  the dashed accent layers on top of fill, agent stripe, and status dot.
- TaskPlanPanel: "+N discovered" pill next to the plan summary when at
  least one discovered task exists; suppressed otherwise.
- gantt/types.ts: ``Task.discovered`` (optional bool, defaults to false).
- rpc/goldfiveEvent.ts: ``convertGoldfiveTask`` reads ``t.discovered``
  with explicit ``Boolean()`` coercion so legacy proto frames (no field)
  land as ``false`` — the back-compat default specified in the proto.

Frontend (interventions panel):
- InterventionsList: rows with
  ``driftKind=new_work_discovered && severity=info`` (framework-
  synthesised, design doc §4.6) carry ``data-observational="true"`` and
  render at 0.6 opacity. WARNING-severity discoveries (sub-agent-
  authored via ``report_new_work_discovered``) render normally.
- New "Hide observational discoveries (N)" toggle in the list header;
  off by default per the PR brief — users SHOULD see observational
  rows by default. When toggled on, only observational rows are
  filtered; actionable rows stay.

Server (round-trip):
- convert.py: ``goldfive_pb_task_to_storage`` and
  ``storage_task_to_goldfive_pb`` pass ``discovered`` and
  ``discovery_identity_hash`` through both directions. Without this,
  ``GetSessionPlanHistory`` replay would drop the markers on
  reconnect and the frontend would render forecast-styled cards even
  when the wire frame says discovered.
- storage/sqlite.py: two new columns on ``tasks`` with the standard
  ALTER TABLE migration for pre-#423 DBs. Schema declaration mirrors
  the supersedes pattern; SELECT defends with ``in row_keys`` so a
  partially-migrated DB still reads safely.

Proto stubs:
- Regenerated frontend/src/pb/** via ``make proto-ts``. The PR 1 bump
  on main updated only the submodule pointer (no stub regen); this PR
  catches the stubs up so the new ``Task.discovered`` field is visible
  to TS, alongside the other goldfive PRs (#428 JUSTIFIED_DEVIATION,
  #429 CAPABILITY_MISMATCH, #427 CONFUSION removal) bundled into the
  same submodule pointer.

Tests:
- TaskStagesGraph.test.tsx: 5 new tests under "discovered-task
  rendering" — baseline (no discovered tasks), single discovered,
  mixed plan, legacy (no field at all), tooltip hint.
- InterventionsList.test.tsx: 5 new tests under "observational
  discovery filter" — INFO flagging, WARNING not flagged, toggle
  visibility, default-off behaviour, filter-flip behaviour.
- goldfiveEvent.test.ts: 1 new test for ``Task.discovered``
  round-trip through ``convertGoldfiveTask``.
- test_convert_round_trip.py: 4 new tests + 1 extended migration
  test covering pb→storage→pb and sqlite write/read across both
  memory and sqlite stores, including the legacy ALTER-TABLE path.

Backward compatibility:
- Plans with no discovered tasks render exactly as before (verified
  by the baseline test).
- Legacy proto frames without the field deserialize to
  ``discovered=false`` (verified by the legacy-fixture test).
- Existing ``tasks`` DBs without the new columns get them on next
  start via ALTER TABLE; legacy rows surface as
  ``discovered=False`` / ``discovery_identity_hash=""``.

No changes to: ``frontend/src/gantt/renderer.ts`` (recent #285/#287),
``components/Gantt/`` (gantt rendering — separate concern),
``third_party/goldfive`` (submodule pointer; bumped separately),
events/spans tables.

Coordinates with: harmonograf#285 (delegation arrow tail),
harmonograf#286 (fitAll respects spans) — both untouched.
@pedapudi
pedapudi merged commit d2b3921 into main May 14, 2026
4 checks passed
@pedapudi
pedapudi deleted the feat/plan-descriptive-growth-pr3-frontend-rendering branch May 14, 2026 06:25
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