From cb7ee45bb62233c7e61c62412d7f7bab1346e8ca Mon Sep 17 00:00:00 2001 From: Mathijs Beemsterboer <15211332+TheBeems@users.noreply.github.com> Date: Sat, 17 Oct 2026 15:35:53 +0200 Subject: [PATCH] Clean up obsolete development records and guidance --- .10x/specs/dock-allowance-refresh.md | 25 -- .../2026-07-20-dock-allowance-refresh.md | 59 --- .10x/tickets/2026-07-21-release-0-6-0.md | 59 --- .github/copilot-instructions.md | 49 +-- .../cmdpal-extension.instructions.md | 351 +----------------- CHANGELOG.md | 6 + CodexUsageDock/CodexUsageDock.csproj | 6 - SPRINTS.md | 49 --- 8 files changed, 13 insertions(+), 591 deletions(-) delete mode 100644 .10x/specs/dock-allowance-refresh.md delete mode 100644 .10x/tickets/2026-07-20-dock-allowance-refresh.md delete mode 100644 .10x/tickets/2026-07-21-release-0-6-0.md delete mode 100644 SPRINTS.md diff --git a/.10x/specs/dock-allowance-refresh.md b/.10x/specs/dock-allowance-refresh.md deleted file mode 100644 index 0457a91..0000000 --- a/.10x/specs/dock-allowance-refresh.md +++ /dev/null @@ -1,25 +0,0 @@ -Status: active -Created: 2026-07-20 -Updated: 2026-07-20 - -# Dock allowance refresh contract - -## Scope - -The Dock and the usage details page must present the same latest allowance snapshot after a completed `CodexUsageService` refresh. - -## Contract - -Given a completed refresh publishes a weekly or five-hour allowance value, when Command Palette is displaying the Dock, then the provider MUST invalidate the Dock-band collection so that the host requests a band rendered from that completed snapshot. - -The Dock MAY show the loading state while a refresh is in progress, but it MUST NOT retain a prior completed allowance after the details page has rendered the newer completed snapshot. - -## Acceptance criteria - -- A completed refresh causes a provider-level item invalidation in addition to any child-list notification. -- The Dock band returned after that invalidation contains the current snapshot's formatted allowance. -- The details page remains driven by the same `CodexUsageService.Current` snapshot. - -## Exclusions - -- No change to allowance calculation, refresh cadence, rate-limit source selection, or visual layout. diff --git a/.10x/tickets/2026-07-20-dock-allowance-refresh.md b/.10x/tickets/2026-07-20-dock-allowance-refresh.md deleted file mode 100644 index 3910f9f..0000000 --- a/.10x/tickets/2026-07-20-dock-allowance-refresh.md +++ /dev/null @@ -1,59 +0,0 @@ -Status: done -Created: 2026-07-20 -Updated: 2026-07-21 - -# Reopen Dock allowance refresh bug - -## Scope - -Make a completed usage refresh invalidate the Dock-band collection at the command-provider boundary, then add a regression test for the provider-level notification and the refreshed weekly allowance. - -## Non-goals - -- Do not change rate-limit parsing or allowance arithmetic. -- Do not touch the unrelated local-token-usage work already present in the worktree. - -## Acceptance criteria - -- Satisfy `.10x/specs/dock-allowance-refresh.md`. -- Preserve Dock visibility settings and IDs. -- Add deterministic regression coverage. -- Validate with the native ARM64 test suite using an isolated output path if the running extension locks Debug output. - -## References - -- `.10x/specs/dock-allowance-refresh.md` -- `CodexUsageDock/CodexUsageDockCommandsProvider.cs` -- `CodexUsageDock.Tests/UsageDataTests.cs` - -## Assumptions - -- Record-backed: the screenshot shows the details page at 34% while the Dock shows 37% after the same live refresh. -- Record-backed: `CodexUsageDockPage` raises an items-changed notification after every update; the provider currently does not. - -## Journal - -- 2026-07-20: Reopened from user screenshot. The running ARM64 binary contains `OnUsageUpdated`, so the earlier child-list invalidation was deployed but did not refresh the host's Dock band. -- 2026-07-20: Replaced child-list-only invalidation with provider-level Dock-band rebuilding and invalidation. The regression now asserts the provider notification and reads the replacement band. -- 2026-07-20: Focused native ARM64 test `CompletedRefreshRebuildsAndInvalidatesDockBands` passed (1/1). Full native ARM64 suite passed (113/113) using `artifacts/validation/dock-provider-refresh`. -- 2026-07-20: Stopped the active extension, built ARM64 Debug with zero warnings/errors, and ran `scripts/test-integration.ps1 -Architecture ARM64 -Configuration Debug -Register`. The manifest, registration, AppExtension discovery, and selected COM provider all passed. - -## Evidence - -- Provider-level `ItemsChanged` is raised once after a completed refresh and the rebuilt band exposes `5h 75%` in deterministic regression coverage. -- The full ARM64 test suite passed 113/113. The standard ARM64 Debug build passed with zero warnings/errors. -- Integration preflight passed after development registration. It proves registration/discovery and the provider process, not visual rendering. - -## Review - -- Verdict: pass -- Findings: The prior code only changed the internal `WrappedDockItem` list. The replacement rebuilds the same stable band ID and signals the provider boundary that the Dock host owns. It preserves settings filtering and does not alter snapshot parsing or allowance calculation. -- Residual risk: Command Palette must be manually reloaded once before visual verification; automated checks cannot prove host rendering. - -## Retrospective - -- A child `IListPage.ItemsChanged` event is insufficient evidence for a Dock update. Regression coverage must assert the `CommandProvider.ItemsChanged` boundary because that is where the host refreshes its band collection. - -## Blockers - -- None. Manual Command Palette reload remains a post-release visual verification step, not a source-code blocker. diff --git a/.10x/tickets/2026-07-21-release-0-6-0.md b/.10x/tickets/2026-07-21-release-0-6-0.md deleted file mode 100644 index 3f430d1..0000000 --- a/.10x/tickets/2026-07-21-release-0-6-0.md +++ /dev/null @@ -1,59 +0,0 @@ -Status: done -Created: 2026-07-21 -Updated: 2026-07-21 - -# Prepare release 0.6.0 - -## Scope - -Prepare version 0.6.0 from the current validated main work: the local-token weekly trend and the Dock allowance refresh fix. Update release metadata, validate the Store upload, commit the scoped changes, and push them to `origin/main`. - -## Non-goals - -- Do not submit a package to Partner Center. -- Do not create a Git tag or GitHub Release. -- Do not change Store identity, publisher, signing configuration, or tracked development manifest version. - -## Acceptance criteria - -- `CodexUsageDock.csproj` and the version assertion report `0.6.0`. -- `CHANGELOG.md` has a dated `0.6.0` section containing the unreleased user-facing entries and commit links. -- Native ARM64 tests and release package validation pass. -- `scripts/build-release.ps1` produces the versioned Store upload and checksum. -- Only inspected release and Dock-fix files are committed and `origin/main` is verified at the resulting commit. - -## References - -- `.10x/tickets/2026-07-20-dock-allowance-refresh.md` -- `DEVELOPMENT.md` release workflow -- `scripts/build-release.ps1` - -## Assumptions - -- User-ratified: release version is `0.6.0`. -- User-ratified: prepare and publish source to `origin/main`; Store submission, tag, and GitHub Release remain out of scope. - -## Journal - -- 2026-07-21: User approved version `0.6.0` after the proposed SemVer minor increment for the local-token trend feature plus Dock fix. -- 2026-07-21: Full native ARM64 tests passed (113/113). The official release builder produced and validated `CodexUsageDock-0.6.0.msixupload` and `SHA256SUMS.txt` containing x64 and ARM64 packages. - -## Evidence - -- `CodexUsageDock.csproj` and the version assertion both use `0.6.0`. -- `scripts/build-release.ps1` completed and produced the Store upload plus SHA-256 checksum under `artifacts/store`. -- The source manifest remained unchanged by the build; the builder supplied the Store package version only in its disposable build-local manifest. - -## Review - -- Verdict: pass -- Scope review: the release contains only the allowance-refresh regression fix, version metadata, changelog, and the associated task records. Generated artifacts remain untracked. -- Residual risk: the Command Palette host must still be manually reloaded to visually verify the Dock after the provider-level invalidation fix. - -## Retrospective - -- The official builder needs time beyond its first x64 package output to finish the ARM64 package and bundle. Release readiness is established only when both the `.msixupload` and checksum are present. - -## Blockers - -- None. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8a856e7..b2aa8a8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,48 +1,5 @@ -# Command Palette Extension – Copilot Instructions +# Copilot Instructions -Concise guidance for AI-assisted development of this Command Palette extension. +Read and follow [AGENTS.md](../AGENTS.md) for repository scope, engineering rules, architecture, privacy, verification, and authorization boundaries. -## Project Structure - -| Folder | Purpose | -|--------|---------| -| `Pages/` | Extension pages (ListPage, ContentPage, DynamicListPage implementations) | -| `Assets/` | Icons and images (StoreLogo.png, etc.) | -| `Properties/` | Launch settings and publish profiles | -| Root `.cs` files | Extension entry point, COM server (Program.cs), and CommandsProvider | - -## Key Conventions - -- Extensions run **out-of-process** via COM server registration -- `Program.cs` hosts the COM server — do not modify the hosting pattern -- The `CommandProvider` subclass is the entry point for all commands -- Pages are **ICommand** implementations — they can be used anywhere commands are used -- Always **Deploy** (not just Build) to register the MSIX package -- After deploying, use the **Reload** command in Command Palette to refresh - -## Build & Deploy - -1. In Visual Studio, use **Build > Deploy** (not just Build) -2. In Command Palette, run `Reload` → select "Reload Command Palette extensions" -3. For debugging, run in Debug configuration (F5) and check Output window (Ctrl+Alt+O) - -## Source Control - -If using git, remove these lines from `.gitignore` (needed for deployment): -- `**/Properties/launchSettings.json` -- `*.pubxml` - -## Available Skills - -This project includes Copilot skills for common workflows: -- **add-adaptive-card-form** — Create form-based UI with Adaptive Cards -- **add-extension-settings** — Add a settings page to your extension -- **add-dock-band** — Add persistent toolbar widgets -- **add-fallback-commands** — Add catch-all search commands -- **publish-extension** — Prepare, commit, push, publish, install, or resume a Codex Usage Dock release - -## Documentation - -- [Creating an extension](https://learn.microsoft.com/windows/powertoys/command-palette/creating-an-extension) -- [Extension samples](https://learn.microsoft.com/windows/powertoys/command-palette/samples) -- [Extensibility overview](https://learn.microsoft.com/windows/powertoys/command-palette/extensibility-overview) +Use [DEVELOPMENT.md](../DEVELOPMENT.md) as the canonical guide for SDK setup, builds, tests, integration checks, and release procedures. diff --git a/.github/instructions/cmdpal-extension.instructions.md b/.github/instructions/cmdpal-extension.instructions.md index af351c3..5614615 100644 --- a/.github/instructions/cmdpal-extension.instructions.md +++ b/.github/instructions/cmdpal-extension.instructions.md @@ -1,353 +1,10 @@ --- -description: 'Comprehensive guide for developing Command Palette extensions — covers pages, content, commands, items, icons, settings, dock, and debugging' +description: 'Repository guidance for C# changes in the Command Palette extension' applyTo: '**/*.cs' --- -# Command Palette Extension Development +# C# Development Instructions -Complete reference for building Command Palette (CmdPal) extensions. Extensions run out-of-process as MSIX-packaged COM servers. +Read and follow [AGENTS.md](../../AGENTS.md) for repository scope, engineering rules, architecture, privacy, verification, and authorization boundaries. -## Extension Architecture - -### IExtension Interface - -The root class implements `IExtension` and `IDisposable`: - -```csharp -[Guid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")] -public sealed partial class MyExtension : IExtension, IDisposable -{ - private readonly ManualResetEvent _extensionDisposedEvent; - private readonly MyCommandsProvider _provider = new(); - - public MyExtension(ManualResetEvent extensionDisposedEvent) - { - _extensionDisposedEvent = extensionDisposedEvent; - } - - public object? GetProvider(ProviderType providerType) => providerType switch - { - ProviderType.Commands => _provider, - _ => null, - }; - - public void Dispose() => _extensionDisposedEvent.Set(); -} -``` - -- Only `ProviderType.Commands` is currently supported -- The `[Guid]` must match the CLSID in `Package.appxmanifest` - -### CommandProvider - -Override `TopLevelCommands()` to register main commands. Optionally override `FallbackCommands()` and `GetDockBands()`: - -```csharp -public partial class MyCommandsProvider : CommandProvider -{ - public MyCommandsProvider() - { - DisplayName = "My Extension"; - Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png"); - } - - public override ICommandItem[] TopLevelCommands() => [ - new CommandItem(new MyPage()) { Title = DisplayName }, - ]; -} -``` - -### COM Server (Program.cs) - -`Program.cs` hosts the COM server. Do not change this pattern: - -```csharp -public class Program -{ - [MTAThread] - public static void Main(string[] args) - { - if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer") - { - global::Shmuelie.WinRTServer.ComServer server = new(); - ManualResetEvent extensionDisposedEvent = new(false); - var extensionInstance = new MyExtension(extensionDisposedEvent); - server.RegisterClass(() => extensionInstance); - server.Start(); - extensionDisposedEvent.WaitOne(); - server.Stop(); - server.UnsafeDispose(); - } - } -} -``` - -### Package.appxmanifest - -Two critical extension registrations must be present: - -1. **COM server** — `com:ComServer` with matching CLSID and `-RegisterProcessAsComServer` args -2. **App extension** — `uap3:AppExtension` with `Name="com.microsoft.commandpalette"` and `CreateInstance ClassId` matching the GUID - -The CLSID must be identical in three places: the `[Guid]` attribute, the `com:Class Id`, and the `CreateInstance ClassId`. - -## Page Types - -### ListPage (Most Common) - -Displays a searchable list of items: - -```csharp -internal sealed partial class MyPage : ListPage -{ - public MyPage() - { - Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png"); - Title = "My page"; - Name = "Open"; - } - - public override IListItem[] GetItems() => [ - new ListItem(new OpenUrlCommand("https://example.com")) { Title = "Example" }, - ]; -} -``` - -### DynamicListPage (Search-Reactive) - -Responds to search text changes for filtering or live queries: - -```csharp -internal sealed partial class MyDynamicPage : DynamicListPage -{ - private IListItem[] _filteredItems = []; - - public override void UpdateSearchText(string oldSearch, string newSearch) - { - _filteredItems = _allItems - .Where(i => i.Title.Contains(newSearch, StringComparison.OrdinalIgnoreCase)) - .ToArray(); - RaiseItemsChanged(); - } - - public override IListItem[] GetItems() => _filteredItems; -} -``` - -- Supports `Filters` property for category filtering -- Call `RaiseItemsChanged()` after updating items to notify the UI - -### ContentPage (Rich Content) - -Displays rich content like markdown, forms, or images: - -```csharp -internal sealed partial class MyContentPage : ContentPage -{ - public override IContent[] GetContent() => [ - new MarkdownContent("# Hello\nThis is **markdown**."), - ]; -} -``` - -- Can return multiple `IContent` items (mix markdown, forms, images, etc.) -- Supports `Commands` property for context menu items via `CommandContextItem` - -## Content Types - -| Type | Description | -|------|-------------| -| `MarkdownContent(string)` | Renders markdown with headers, links, code blocks, tables, images | -| `FormContent` | Adaptive Cards forms with `TemplateJson`, optional `DataJson`, and `SubmitForm()` | -| `PlainTextContent(string)` | Plain text; optional `FontFamily.Monospace` and `WrapWords` | -| `ImageContent` | Images with `MaxWidth`/`MaxHeight` constraints | -| `TreeContent` | Hierarchical nested content; override `GetChildren()` for child `IContent[]` | - -### MarkdownContent Images - -Supports `file:`, `data:` (base64), and `https:` URLs. Image hints control rendering: - -```markdown -![alt](https://example.com/img.png?--x-cmdpal-fit=fit&--x-cmdpal-maxwidth=400) -``` - -### FormContent (Adaptive Cards) - -```csharp -internal sealed partial class MyForm : FormContent -{ - public MyForm() - { - TemplateJson = """{ "type": "AdaptiveCard", ... }"""; - DataJson = """{ "name": "default" }"""; - } - - public override CommandResult SubmitForm(string payload) - { - var data = JsonSerializer.Deserialize(payload); - return CommandResult.Dismiss(); - } -} -``` - -- Design cards visually at [adaptivecards.io/designer](https://adaptivecards.io/designer) -- Use `${...}` placeholders in `TemplateJson` bound to `DataJson` properties - -## Commands - -### InvokableCommand - -Actions that do something when activated: - -```csharp -internal sealed partial class MyCommand : InvokableCommand -{ - public override string Name => "Do it"; - public override IconInfo Icon => new("\uE945"); - - public override CommandResult Invoke() - { - // Do work here - return CommandResult.Dismiss(); - } -} -``` - -### Built-in Command Helpers - -| Helper | Purpose | -|--------|---------| -| `OpenUrlCommand(string url)` | Open URL in default browser | -| `CopyTextCommand(string text)` | Copy to clipboard with toast | -| `NoOpCommand()` | Does nothing (placeholder) | -| `AnonymousCommand(Action? action)` | Lambda command; set `Result` property for navigation | - -### CommandResult Types - -| Result | Behavior | -|--------|----------| -| `CommandResult.Dismiss()` | Hide palette, go home | -| `CommandResult.KeepOpen()` | Stay on current page | -| `CommandResult.Hide()` | Hide palette, keep page state | -| `CommandResult.GoBack()` | Navigate back one page | -| `CommandResult.GoHome()` | Navigate to home page | -| `CommandResult.ShowToast("msg")` | Show toast notification, then dismiss | -| `CommandResult.Confirm(args)` | Show confirmation dialog before proceeding | - -## ListItem Properties - -```csharp -new ListItem(command) -{ - Title = "Display name", - Subtitle = "Secondary text", - Icon = new IconInfo("\uE8A7"), - Tags = [new Tag("label") { Foreground = ColorHelpers.FromRgb(255, 0, 0) }], - Details = new Details - { - Title = "Detail panel", - Body = "**Markdown** body", - HeroImage = IconHelpers.FromRelativePath("Assets\\hero.png"), - Size = ContentSize.Medium, - Metadata = [ - new DetailsLink("URL", "https://example.com"), - new DetailsSeparator(), - ], - }, - MoreCommands = [ - new CommandContextItem(deleteCommand) - { - RequestedShortcut = KeyChordHelpers.FromModifiers( - true, false, false, (int)VirtualKey.Delete), - }, - ], -} -``` - -## Sections and Grid Layouts - -### Sections - -Group items under section headers: - -```csharp -public override ISection[] GetSections() => [ - new Section { Title = "Group A", Items = itemsA }, - new Section { Title = "Group B", Items = itemsB }, -]; -``` - -### Grid Layouts - -Set `GridProperties` on a `ListPage`: - -| Layout | Description | -|--------|-------------| -| `GalleryGridLayout()` | Large tiles with title + subtitle | -| `SmallGridLayout()` | Compact grid | -| `MediumGridLayout()` | Medium tiles with title | - -## Icons - -```csharp -// Segoe Fluent UI icons (most common) -new IconInfo("\uE8A5") // Document -new IconInfo("\uE945") // Lightning bolt - -// Emoji -new IconInfo("📂") - -// Image from package assets -IconHelpers.FromRelativePath("Assets\\StoreLogo.png") - -// Remote URL or SVG -new IconInfo("https://example.com/icon.svg") - -// From exe/dll resource -new IconInfo("%systemroot%\\system32\\shell32.dll,3") -``` - -## Dynamic Updates - -- Call `RaiseItemsChanged()` on any page to trigger a UI refresh of its items -- Call `RaisePropertyChanged(propertyName)` for individual property updates (e.g., title) -- For top-level command changes, call `RaiseItemsChanged()` on the `CommandProvider` -- Use `System.Timers.Timer` for periodic background updates - -## Status Messages and Toasts - -```csharp -// Inline status message (e.g., loading indicator) -var msg = new StatusMessage -{ - Message = "Loading...", - State = MessageState.Info, - Progress = new ProgressState { IsIndeterminate = true }, -}; -ExtensionHost.ShowStatus(msg, StatusContext.Page); -ExtensionHost.HideStatus(msg); - -// Transient toast notification -new ToastStatusMessage("Copied to clipboard").Show(); -``` - -## Build & Debug - -1. Select **Debug** configuration -2. **Deploy** via Build > Deploy (not just Build) — this registers the MSIX package -3. Press **F5** to launch with debugger attached -4. Use `Debug.Write()` / `Debug.WriteLine()` for diagnostic output -5. Check Output window (**Ctrl+Alt+O**) set to "Debug" -6. In Command Palette, run `Reload` → "Reload Command Palette extensions" - -Use the `(Package)` launch profile, not `(Unpackaged)`. - -## Common Mistakes - -| Mistake | Fix | -|---------|-----| -| Building without deploying | Use Build > Deploy so the MSIX package is updated | -| Running "(Unpackaged)" profile | Select the "(Package)" launch profile | -| Forgetting to reload extensions | Run `Reload` in Command Palette after deploying | -| CLSID mismatch | Ensure `[Guid]` in .cs matches `ClassId` in Package.appxmanifest (both places) | -| Logging in hot paths | `GetItems()` is called frequently — avoid expensive work or logging here | +Use [DEVELOPMENT.md](../../DEVELOPMENT.md) as the canonical guide for SDK setup, builds, tests, integration checks, and release procedures. diff --git a/CHANGELOG.md b/CHANGELOG.md index b952f50..f162120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ the [changelog workflow](AGENTS.md#documentation-and-change-quality). ### Changed - Update the README screenshot to show the released 0.8.9 weekly dashboard. ([commit 733c44c](https://github.com/TheBeems/CodexUsageDock/commit/733c44c2a889e45d99652a02723e49fe4bfdfb3f)) +- Consolidate Copilot development guidance in `AGENTS.md` and `DEVELOPMENT.md`. ([commit c0c7bcc](https://github.com/TheBeems/CodexUsageDock/commit/c0c7bcc9121b58f2b60367cf55aed746f19e2772)) + +### Removed + +- Remove obsolete `.10x` development specifications and tickets. ([commit c0c7bcc](https://github.com/TheBeems/CodexUsageDock/commit/c0c7bcc9121b58f2b60367cf55aed746f19e2772)) +- Remove historical sprint records and the unused installer build configuration. ([commit c0c7bcc](https://github.com/TheBeems/CodexUsageDock/commit/c0c7bcc9121b58f2b60367cf55aed746f19e2772)) ## [0.8.9] - 2026-10-13 diff --git a/CodexUsageDock/CodexUsageDock.csproj b/CodexUsageDock/CodexUsageDock.csproj index 596577c..0f0a79c 100644 --- a/CodexUsageDock/CodexUsageDock.csproj +++ b/CodexUsageDock/CodexUsageDock.csproj @@ -27,12 +27,6 @@ $(DefaultItemExcludes);$(MSBuildProjectDirectory)\bin\**;$(MSBuildProjectDirectory)\obj\**;$(MSBuildProjectDirectory)\artifacts\** - - None - false - true - -