Skip to content

Move remove preflight off the UI thread - #18

Merged
harder merged 2 commits into
mainfrom
fix/remove-dialog-activation
Aug 31, 2026
Merged

harder merged 2 commits into
mainfrom
fix/remove-dialog-activation

Conversation

@harder

@harder harder commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Summary

Moves Installed-tab remove preflight completely off the Terminal.Gui thread and closes an adjacent modal-dispatch ownership race.

This addresses the final Needs a closer look finding from PR #17 (review 5071638437). The review was correct: compact eligibility still reached native filesystem capture synchronously through OpenRemoveDialogInternal, so slow or disconnected roots could freeze the TUI before the advanced wizard's background evaluation began.

User-facing changes

  • Opening remove no longer performs target grouping or native safety inspection on the UI thread.
  • The Installed footer shows an inline checking removal safety… spinner while preflight runs.
  • Repeated x presses cannot launch overlapping remove preflights or dialogs.
  • Leaving the Installed tab or shutting down cancels queued preflight and prevents a stale dialog from appearing later.
  • Compact confirmation remains available for simple removals; complex, warned, or blocked removals still open the advanced wizard.
  • The advanced wizard reuses the completed primary preflight result instead of repeating the same native inspection, while retaining its required fresh validation immediately before deletion.

Implementation and hardening

  • Added an app-owned asynchronous RemoveDialogPlan boundary that builds targets and evaluates compact eligibility on the thread pool.
  • Added cancellation checks before and between agent/package/repository grouping, path identity work, and multi-skill native validation.
  • Captured the Installed removal token before the first await and tied it to tab/app lifetime through CancellationTokenSourceSlot.
  • Added a start-aware owned UI dispatcher for callbacks that enter synchronous modal subloops:
    • cancellation rejects callbacks that are still queued;
    • once a callback starts, its background owner remains alive until the modal returns.
  • Passed prebuilt targets and the primary evaluation into RemoveScreen; display caching does not weaken finish-time authority revalidation.
  • Recorded the finding, disposition, analogous-path audit, and durable lifecycle rules in the adversarial audit, AGENTS.md, and the UI lifecycle guide.

Regression coverage

  • Proves remove preflight evaluation runs on a worker thread.
  • Proves pre-cancellation prevents evaluation.
  • Proves repeated Installed-tab remove requests are gated.
  • Proves tab deactivation cancels preflight without scheduling a stale refresh/dialog.
  • Proves owned dispatch rejects canceled queued callbacks.
  • Proves cancellation cannot release ownership after a modal callback has started.

Validation

  • dotnet format --verify-no-changes --no-restore
  • Debug build: passed
  • Debug tests: 772 passed
  • Release build: passed
  • Release tests: 772 passed
  • Standalone macOS ARM64 Native AOT publish: passed with IL2026, IL3050, and IL3053 promoted to errors
  • gh extension macOS ARM64 Native AOT publish: passed

Release notes

Remove dialogs now open responsively even when an installed skill is located on a slow or disconnected filesystem. SkillView performs removal safety checks in the background, prevents duplicate remove requests while checking, cancels stale work on navigation/shutdown, and preserves compact versus advanced confirmation behavior without duplicate native inspection.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Concurrent inventory loading can incorrectly clear the active removal preflight spinner and footer state.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Moves removal preflight and safety inspection off the Terminal.Gui thread while preserving modal ownership and cancellation behavior.

Changes:

  • Adds cancellable background remove planning and reuses evaluations.
  • Introduces start-aware modal dispatch ownership.
  • Adds regression tests and lifecycle documentation.
File summaries
File Description
AGENTS.md Documents removal preflight and modal ownership rules.
agent_docs/ui-lifecycle-and-resource-bounds.md Records lifecycle and cancellation behavior.
docs/reviews/adversarial-concurrency-resource-cancellation-audit-2026-08-28.md Documents the finding and resolution.
src/SkillView.Core/Inventory/RemoveTargetResolver.cs Adds cancellation-aware target building and evaluation.
src/SkillView.Core/Ui/InstalledTabView.cs Owns and gates asynchronous remove preflight.
src/SkillView.Core/Ui/RemoveScreen.cs Reuses precomputed targets and evaluations.
src/SkillView.Core/Ui/SkillViewApp.cs Adds start-aware owned UI dispatch.
src/SkillView.Core/Ui/SkillViewWorkflowCoordinator.cs Builds removal plans off-thread and dispatches modals.
tests/SkillView.Tests/Ui/InstalledTabViewTests.cs Tests gating, refresh, and cancellation.
tests/SkillView.Tests/Ui/SkillViewAppTests.cs Tests owned-dispatch cancellation races.
tests/SkillView.Tests/Ui/SkillViewWorkflowCoordinatorTests.cs Tests worker-thread planning and pre-cancellation.
tests/SkillView.Tests/Ui/UpdatesTabViewTests.cs Updates callback signatures.
Review details
  • Files reviewed: 12/12 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/SkillView.Core/Ui/Tabs/InstalledTabView.cs Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Removal safety, nested modal ownership, and cancellation timing remain sufficiently concurrency-sensitive to warrant final human review.

Review details
  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@harder
harder merged commit 8d028ae into main Aug 31, 2026
9 checks passed
@harder
harder deleted the fix/remove-dialog-activation branch October 3, 2026 22:38
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.

2 participants