Close the device-gone hole, then delete the retired step-stack device pane - #171
Open
Yona-Appletree wants to merge 10 commits into
Open
Close the device-gone hole, then delete the retired step-stack device pane#171Yona-Appletree wants to merge 10 commits into
Yona-Appletree wants to merge 10 commits into
Conversation
…ing quiesces The editor's right column has exactly one device surface (D43), but `lens_device_card()` returned `None` the moment the lens device reported `DeviceState::Gone` — the gallery's Offline filter fired at lens scale too. Nothing resets the project on device-gone, so the project stayed `Ready`, panes kept rendering, and the shell fell through to the RETIRED step-stack device pane. Stable state, not a transient. - `device_card_from_live_evidence` is the unfiltered derivation and is total; `live_device_card` keeps the Offline filter for the gallery roster only (there the registry card is better informed). The lens card now fades to "Seen …/Reconnect" instead of vanishing — the lens and the project are untouched, so a flaky cable never yanks anyone out of their editor. - Live evidence carries no registry entry, so the offline lens borrows the remembered card's sighting rather than reading "Not seen yet". - `settle_connect_outcome`'s four `remove_kind` calls now quiesce the lens first when it sits on that kind. `remove_kind` alone dropped the lens id but left the mirror dressed: project `Ready`, panes up, no lens card. Pins the invariant that had ZERO coverage and made this invisible: panes non-empty => `view.lens_card.is_some()`, held across Booting / BlankFlash / Bootloader / ForeignFirmware / Gone and the sim lens. Refs docs/defects/2026-07-28-retired-device-pane-still-reachable.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
D43 made the grown device CARD the editor's device surface; with the device-gone hole closed the pane has no reachable path left. This removes it, the DTOs it alone used, and its stories/baselines. Core: DeviceController::view + status/disconnected/connected/firmware section helpers and the DeviceRuntimeEvidence they read; steps_view.rs (UiStepsView/UiStepView/UiStepState); UiViewContent::Stack and ::Empty (the latter's only constructor was UiStepView::new); the apply_activity StackSection branch and the UxActivityTarget::StackSection variant; body_actions' stack recursion; the exports. Web: core/view/stack_view.rs, src/app/device/, the shell's group_panes split (it existed only to peel the device pane out of the pane list), and the device story fixtures. The 16 device_section_target call sites split by what they narrate: - Six project-facing ones (Opening/Connecting project, Checking running projects, Loading demo project) retarget to the PROJECT pane, which is where that work is visible and already the target of refresh_project / sync_project_after_attach. - Ten device-link ones are removed. The card derives that narration itself — ConnectFlowState via gallery_connect_evidence, session.operation_label(), and the card-owned op flow — so the pane emissions were a parallel copy that landed nowhere once the gallery was showing. management_event_sink loses its UiActivityView mirror accordingly; run_device_management now publishes a fresh view before the long manage await so the card overlay is up. Tests rewritten, not deleted: the ladder's soft ending, the incompatible and no-firmware escalations, and the pane inventory now assert on the lens CARD and on "project + bus panes, device card". ADRs 2026-07-05-studio-pane-grammar (device pane as "intended third consumer") and 2026-06-22-studio-device-ux-workflow are marked superseded. BREAKING (UI): DeviceOp::DisconnectDevice loses its only entry point — the pane's Disconnect button. The op, handler, and e2e coverage stay; the card has no disconnect verb yet. Erase is unaffected: the card's Danger tab dispatches DeployOp::EraseDevice, which runs the same reset_to_blank. 54 baselines deleted; ~30 rebaseline in CI (validate-stories auto-commits per docs/adr/2026-07-26-ci-story-auto-commit.md — nothing captured locally). Closes docs/defects/2026-07-28-retired-device-pane-still-reachable.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deleting the shell stories took `studio/layout/studio-shell/simulator-idle` with them — and that was DEFAULT_STORY_ID. `StoryBook` `.expect()`ed it, so the storybook rendered an empty body and the capture pipeline reported "No story links were discovered from the storybook page": a stale constant surfacing three layers away from its cause, with no console error. - DEFAULT_STORY_ID → `studio/home/home-gallery/populated`. - `StoryBook` falls back to the FIRST registered story when the default is unknown, so a stale default degrades to "wrong story" rather than "no page at all". - build.rs fails the build when DEFAULT_STORY_ID names no registered story, and says why. Verified it fires on the stale value. Capture discovers 333 stories again (351 before, minus the 18 retired). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Captured in the pinned CI environment by run: https://github.com/light-player/lightplayer/actions/runs/30349171275
Contributor
CI refreshed the story baselines on this branchThe Review every PNG in the PR's Files changed view (swipe / onion-skin).
|
…pane-2242af # Conflicts: # docs/defects/2026-07-28-retired-device-pane-still-reachable.md # docs/defects/README.md # lp-app/lpa-studio-web/story-images/studio__readme__studio-hero__lg.png # lp-app/lpa-studio-web/story-images/studio__readme__studio-hero__md.png # lp-app/lpa-studio-web/story-images/studio__readme__studio-hero__sm.png
Captured in the pinned CI environment by run: https://github.com/light-player/lightplayer/actions/runs/30350062140
…' into claude/retire-device-pane-2242af
…pane-2242af # Conflicts: # lp-app/lpa-studio-core/src/app/device/device_event_adapter.rs # lp-app/lpa-studio-core/src/app/studio/studio_controller.rs
Captured in the pinned CI environment by run: https://github.com/light-player/lightplayer/actions/runs/30374123460
Captured in the pinned CI environment by run: https://github.com/light-player/lightplayer/actions/runs/30375182760
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.


Closes the defect that made the retired device pane reachable, then deletes the pane.
Read
docs/defects/2026-07-28-retired-device-pane-still-reachable.mdfirst — it carries the full root-cause trace. (That file wasn't inmain; it and the README-hero fix rode the tail ofclaude/upbeat-leavitt-0a9b73and never merged, so they come along here.)Phase 1 — the holes (
4ef773d)The editor has exactly one device surface, but
lens_device_card()returnedNonethe moment the lens device reportedDeviceState::Gone: the gallery roster's Offline filter was firing at lens scale too. Nothing resets the project on device-gone, so the project stayedReady, panes kept rendering, and the shell fell through to the retired pane. Stable state, not a transient.device_card_from_live_evidenceis the unfiltered, total derivation.live_device_cardkeeps the Offline filter for the gallery roster only (there the registry card is better informed). The unplugged lens now fades to "Seen …/Reconnect" rather than vanishing — the lens and the project are untouched, per Yona's call: a flaky cable must not yank anyone out of their editor.settle_connect_outcome's fourremove_kindcalls becameclear_connect_slot, which quiesces the lens first when it sits on that kind.remove_kindalone dropped the lens id but left the mirror dressed.Three tests where there were zero before:
panes_never_render_without_a_lens_card(Booting / BlankFlash / Bootloader / ForeignFirmware / Gone + the sim lens),an_unplugged_lens_fades_to_an_offline_card_and_keeps_the_editor,a_soft_connect_ending_on_the_lens_kind_returns_to_the_gallery.Phase 2 — the deletion (
9b116ee)~1750 lines out. The interesting part is the 16
device_section_targetcall sites, which split by what they narrate:UxActivityTarget::pane(ProjectController::NODE_ID)— the precedentrefresh_projectandsync_project_after_attachalready use).ConnectFlowState→gallery_connect_evidence,session.operation_label(), and the card-owned op flow), so the pane emissions were a parallel copy that landed nowhere whenever the gallery was showing.management_event_sinkloses itsUiActivityViewmirror to match;run_device_managementnow publishes a fresh view before the long manage await so the card overlay is up.Tests were rewritten, not dropped — the M6 ladder ending, the incompatible and no-firmware escalations, and the pane inventory now assert on the lens card.
DeviceOp::DisconnectDeviceloses its only UI entry point (the pane's Disconnect button). The op, its handler, and its e2e coverage all stay; the card has no disconnect verb. It was on the verified delete inventory, but flagging it explicitly since it's a real behavior change — say the word and I'll add a card affordance in a follow-up.Erase is not affected: the card's Danger tab dispatches
DeployOp::EraseDevice, which runs the samereset_to_blankthe pane's "Erase device" did.Decided explicitly, as asked:
UiTerminalLine/TerminalOutputkept. They hang offUiActivityView(a KEEP surface), still render there, and still have story coverage. Nothing in production populates the field — that's its own cleanup, not this PR's. The two zero-caller mutators (push_terminal_line,retain_recent_terminal_lines) are gone.UiViewContent::Emptydeleted. Its only constructor wasUiStepView::new.Validation
just checkandjust testgreen locally (664 lpa-studio-core tests); story bundle builds.Baselines: 54 committed PNGs deleted, ~30 expected to rebaseline. Nothing was captured locally — validate-stories auto-commits to this branch per
docs/adr/2026-07-26-ci-story-auto-commit.md.Docs
ADR
2026-07-05-studio-pane-grammar(device pane as the grammar's "intended third consumer" + follow-up (a)) superseded;2026-06-22-studio-device-ux-workflowmarked superseded; websrc/README.mdupdated; defect closed and registry row added with a newretired-surface-still-reachableclass.🤖 Generated with Claude Code