Repository navigation
Workflow-first UX redesign and TUI polish - #1
Merged
Merged
Conversation
Introduce a truecolor palette mirroring shanselman/winget-tui (gold accent #EEC98D, warm beige #E8DCB7, dark surfaces, mint success, red danger, blue info, purple selection) and register it under the built-in "Base" and "Dialog" scheme names at app start. TuiHelpers status / editable / read-only / table schemes delegate to the new palette for AppTheme.Default; HighContrast keeps its existing 16-color StandardColor schemes for terminal-default fidelity. Phase 1 of the winget-tui redesign tracked in .claude/plans/do-a-deep-analysis-harmonic-cascade.md.
…se 2) Pull the right-pane construction (item-actions strip, Details metadata frame, SKILL.md preview + raw fallback, log overlay) into a dedicated SkillDetailPaneView : FrameView. SkillViewApp keeps its private references to the inner controls so existing render/toggle methods are unaffected — this is purely a structural extraction. Behavior-bearing methods (UpdateMetadataPane, SetPreviewText, TogglePreviewMode) stay on SkillViewApp and will migrate in later phases as call sites stabilize. Also shifts the main left/right split from 50/50 → 60/40 to match winget-tui's package-list/detail proportions. Long repo names get more room without sacrificing wrapped SKILL.md prose readability. Phase 2 of the winget-tui redesign.
Introduce a persistent top-header tab bar (◇ Search · ▣ Installed · △ Updates) in the winget-tui accent palette. Renders the active tab in bold gold and inactive tabs dim; click hit-testing per pill via OnMouseEvent. Wire 1/2/3 direct-jump and ←/→ cyclic tab keys. Search stays the embedded base view; Installed and Updates currently route to the existing modal screens (ShowInstalled / ShowUpdateScreen) — Phases 4 and 5 will replace those modals with embedded tab views. After modal close the active-tab indicator snaps back to Search so the header stays honest about what's visible. Phase 3 of the winget-tui redesign.
Introduce a winget-tui-style modal keybinding reference rendered as grouped Markdown — Navigation, Search & filter, Actions, Batch, Modes — accessible via either `?` or F1. Dismisses on Esc / Enter / `?` / Close button. Bind `?` at the window-shortcut handler alongside F1 and replace the single-line MessageBox.Query help with the new HelpOverlay. Promote `?` in the preview status bar in place of the redundant F1 label. Phase 7 (partial — key map centralization deferred until the embedded Installed/Updates tabs land, since the central key map is the right home for their per-tab hint generation).
…se 6a)
Adopt winget-tui's hybrid install vocabulary:
i — InstallConfirmModal (one screen: Scope radio · agents row · Install
button) with sensible defaults (Project scope if the cwd has a known
agent seed, otherwise User; agents pre-checked from
InstallAgentCatalog.DetectInstalledGhIds against HOME).
I — direct entry into the existing multi-step InstallScreen wizard.
The compact modal exposes an Advanced… button that escalates to the wizard
without losing the picked scope. Coordinator gains a forceAdvanced parameter
that bypasses the compact step for I; both paths flow through the same
post-install inventory rescan and success/failure status reporting.
BuildOptionsFromSelection is pulled out as a pure helper so the
scope→options mapping can be unit-tested without standing up Terminal.Gui
views (4 new tests, 379/379 unit + 1/1 integration green).
Phase 6a of the winget-tui redesign. (RemoveConfirmModal follows.)
Add a winget-tui-style "Remove {name}? [y/n]" modal that takes over the
simple-remove path. The coordinator builds the targets via
RemoveTargetResolver and routes to the compact confirm only when
CanRunCompact(eval) holds — a single CurrentInstall target with no
validation errors and no second-confirm flag. Anything that touches a
package group, repo group, agent symlink, or trips a containment / incoming-
symlink rule keeps the existing multi-step RemoveScreen wizard.
The compact modal exposes an Advanced… button (and `a` key) for users who
want the full review surface even on a simple skill.
CanRunCompact is a pure predicate over RemoveTargetEvaluation, covered by
three new tests that exercise the simple-pass, blocked-by-error, and
agent-symlink paths (382/382 unit + 1/1 integration green).
Phase 6 of the winget-tui redesign complete.
Add a monotonic _searchGeneration counter incremented on every RunSearchAsync invocation. The Invoke callback that paints results checks its captured generation against the current one and drops stale completions silently — mirrors winget-tui's app.view_generation pattern (src/app.rs) so out-of-band results from earlier searches can never clobber a newer query's view. Status bar: replace the stale `I → Installed` label (Installed is now reached via `2` jump or ←/→ cycling) with the new winget-tui-flavored shortcuts: `1/2/3 → Tabs`, `i → Install` (compact), `I → Install…` (advanced wizard). Other labels unchanged. Discoverability of the full key map stays in the `?` HelpOverlay. Phase 8a (refinements — first slice).
Convert the InstalledScreen Application.Run(window) subloop into an embedded InstalledTabView : FrameView that lives inside the main window with Visible=false until tab 2 is activated. Activation flips visibility on the search frames and kicks off an inventory snapshot load via the coordinator's CaptureInventorySnapshotAsync. Startup auto-open seeds the tab from the already-captured snapshot to avoid double-scanning. The view delegates key dispatch + detail rendering to the existing static helpers on InstalledScreen (DecideShortcut / BuildShortcuts / RenderDetail / ShortcutCommand) so the 7 InstalledScreenTests stay green unchanged. The modal Show() method, ShowInstalled/OpenInstalledSnapshot coordinator methods, and the dead private SortMode/SortLabel/BuildFooter helpers are removed. Esc/q on the tab now switches back to Search (instead of tearing down a subloop); `/` invokes the search field with focus restored. 382/382 unit + 1/1 integration green. Phase 4 of the winget-tui redesign complete.
Convert the UpdateScreen Application.Run(window) subloop into an embedded UpdatesTabView : FrameView. Activation of tab 3 (via `3`, `→`, or `u`) hides the Search/Installed panes, reveals the Updates tab, and kicks off an inventory snapshot load via CaptureInventorySnapshotAsync. Adopt winget-tui's batch vocabulary on top of the existing CheckBoxTableSourceWrapperByIndex: Space — toggle mark on current row (already wired by the wrapper) a — mark all visible rows A — unmark all u — update current row only (single skill) U — update every marked row (batch) d — dry-run Esc — back to Search tab Capability-gated checkboxes (--all / --force / --unpin / --yes) and the Dry-run / Update buttons stay; on success the tab invalidates the cached gh skill list so the next Installed-tab view shows fresh data. Strip the modal UpdateScreen.Show() body and the coordinator's ShowUpdateScreen wrapper. Keep UpdateScreen.RenderResult as a static helper so UpdateScreenTests (3 tests) stay green unchanged. The `u`/`U` legacy window shortcuts now route to ActivateTab(Updates) instead of the old modal. 382/382 unit + 1/1 integration green. Phase 5 of the winget-tui redesign complete — all three tabs are now embedded; no more modal subloops for the primary workflows.
…se 8b/1)
Search tab — `S` (or `s`) cycles SearchSort: Off (gh order) → StarsDesc →
NameAsc → NameDesc → RepoAsc → Off. Status bar reports the active mode
("sort: stars ↓" etc.). _resultsNaturalOrder preserves the natural gh-skill-
search ranking so Off restores the original sequence rather than a stale
sort. Mirrors winget-tui's app.sort_field cycle in src/app.rs.
Installed tab — `P` (capital) cycles PinFilter: All → PinnedOnly →
UnpinnedOnly → All. Footer surfaces "📌 pinned only / unpinned only" when
the filter is engaged; the per-tab StatusBar adds a "P · Pin filter" entry
via a small WithPinShortcut insertion helper. P only fires when the filter
text field doesn't own focus so typing literal P in the filter still works.
Cycle helpers are pure static methods: SkillViewApp.{CycleSearchSort,
ApplySearchSort, DescribeSearchSort} and InstalledTabView.{CyclePin,
DescribePin}. 7 new tests cover round-trip cycles, stars-desc null
ordering, case-insensitive name sort, and the Off-mode order-preservation
invariant. 389/389 unit + 1/1 integration green.
Phase 8b first slice.
Convert DoctorScreen.Show()'s Application.Run(window) subloop into DoctorTabView : FrameView. Activated by `d` via EnterDoctor() which hides all primary tabs (Search / Installed / Updates) and reveals the Doctor pane full-screen. LeaveDoctor() restores the tab the user was on before — not always Search — by remembering _tabBeforeDoctor at entry time. Doctor isn't a primary tab so it gets no pill in TabBarView; users still reach it via `d` (consistent with winget-tui's modal-like power-user views). Esc / q dismisses. Lazy gh probe is preserved: if no EnvironmentReport has been captured yet, the pane reveals immediately and the report renders once the background probe completes. Strip the modal Show() body from DoctorScreen and the coordinator's ShowDoctor wrapper; keep DoctorScreen.Render as a static helper so the 3 DoctorScreenTests pass unchanged. 389/389 unit + 1/1 integration green. Phase 8b second slice — every primary view in Skill View is now embedded; the only remaining Application.Run(window) subloops are in escalation modals (InstallScreen wizard, RemoveScreen wizard, CleanupScreen) which retain their modal semantics intentionally.
Suffix the active sort column's header with ↑/↓ ("Name ↓", "★ ↓",
"Repo ↑") so the user sees what `S` last cycled to without consulting the
status line. Off-mode (gh's natural order) shows bare "★ / Name / Repo".
TuiHelpers.ApplyColumnStyles now matches on the leading whitespace-
delimited token so the existing Skill/Name/Repo/★ width rules keep applying
when a trailing glyph is present.
Rewrite the TUI section to describe the current Search / Installed / Updates tab layout, persistent detail pane, and Doctor as a full-screen overlay. Replace the single keyboard table with grouped Navigation / Search / Installed / Updates / Other tables that match what each tab actually accepts (1/2/3 jumps, ←/→ cycling, ? help, S sort, P pin filter, Space/a/U batch select, i compact vs I advanced install). Note the developer-architecture detail that primary workflows are embedded views (no Application.Run subloops) while escalation wizards keep modal semantics. Add Tabs/ and Theming/ to the project layout table. Keep all CLI / install / troubleshooting / automation sections intact — they were already accurate.
Survey of the 118 develop commits between v2.1.0 and v2.2.0-rc.3: Adopted for free (no code changes — bug-fix / behavior wins): - MarkdownView: selection-overlay bugs fixed (#5270/#5273/#5281); Ctrl+Click on link no longer pops the context menu (#5283); right-click adds a "Copy Link" entry (#5285); OSC 8 stale-row clears and re-open lifecycle reset (#5275/#5276). - Button delimiters now anchor to edges; highlight continuity fixed (#5279). - KeystrokeNavigator automatically syncs to Source when reassigned — paths through DisableTypeToSearch (CollectionNavigator = null) are unaffected. - New code-token VisualRoles (CodeComment / CodeKeyword / CodeString / …) with sensible defaults derive automatically from our Base scheme — code fences in SKILL.md previews get token coloring at no cost. - Accent scheme constructor preserves code roles from its base (#review). Required source change: - TextView, TextViewAutocomplete, ContentsChangedEventArgs marked [Obsolete] in favor of gui-cs/Editor's EditorView. SkillView uses TextView only as a read-only scrollable surface for the raw SKILL.md preview pane and the log overlay — neither needs an editing model. Adding a second NuGet for two read-only panes isn't justified, so suppress CS0618 narrowly in the three call sites (SkillDetailPaneView, TuiHelpers.ConfigureReadOnlyPane, the field decls in SkillViewApp) plus the matching unit-test fixture. The pragma is paired with a comment explaining the choice so a future maintainer reading "obsolete" knows the migration is intentional. Not relevant to SkillView: ImageView/Sixel rendering, ColorBar mouse refactor, FileDialog End key fix, editor-oriented Command additions (Find/Replace/InsertTab/FindNext/...), AppTestHelper.RunAsync refactor (our integration tests don't use it). PackageReferenceTests and VersionFlag_IncludesTerminalGuiVersion bumped to match. Assembly version surfaces as "2.2.0" at runtime (the package "-rc.3" suffix is stripped); test assertion uses the SemVer triplet. 389/389 unit + 1/1 integration green on the new TG.
cli/cli#13245 is being closed by cli/cli#13418 (Tommy/skills list), which adds `gh skill list` with the canonical shape: { skillName, hosts[], scope, sourceURL, version, pinned, path } Where scope ∈ {project, user, custom}, hosts is always an array (empty for --dir / custom scans, multi-valued for shared install dirs like .agents/skills), and sourceURL is a full GitHub URL or local filesystem path. The PR is still open, so this change keeps SkillView's tolerant parser tolerant — upstream-canonical keys take priority but every legacy / alternate key our adapter previously recognized stays as a fallback. Adapter changes: - GhSkillListRecord adds SourceUrl (string) and Hosts (ImmutableArray) as first-class fields; the existing Agents property is now an alias of Hosts so any call site that references it continues to work. - ReadRecord reads `skillName` → fallback `name`/`skill_name`; `hosts` → fallback `agents`; `sourceURL` → fallback `repo`/`repository`. New ReadStringArray helper deduplicates the loop body. - CapabilityProbeParser re-enables the `list` probe with the actual upstream flag set (`--json --agent --scope --dir`). When the gh binary doesn't ship the subcommand the probe is a no-op — ListSubcommandPresent stays false and SkillView's filesystem scan stays in charge. - CapabilityProfile.SupportsListDir lights up automatically once the gh binary exposes the flag — unused today but available to any future tab that wants to scan a custom dir via gh. Merge changes: - CliList-only InstalledSkill records propagate SourceUrl into FrontMatter.Upstream so detail panes can render a clickable source link for skills that gh knows about but the filesystem scan hasn't seen. - Agent membership is built from Hosts (upstream-canonical) instead of Agents; the legacy singular `agent` field still seeds a single membership when no array is present. Tests: - GhSkillListAdapterTests adds canonical-payload, multi-host, custom-dir, and precedence cases (hosts beats agents, skillName beats name). - CapabilityProbeParserTests asserts the list-probe flag set instead of asserting the subcommand absent. 393/393 unit + 1/1 integration green. Nothing changes behaviorally on a gh that doesn't ship `gh skill list` yet — the alignment lands now so when PR #13418 merges, SkillView picks the canonical fields up automatically.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Swap the raw preview and log panes from TextView to Terminal.Gui.Editor.Editor and keep them configured as read-only viewer surfaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add ContextBarState record and ContextBarView with FormatForTests helper. Uses 'Locations' wording (never 'roots') per spec §50. - Add StatusHint record and StatusStripView with TruncateHintsForTests helper. Rightmost shortcut pairs survive truncation when space is tight. - Add TuiHelpers.ApplyFocusFrameStyle(FrameView, bool) that applies Heavy border for focused panes and Rounded for unfocused. - Tests: ContextBarViewTests, StatusStripViewTests, and three new TuiHelpersTests (ApplyFocusFrameStyle); all 69 target tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three bugs caught in code-quality review of Task 1: 1. Right hints could overwrite centered status text on narrow widths. Added ComputeHintLeftEdge() to calculate the right-hint budget as width minus the farther of the left-badge end or the center-status end position. The budget is now passed to TruncateHintsForTests so hints are always allocated space that does not overlap the status. 2. Exactly-fitting hint text was suppressed by the rx > x guard. Changed to rx >= leftEdge so a hint block that lands right at the safe-start boundary is drawn instead of silently dropped. 3. StatusStripView hardcoded WingetTuiTheme palette colors directly, bypassing the HighContrast / Default gate used everywhere else. Added TuiHelpers.GetStatusStripAttributes() following the same CurrentTheme branch pattern as GetStatusScheme/ConfigureTableScheme, and updated OnDrawingContent to call it. Tests added: - TruncateHintsForTests_ExactFit_IncludesHint (Bug 2 regression) - TruncateHintsForTests_OneLessThanExact_DropsHint (boundary) - ComputeHintLeftEdge_NoStatusText_ReturnsLeftBadgeEnd (Bug 1) - ComputeHintLeftEdge_WithStatusText_ReturnsEndOfCenterRegion (Bug 1) - ComputeHintLeftEdge_LeftBadgesExceedCenterEnd_ReturnsLeftBadgeEnd - ComputeHintLeftEdge_LongStatusText_ClampedToHalfWidth - GetStatusStripAttributes_DefaultTheme_UsesWingetTuiSurfaceBackground (Bug 3) - GetStatusStripAttributes_HighContrastTheme_UsesBlackBackground (Bug 3) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the top-level tab enum from Search/Installed/Updates to Discover/Installed/Changes and update all shell wiring in SkillViewApp to match the new names. - TabBarView: rename SkillViewTab enum values and pill labels; add TabLabelsForTests helper - Tabs/DiscoverTabView.cs: minimal FrameView skeleton (placeholder for Task 3 content extraction) - Tabs/ChangesTabView.cs: minimal FrameView skeleton (placeholder for Task 3 content extraction) - SkillViewApp: update every SkillViewTab.Search → Discover and SkillViewTab.Updates → Changes reference; instantiate and add the two skeleton views to the window graph; expose ChangesTabForTests and TabBarForTests test hooks; keep UpdatesTabView as the adapter for Changes tab content until the next extraction task - SkillViewAppTests: fix BuildUi_WindowShortcutFocusesQueryField assertion to expect Discover; add three new tests (BuildUi_DefaultsToDiscoverTab, BuildUi_ExposesChangesTabHook, BuildUi_TabBarUsesWorkflowFirstLabels) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the search shell (query fields, results table, detail pane) out of SkillViewApp into DiscoverTabView using the adapter pattern established by SkillDetailPaneView — all inner controls are exposed as internal properties so existing event-handler and rendering call sites in SkillViewApp continue to work unchanged. - DiscoverTabView: rewrite from skeleton into full search workspace; owns LeftFrame (search controls + TableView) and SkillDetailPaneView (right detail pane) in a persistent 60/40 layout; applies scheme to all owned controls; exposes BuildFacetSummaryForTests static helper that uses Locations: wording (not roots) and includes hidden-dir state - SkillDetailPaneView: add SetMetadataChips(params string[] chips) helper for chip-style metadata updates - SkillViewApp.BuildUi: replace 120-line inline search scaffold with a single DiscoverTabView construction; pull all control references back into existing fields so the rest of the file is unchanged; update ShowSearchPanes to toggle _discoverTab.Visible instead of separate left/right frame visibility; window.Add no longer adds _leftFrame and _rightFrame directly (they live inside DiscoverTabView now) - Tests: add DiscoverTabViewTests covering Locations wording, hidden-dir state, and empty-field omission Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SetMetadataChips was added to SkillDetailPaneView but the live metadata update path in SkillViewApp.UpdateMetadataPane bypassed it by directly setting _metadataPane.Text. - Add SetMetadataContent(string?) to SkillDetailPaneView: updates MetadataPane.Text and auto-sizes MetadataFrame.Height. MaxMetadataHeight constant moves here from SkillViewApp. - Refactor SetMetadataChips to delegate to SetMetadataContent so both callers share the same text/sizing path. - Wire UpdateMetadataPane to call _discoverTab.DetailPane.SetMetadataContent instead of reaching into _metadataPane directly. - Remove the now-redundant _metadataPane private field, its assignment, and the duplicate MinMetadataHeight / MaxMetadataHeight constants from SkillViewApp. - Add five focused unit tests covering both helpers and the null/empty reset path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add InstalledInventoryFormatter with DescribeLocation and DescribeAgents pure formatting helpers (no UI dependencies) - Replace InstalledTabView's Scope column with Location column using InstalledInventoryFormatter.DescribeLocation - Use InstalledInventoryFormatter.DescribeAgents for the Agents column - Update footer to use 'location(s)' inventory-first wording instead of 'root(s)' - Remove now-unused DisplayScope private method from InstalledTabView - Add InstalledInventoryFormatterTests covering all three scopes, empty agents, single agent, and duplicate-agent deduplication Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Installed tab column was renamed to 'Location' in Task 4, but the internal SortMode enum and sort label still used 'Scope'. This aligns the sort state with the visible column name. Changes: - SortMode.Scope → SortMode.Location - Footer sort label 'scope' → 'location' - Sort cycle transitions updated to use SortMode.Location Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add ChangesQueueRow record and ChangesQueueBuilder pure static builder that concatenates Update → Cleanup → Diagnostics rows in priority order. - Upgrade ChangesTabView from skeleton to real maintenance-queue view: full-width table, Load() binding, LoadAsync() that populates from snapshot (skills as update candidates, CleanupClassifier for cleanup candidates, fixed Diagnostics row), Enter key drills into the appropriate specialist flow. - Wire ChangesTabView into SkillViewApp: ActivateTab(Changes) now shows the queue view, OpenUpdatesFromChanges() hands off to UpdatesTabView, Cleanup row delegates to ShowCleanupScreen(), Diagnostics row enters Doctor. - Add 6 ChangesQueueBuilderTests covering ordering, empty inputs, and single-kind cases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Rename ChangesQueueBuilder.Build → BuildForTests (spec-required API name) - Move ChangesQueueBuilder.cs from Ui/Tabs/ to Ui/ (spec-required location), updating namespace SkillView.Ui.Tabs → SkillView.Ui - Add UpdatesTabView.ActivateFromChanges(Action hideChanges) so the Changes→Updates drill-in lives on the specialist view, not in SkillViewApp - Add DoctorTabView.ActivateFromChanges(Action hideChanges, Action enterDoctor) so the Changes→Doctor drill-in is wired through the spec-named file - Add SkillViewWorkflowCoordinator.OpenUpdatesFromChanges(ChangesTabView, UpdatesTabView) to own the Changes queue coordination in the coordinator layer - Update SkillViewApp.cs: remove OpenUpdatesFromChanges(), delegate to the above three surfaces; keep the ChangesTabView construction and tab lifecycle here as minimal call-site wiring - Update ChangesTabView and test to match new namespace and method name All 14 ChangesQueueBuilderTests + UpdatesTabViewTests + DoctorScreenTests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ate update row
- ChangesTabView.cs: GetOrCreateColumnStyle(0) now targets the Kind column
(was incorrectly targeting column 1, the Title column)
- ChangesTabView.LoadAsync: replace per-skill Update rows with a single
aggregate row ('N skill(s) installed — check for updates') so the queue
does not overstate update work when availability is unknown
- SkillViewWorkflowCoordinator.OpenUpdatesFromChanges: replace concrete
ChangesTabView/UpdatesTabView parameters with (Action hideChanges,
Action<Action> activateUpdates) callbacks, removing concrete UI coupling;
drop the now-unused SkillView.Ui.Tabs import
- SkillViewApp.cs: update call-site to pass the two callback lambdas
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Issue 1 — Changes queue overstates pending work: - Remove the unconditional "N skill(s) installed — check for updates" aggregate row from LoadAsync. Update availability is unknown until a dry-run runs; surfacing a fabricated row misleads the user about the queue's actual size. - Remove the unconditional "Run Doctor" diagnostics row. Doctor is always reachable via 'd' from any screen; no need to inject it as pending work. - Only Cleanup items from CleanupClassifier (real filesystem findings) remain in the queue. Issue 2 — Updates flow returns to Discover instead of Changes: - Add _openedUpdatesFromChanges flag set in onActivateUpdates. - Replace the inline () => ActivateTab(Discover) with a new LeaveUpdates() method that mirrors LeaveDoctor's pattern: when the flag is set, hide UpdatesTabView and drive ActivateTab back to Changes (bypassing the no-op guard via a temporary _activeTab reset); otherwise fall back to Discover. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DescribeWorkspaceSummary was calling SkillHealthFormatter.RowBadge and comparing its string output to determine behavior. This coupled behavior to human-facing display strings that could change without warning. Replace the string comparisons with direct checks on ValidityState and IsSymlinked so the formatter remains a pure presentation layer and DescribeWorkspaceSummary is driven by data. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
InstalledTabView replaced the narrow '!' and 'Lnk' indicators (totaling ~4 chars) with a wider 'Health' column (MinWidth=10). Update the fixed-column budget in RecomputeColumnWidths from the legacy '6 + 1 + 3' magic number to explicit named constants that account for the actual column configuration: - LocationColumnWidth = 6 (Location column, no explicit sizing) - HealthColumnMinWidth = 10 (from BuildTableSource Health column) This ensures the width allocation math doesn't drift when columns are modified, and leaves more accurate budget space for Name/Package/Agents allocation under tighter terminal widths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
….2.3 Pick up recent upstream hang-related fixes by upgrading from Terminal.Gui 2.2.1 to 2.2.2-develop.18 (the latest published develop build on NuGet). Also upgrade Terminal.Gui.Editor from 2.2.1 to stable 2.2.3, which requires Terminal.Gui >= 2.2.1 and is compatible with the develop build. Update all version-facing references in: - SkillView.Core.csproj (package pins) - PackageReferenceTests.cs (expected version assertion) - CliDispatcherHelpTests.cs (version output check - updated to match assembly version normalization behavior) - README.md, AGENTS.md (documentation) - SkillViewApp.cs (code comment) Validated with: - dotnet restore - dotnet test (targeted filter covering 22 tests including PackageReference and CliDispatcherHelp tests) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update stale version-facing statements to reflect the current Terminal.Gui pin of 2.2.2-develop.18: - Line 100: Update AOT compatibility note to reference 2.2.2-develop.18 - Line 204: Update upstream dependencies note to reference 2.2.2-develop.18 - Remove stale reference to 2.1.1-develop.* AOT configuration-crash fix The changes align with the actual TerminalGuiVersion property in SkillView.Core.csproj which defaults to 2.2.2-develop.18. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…guard
This addresses two narrow review issues:
1. InstalledTabView LocationColumnWidth hardcode:
- Changed LocationColumnWidth from 6 to 7 to account for 'Project' (7 chars)
- Added comment documenting the derivation from InstalledInventoryFormatter
actual values: 'User' (4), 'Project' (7), 'Custom' (6)
- Fixes understated width budget on tighter terminal widths
2. Terminal.Gui.Editor pairing guard and justification:
- Added SkillViewCore_PairsEditorWithBaseVersion test to catch future
version drift between Terminal.Gui and Terminal.Gui.Editor
- Updated AGENTS.md to document the intentional pairing of develop
Terminal.Gui (2.2.2-develop.18) with stable Terminal.Gui.Editor (2.2.3)
- Explains that develop build addresses prior hangs while stable editor
remains forward-compatible
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace old _statusLabel and stock StatusBar controls with the planned ContextBarView + StatusStripView components. The new status strip now dynamically updates hints based on active workspace (Discover/Installed/ Changes) and log mode. Context bar is wired and ready for facet display. Also update all user-facing guidance from obsolete 'Search / Installed / Updates' terminology to the current 'Discover / Installed / Changes' workspace model. This applies to HelpOverlay, TuiHelpers hints, and README. Fixes: - Context bar positioned at Y=2 below tab strip - Status strip at bottom replaces old label + StatusBar pair - All tabs now start at Y=2 to accommodate context bar - Status hints switch per workspace and log/preview mode - Terminology updated: Search→Discover, Updates→Changes throughout - StatusTextForTests tracks _currentStatus for test compatibility All UI tests pass (237 total). Chrome implementation now matches approved UX spec §44-49, §114-140. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… filters - Add UpdateContextBar() to populate ContextBarState with current workspace, agent filter, and hidden-dirs state - Call UpdateContextBar() from BuildUi(), ActivateTab(), RefreshHiddenDirUi(), and SubmitSearch() to keep the bar live as state changes - Render Workspace field in ContextBarView.FormatForTests() so the bar shows the active tab (Discover/Installed/Changes) - Show agent filter and hidden-dirs state on Discover tab - Add ContextBarForTests property to expose the view for testing - Add focused tests to verify context bar is created and responds to state changes The context bar now surfaces real, live state instead of staying blank. This fixes the dead code issue from the workflow-first-ux design. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1. Agent field now suppresses global shortcuts during text entry - Added _agentField check to OnWindowShortcut guard - Prevents letters like 'd', 'u', 'i' from triggering app actions while typing 2. Changes summary no longer contradicts empty queue state - Fixed DescribeWorkspaceSummary to only show health concerns when cleanup items exist - Prevents 'Needs review' status with 'no pending changes' text 3. Updated docs/help to match actual Changes workspace behavior - Removed references to row marking, batch update, and 60/40 layout - Changes tab now correctly described as maintenance queue with Enter to open 4. Context bar now meaningful for Installed/Changes workspaces - Installed shows filter text and pin filter state - Changes shows pending item count - Added state change callbacks to both tab views 5. Fixed Installed column width budgeting - Health column now allocates 12 chars for 'Needs review' (was 10) - Width calculations derive from actual possible values - MinWidth also updated to 12 to match allocation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes four remaining issues from the final review: 1. Changes empty-state messaging: Updated to be honest about what the Changes tab tracks. Changed 'Healthy' to 'No cleanup items' and removed the overly optimistic 'everything looks good' text. Added clarifying comment that update availability is unknown until dry-run. 2. Changes shortcut guidance: Fixed status strip to show 'u: Changes' instead of incorrect 'u: Updates', matching the actual global key mapping. 3. Shell chrome now more fully live: Implemented live context bar fields (LocationLabel, ProvenanceLabel, HealthLabel) for Installed tab selections, plus left-side facet badges showing agent icons. Added GetSelectedSkill() to InstalledTabView and DescribeProvenance() to InstalledInventoryFormatter to support this. 4. README alignment: Updated stale references to match current workflow-first model: - 'discovered roots' -> 'local inventory' - Sort modes: 'name/package/scope' -> 'name/package/location' - Tab references: 'UpdatesTabView' -> 'ChangesTabView' - Architecture description now matches actual tab structure All existing tests pass (462 unit + 1 integration). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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
Test Plan