fix(webview): invalidate live sibling view state on reset and settings import (vps2 F4) - #1562
easonLiangWorldedtech wants to merge 24 commits into
Conversation
📝 SummarySummary by CodeRabbit
WalkthroughThe change adds durable per-view mode and provider state, stable webview identifiers, provider-specific command routing, serialized tab creation, import/export isolation, and task-scoped mode switching. It also adds broad tests for persistence, lifecycle handling, profile repair, and storage fallback. ChangesPer-view state and webview identity
Panel commands and integrations
Priority: ➖ Normal Estimated code review effort: 5 (Critical) | ~90 minutes Merge Risk: 🟡 Moderate · up to This change adds durable per-view state and multi-panel routing. A few edge cases should be resolved before merge: a legacy profile entry can wipe the saved API profile selection for all views on launch; deleting a profile can restore per-view pins to the deleted profile; and a failure while refreshing one open tab can stop a reset from clearing the remaining tabs. Normal flows appear covered by tests, but these paths can leave users with wrong or stale configuration after reset, import, or profile deletion. Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (2 errors, 1 warning)
✅ Passed checks (5 passed)
Full details: Persistence IntegrityExplanation Changed persistence paths can leave stale or split state. Resolution Serialize reset/import invalidation through the same view-state write queue as all view-state mutations. Add an invalidation generation or barrier so writes that started before or during reset/import cannot recreate cleared entries. Make shared-setting and per-view persistence one atomic transaction where possible; otherwise snapshot both values, roll back the first write when the second fails, and report the operation as partially failed. Update the in-memory view cache only after the durable operation succeeds. Add tests for a queued save racing with broadcast and for a per-view write rejection after the shared write succeeds. Full details: Lifecycle Resource CleanupExplanation The changed Resolution Make the mode submission cancellation-aware. After Full details: Out of Scope Changes checkExplanation The raw summary includes many changes outside the stated F4 objective, including command registration, task-mode handling, provider profiles, webview state foundations, and UI utilities. The description claims a five-file scope, which conflicts with the supplied changeset summary.
✨ Finishing Touches 💡 2⚔️ Resolve merge conflicts 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review statusThanks for contributing. This comment tracks the review sequence and the next action. Current step: Address automated review findings and push fixes. After fixes are pushed and required CI passes, automated review restarts. Review-state labels are managed by this workflow; do not edit them manually. |
80c147f to
da97f98
Compare
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
916900f to
d56b60b
Compare
d56b60b to
c2822dc
Compare
…en view-identity tests Track the in-flight tab panel creation with a module-level promise so concurrent openClineInNewTab calls reuse one panel and provider (adds a Promise.all regression test). ClineProvider.spec sets the private view via the public resolveWebviewView() instead of a ts-ignore assignment. registerCommands.spec types evictCurrentTask/refreshWorkspace on the fixture and drops the as any attachment. eslint-suppressions: prune the registerCommands.spec.ts entry (two as any suppressions removed).
…n the concurrency assertion
…-bar posts - openClineInNewTab: extract the unserialized creation body into createTabPanelUnlocked and guard the in-flight slot clear so a settled creation cannot clobber a replacement already stored in the slot. - onDidDispose: clear the tracked tab ref only when the disposing panel is still the tracked one, so a late disposal of a replaced panel cannot clobber the replacement's ref. - MDM lookup failure: log the fallback to the output channel instead of swallowing it silently. - Route the six title-bar button handlers through a shared postActions helper that posts each action in order and logs failures with the handler-specific prefix. - package.json: add the four InTab commands to the command palette, scoped to the active tab panel. - Tests: handler-level regression for openInNewTab + popoutButtonClicked started before the first creation resolves; fresh-creation test for a settled in-flight promise; stale-panel disposal regression; retained panel assertion for disposed tab instances; rightmost-editor column placement assertion; MDM fallback output assertion; %s placeholders for primitive it.each titles. - Stryker directives for the two equivalent setPanel type-literal mutants (setPanel branches only on type === sidebar).
b9e8fb7 to
05f264b
Compare
Replace the weak toBeDefined() assertion in the dispose spec with an identity check against the panel returned during creation, per the CodeRabbit actionable comment on this PR (review run 7c4cfeb3-6dd9-4615- 9a58-70cfc705eca2). The tracked tab is now pinned with toBe(panel) before the dispose assertions, so a wrong or duplicated tracked panel fails the suite instead of passing a defined-only check. Upstream: Zoo-Code-Org#1528 (vps2 F0)
05f264b to
eac3873
Compare
Retain the tracked tab panel in the InTab handler cases and assert that getInstanceForView was called with that exact panel, per the CodeRabbit actionable comment on this PR (review run 4afe1273-8739-4235-90d3-311db5f6ccb9, inline comment 3952466254 on the tabHandlerCases spec). A handler resolving any other view now fails instead of passing on the stubbed provider result alone; the same identity pin is applied to plusButtonClickedInTab. Upstream: Zoo-Code-Org#1528 (vps2 F0)
…States Each ClineProvider instance now owns a unique viewId (renderContext plus a monotonic counter) and registers a stable viewStateId for durable persistence. - Per-view state buffer (viewLocalState) holds mode / currentApiConfigName / apiConfiguration overrides in memory; saveViewState persists the non-secret subset durably under the active view id, rekeyed to the stable id on registration. - viewStates is stored as a map pruned to the newest 50 entries; writes go through a serialized queue so concurrent provider instances merge without lost updates. - setViewStateId sanitizes ids and rejects "__proto__" so a per-view entry can never be keyed through the Object.prototype setter. - postMessageToWebview no longer awaits the webview ack: a remounted or disposed page never acknowledges, and awaiting would wedge task-critical callers. - History restore falls back to the default mode view-locally instead of writing the shared global mode. - GlobalState gains the "viewStates" key and GLOBAL_STATE_KEYS tracks it. Adds F1a coverage in ClineProvider.spec.ts (viewId uniqueness, saveViewState persistence semantics, loadViewState fallback and failure, pruning, the __proto__ guard) and adapts the two history-restore tests in ClineProvider.sticky-mode.spec.ts to the view-local restore. getState() merging of hydrated per-view values and the remaining view-state suites land in the follow-up (F1b).
…lude viewStates from settings transfer
Draft PR — vps2 unit F4 (cross-instance reset + import invalidation).
Tracking: easonLiangWorldedtech#41 (vps2 series ledger). Upstream issue: #1561 (this series' gap record; the original upstream bug is #980). Port source: upstream PR #981 (fix(webview): invalidate per-view state after reset and import) — closed draft, superseded by the vps2 series; the #41 ledger names #981 as the F4 port source.
Scope
5 files, 342 insertions, 1 deletion (measured vs stack base 8da5c6e):
Budget
Port fidelity (coordinator-verified)
Structural note on the parallelMode spec (coordinator-verified)
The CS parallelMode.spec.ts is 1790 lines: a shared preamble (L1-672), an F1-series test section (L673-1363: viewId uniqueness, local state isolation, saveViewState, stale temporary-id load), the F3 describes (L1364-1673), a blank separator (L1674), the F4 multi-instance describes (L1675-L1789), and the file's final top-level close (L1790). In this series the F1-series section lives in ClineProvider.spec.ts (shipped by F1a/F1b/F1c — the deliberate F1-series describe restructure), and the F2 unit shipped the persisted-pruning and #1065 retention tests inside the parallelMode file (absent from the CS parallelMode file). Both placements are behaviorally covered; the divergence is structural, not a coverage gap.
Series mechanics