Repository navigation
feat(frontend): render discovered tasks distinctly + INFO drift filter (PR 3 of 5 for goldfive#423) - #291
Merged
pedapudi merged 1 commit intoMay 14, 2026
Conversation
…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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.NEW_WORK_DISCOVEREDrows (framework-synthesised, per design doc §4.6) render at 60% opacity viadata-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 viareport_new_work_discovered) render normally.convert.py+storage/sqlite.pynow passdiscovered+discovery_identity_hashthrough pb → storage → pb in both directions. Without this the frontend would see the markers on initial wire but lose them on reconnect viaGetSessionPlanHistory.frontend/src/pb/**viamake 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,CONFUSIONremoval).Visual rendering changes
Plan view (bottom of harmonograf UI) — before this PR, all task cards rendered uniformly. After this PR:
Interventions panel — before this PR, all
NEW_WORK_DISCOVEREDrows rendered identically regardless of severity. After this PR:Browser-verified against a synthesised test DB with
tasks.discovered=1rows. 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
frontend/src/gantt/types.tsTask.discovered?: booleanfrontend/src/rpc/goldfiveEvent.tsconvertGoldfiveTaskpassesdiscoveredthroughfrontend/src/components/TaskStages/TaskStagesGraph.tsx--discoveredclass + DISC pill SVG groupfrontend/src/components/TaskStages/TaskStagesGraph.cssfrontend/src/components/TaskStages/TaskPlanPanel.tsx+N discoveredbadge next to summaryfrontend/src/components/Interventions/InterventionsList.tsxisObservationalDiscovery+ filter toggle +data-observationalfrontend/src/components/Interventions/InterventionsList.cssfrontend/src/pb/**server/harmonograf_server/convert.pyserver/harmonograf_server/storage/sqlite.pyTest coverage
discovered-task rendering (goldfive#423)block:data-discovered="true"+data-testid.discoveredfield at all) renders as non-discovered.observational discovery filter (goldfive#423)block:data-observational.Task.discoveredround-trip throughconvertGoldfiveTask(forecast vs. discovered fixtures).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)test_sqlite_migration_adds_columns_no_data_lossto assert the discovery fields too.Test plan
pnpm test— all new frontend tests pass (722 passing; 2 pre-existing failures inTrajectoryView.headerMath.test.tsxare NOT caused by this PR — verified by stashing the diff and re-running).pnpm exec tsc --noEmit— clean.pnpm exec eslinton changed files — clean.pnpm build— clean.pytest server/tests/— 453 passing (including 15/15 intest_convert_round_trip.py).Constraints honoured
frontend/src/gantt/renderer.tsorfrontend/src/components/Gantt/(recent fix(frontend/gantt): delegation-observed arrow tail anchors at source span end (closes #241) #285/fix(frontend/gantt): fitAll ignores nowMs when spans exist; freezeAt for completed sessions (closes #286) #287 areas).third_party/goldfivepointer unchanged.