From 7273ccfd7dfc3c01d799908b8271d544292cab31 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 08:56:29 +0000 Subject: [PATCH 1/5] Remove Code-sign installer TODO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dropped — not pursuing paid code-signing (Azure Trusted Signing / OV cert) at this stage. Can revisit if broader distribution warrants the cost. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 60 --------------------------------------------------------- 1 file changed, 60 deletions(-) diff --git a/TODO.md b/TODO.md index 274f915..c8ac32a 100644 --- a/TODO.md +++ b/TODO.md @@ -297,66 +297,6 @@ Reasons: --- -## Code-sign the installer (SmartScreen / Authenticode) - -**Problem.** The v0.1.0-alpha.1 installer is unsigned. Downloading it in -Edge / Chrome trips SmartScreen's "this file isn't commonly downloaded — -make sure you trust it" warning, and running it shows the blue "Windows -protected your PC" dialog. Every user has to click through "More info → -Run anyway", which is a terrible first impression and a real deterrent. - -**Cause.** SmartScreen reputation is built from a combination of valid -Authenticode signatures plus aggregate download counts. An unsigned -binary with zero downloads is automatic prompt-territory. Signing solves -the warning immediately for EV certs and over time (as downloads -accumulate) for OV certs. - -**Options.** - -- **Azure Trusted Signing** (recommended). Microsoft's new managed - signing service, ~$10/month, gives you a cloud-hosted signing identity - with no HSM to manage. Velopack supports it natively via - `--azureTrustedSigningAccount` / `--azureTrustedSigningCertProfile` - flags on `vpk pack`. Wants an Azure subscription and an OIDC trust - relationship from the GitHub Actions runner — five-step setup, no - long-lived secrets in the repo. -- **Standard OV code-signing certificate.** From DigiCert / Sectigo / - GlobalSign, ~$200–400/year. Comes as a cert + key the runner imports. - SmartScreen reputation builds gradually rather than instantly. Easier - if you already have an account with a CA. -- **EV code-signing certificate.** ~$400–600/year, requires an HSM / - USB token (hard to use from CI without a paid signing service in front - of it) but gets immediate SmartScreen reputation. Probably overkill - for an alpha; revisit pre-1.0 stable. - -**Sketch — Azure Trusted Signing path.** - -1. Create the Azure resources (Trusted Signing account, certificate - profile, OIDC trust to the GitHub repo) per - . -2. Add the federated-identity secrets / variables to the repo: tenant - id, client id, account / profile names. -3. In `release.yml`, extend the `vpk pack` step with - `--azureTrustedSigningAccount`, `--azureTrustedSigningCertProfile`, - `--azureTrustedSigningEndpoint` (region URL) and an `azure/login@v2` - step ahead of it for federated auth. -4. Verify with `signtool verify /pa /v Snipdeck-*-Setup.exe` locally - after a download, and re-do the manual install smoke test. - -**Open questions.** - -- Whether the cost ($10/month indefinitely) is acceptable for a hobby / - side project. If not, the OV cert path is a single annual payment. -- Whether the Velopack-generated update packages (the `.nupkg` deltas - used by self-update) also need signing for self-update to keep working - smoothly under SmartScreen. Worth reading the Velopack signing docs - carefully before flipping the switch. - -Not urgent — alpha users can click through the prompt — but blocking -for any kind of broader distribution. - ---- - ## Tighten the iteration loop (build/CI feedback) **Problem.** During the phase build-out and post-release fixes, the From 1d4496214ee99ac8097e11df29af950364f84fd7 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 08:58:04 +0000 Subject: [PATCH 2/5] Remove Tighten-the-iteration-loop TODO Resolved: required status checks ('App build (windows)' + 'Core build + tests (ubuntu)') now enforced on the main ruleset, which closes the "merged red CI" problem the section was about. EnableWindowsTargeting was investigated and doesn't help (the WinUI XAML compiler is Windows-only and blocks the App build before analysers run); the winbuild ssh agent stays the mechanism. Draft-PR convention dropped with the section. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/TODO.md b/TODO.md index c8ac32a..a3092d5 100644 --- a/TODO.md +++ b/TODO.md @@ -297,47 +297,6 @@ Reasons: --- -## Tighten the iteration loop (build/CI feedback) - -**Problem.** During the phase build-out and post-release fixes, the -build-and-debug cycle relied heavily on PRs as the feedback loop: -local Linux can't build the `Snipdeck.App` project (the WinUI XAML -compiler is Windows-only), so analyser errors / build breaks only -surface in CI. Each round-trip is a PR, which generates churn and -sometimes ends with main broken (PR #13 was merged with red CI). - -**Idea.** Three independent improvements; each is small, all three -together would make the iteration loop tight. - -**Sketch.** - -- **`EnableWindowsTargeting=true` for local builds.** Adding this to - `Snipdeck.App.csproj` (or passing as `-p:EnableWindowsTargeting=true` - on Linux) lets the restore + compile step run on non-Windows hosts. - The WinUI XAML pass still requires Windows, but most analyser / - C# compiler rules fire under plain `dotnet build` and would catch - editorconfig violations (IDE0058, IDE0330, IDE0370, IDE0005 — all - hit in this session) before the push. -- **Branch protection: require status checks to pass.** Add a rule to - the existing branch ruleset on `main` that requires the - `App build (windows)` and `Core build + tests (ubuntu)` checks to be - green before the Merge button activates. Mechanical guardrail - against the merged-red scenario. -- **Draft PRs with force-push fixups during iteration.** Convention, - not config: open PRs as **Draft** while iterating, and amend + - force-push fixup commits into the original commit instead of stacking - "fix lint" follow-ups. The final merged history shows one clean - commit per change, which is what the project's commit log wants. - Auto-mode currently blocks `git push --force-with-lease` — would - need an explicit settings.json permission or a one-off approval - to enable. Force-push to `main` itself stays blocked. - -**Sequencing.** Do `EnableWindowsTargeting` first (cheapest, biggest -quality-of-life win for me); then branch protection (one-off setup, -done forever); then adopt the draft-PR convention. - ---- - ## Final UI polish pass A deliberate sweep of visual / interaction rough edges, done **at the end** From ae391126a665d810368139e1f35a3369a6efa898 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 14:06:10 +0000 Subject: [PATCH 3/5] TODO: add icon picker (glyph browser) for tag icons A visual, searchable glyph grid as a friendlier alternative to typing a Segoe Fluent Icons code point in the Tags management view. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/TODO.md b/TODO.md index a3092d5..6c371b2 100644 --- a/TODO.md +++ b/TODO.md @@ -328,6 +328,40 @@ feature work, then knock them out in one pass before a stable cut. --- +## Icon picker (glyph browser) for tag icons + +**Problem.** Tag icons are set by typing a raw glyph — either pasting a Segoe +Fluent Icons character or entering its hex code point (`GlyphInput.Resolve` +already accepts `E8EC`, `U+E8EC`, `0xE8EC`, ``). That works, but it's +unfriendly: the user has to know or look up a code point and can't see what's +available. There's no way to browse the icon set. + +**Idea.** A visual icon picker — a searchable grid of glyphs the user clicks to +choose — instead of (or alongside) typing a code. Driven from the Tags +management view, and a reusable fit for any future "choose a glyph" need. + +**Sketch.** +- A reusable `IconPicker` control / flyout: a virtualised `GridView` of + `FontIcon`s over a list of Segoe Fluent Icons glyphs, with a search box that + filters by name and/or code point. +- Needs a glyph **catalogue** — code point + friendly name — for the grid and + search. Either hand-curate a useful subset or embed the published Segoe Fluent + Icons mapping; the names are what make search worthwhile. +- Wire into the Tags view: add a "Choose…" button next to each row that opens + the picker, while keeping the free-text field as an escape hatch for pasting / + power users. +- Selection still flows through `GlyphInput.Resolve` and the stored-character + model, so persistence is unchanged. + +**Open questions** to settle when scheduled: +- Curated subset vs. full catalogue (the full set is ~1.5k glyphs — needs + virtualisation and good search to stay usable). +- Where do the glyph **names** come from, and is fuzzy search worth it? +- Do CLI icons (today: uploaded image, identicon fallback) also gain a + "pick a glyph instead" option, or stay image-only? Keep the first cut to tags. + +--- + ## Carried over from the phase stack These were trimmed out of Phase 4–6 to keep the PRs reviewable. None are From ae27fc4dea2c068a6df374af039addec81f60ad6 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 14:21:08 +0000 Subject: [PATCH 4/5] TODO: note deferred resizable / size-remembering snip editor The polish pass widened the editor to fit content but kept it a ContentDialog; true drag-resize + remembered size needs a resizable window and is parked here. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TODO.md b/TODO.md index 6c371b2..75670f1 100644 --- a/TODO.md +++ b/TODO.md @@ -322,6 +322,13 @@ re-polishing the same screens after every feature lands. Known items so far: the risk of accidental copies / conflicts with the overflow menu and favourite star hit-targets. Decide, then either remove the button or keep it. +- **Resizable, size-remembering snip editor.** The New/Edit snip editor was + widened to fit its content, but it's still a `ContentDialog` (fixed size). + Make it genuinely user-resizable and persist the chosen size (to `AppConfig`) + so it reopens at the same dimensions. `ContentDialog` can't do this natively — + the likely route is to host the editor in a resizable secondary `Window` + (native drag-resize) rather than a dialog overlay, which means rethinking how + the editor is shown and how its result returns through `IShellInteractions`. Add to this list as other cosmetic / interaction snags turn up during feature work, then knock them out in one pass before a stable cut. From 25480119c053295560748bd54516dff7825731e6 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sun, 31 May 2026 08:24:40 +0000 Subject: [PATCH 5/5] TODO: remove shipped items, keep the backlog current Shared parameter definitions, the Final UI polish pass, and the carried-over items (hotkey rebinding, storage path move/adopt/warn, re-enable PublishTrimmed) have all shipped to main, so drop them. Kept the still-pending resizable / size-remembering snip editor as its own section. Remaining backlog: Execute Snips, the importer, the icon picker, and the resizable editor. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 125 +++++--------------------------------------------------- 1 file changed, 10 insertions(+), 115 deletions(-) diff --git a/TODO.md b/TODO.md index 75670f1..8c62307 100644 --- a/TODO.md +++ b/TODO.md @@ -6,53 +6,6 @@ canonical list of *parked* v1 features is the "Out of scope for v1" section in --- -## Shared parameter definitions (global and CLI-scoped) - -**Problem.** Today every `Snip` carries its own `Parameter` definitions inline. -If twenty Snips all need an `env` Choice dropdown with options -`dev` / `staging` / `prod`, that definition is duplicated twenty times and the -user has to keep them in sync by hand. Same story for any other recurring -token (`region`, `org_id`, `tenant`, etc.). - -**Idea.** Let parameter definitions live above the Snip and be *referenced* by -name from individual Snips, with the option to still define a parameter -locally on a Snip when something one-off is needed. - -**Sketch.** -- Add a collection of shared `Parameter` definitions, probably at two scopes: - - **CLI-scoped** — most common case, e.g. an `env` defined once on the - `pl-app` CLI and used by every `pl-app` Snip. - - **Global** — for the rare cross-CLI definition (`yes_no`, common flags). - - Both scopes should be supported; CLI-scoped takes precedence over global - when names collide. -- A Snip can either: - - **Reference** a shared parameter by name — it picks up the type, options, - and default automatically. - - **Define** a parameter locally — overrides any shared definition with the - same name *for that Snip only*. -- The substitution engine doesn't change: tokens still resolve from a - `name → value` dictionary. Only the *definition* moves; resolution is the - same. - -**Open questions** to settle when this gets scheduled: -- Reference by **name** or by **ID**? Names match the `{token}` model and read - well; IDs survive renames. Probably name-based with a uniqueness constraint - per scope, plus a rename flow that propagates. -- Where does the UI to manage shared parameters live? A Settings page? A - flyout from each CLI in the pane header? Probably the latter for CLI-scoped - and a Settings entry for global. -- Schema migration: additive. New collections on `SnipStoreDocument` (global) - and `Cli` (CLI-scoped). Existing Snips with local `Parameter` entries keep - working unchanged. -- Should a Snip's `Parameters` list contain a discriminated union (local - definition vs. reference) or two parallel lists? A small object with - `Name` + optional inline definition feels cleanest — absent inline ⇒ resolve - from shared scope. - -This is the single biggest content-quality-of-life feature after v1 ships. - ---- - ## Execute Snips, not just construct them (with per-CLI shell + execution history) **Problem.** Today Snipdeck is a sophisticated clipboard — it builds the command @@ -297,44 +250,6 @@ Reasons: --- -## Final UI polish pass - -A deliberate sweep of visual / interaction rough edges, done **at the end** -once the feature surface has settled — batching the nitpicks avoids -re-polishing the same screens after every feature lands. Known items so far: - -- **Snip card Copy button is too wide.** It currently stretches further than - it should; size it to its content (or a sensible fixed width) so the card - action row reads cleanly. -- **"Delete CLI" button should be styled as a danger action.** It's a - destructive, hard-to-reverse operation — give it the red/danger accent - (e.g. a danger `Button` style / `Foreground` from the theme palette) - rather than the neutral default, so it visually distinguishes itself from - benign actions. -- **Inconsistent button corner radii.** Cancel buttons render with square - corners while Save / Copy buttons are rounded. Standardise on rounded - corners for *all* buttons (the dialog `CloseButton` is the likely culprit — - align it with the themed `CornerRadius` the primary buttons pick up). -- **Consider making the whole Snip card the Copy target.** Rather than a - dedicated Copy button on the card, let a click anywhere on the card trigger - the copy / parameter-fill flow. Weigh the trade-offs before committing: - discoverability and a cleaner card vs. losing an explicit affordance and - the risk of accidental copies / conflicts with the overflow menu and - favourite star hit-targets. Decide, then either remove the button or keep - it. -- **Resizable, size-remembering snip editor.** The New/Edit snip editor was - widened to fit its content, but it's still a `ContentDialog` (fixed size). - Make it genuinely user-resizable and persist the chosen size (to `AppConfig`) - so it reopens at the same dimensions. `ContentDialog` can't do this natively — - the likely route is to host the editor in a resizable secondary `Window` - (native drag-resize) rather than a dialog overlay, which means rethinking how - the editor is shown and how its result returns through `IShellInteractions`. - -Add to this list as other cosmetic / interaction snags turn up during -feature work, then knock them out in one pass before a stable cut. - ---- - ## Icon picker (glyph browser) for tag icons **Problem.** Tag icons are set by typing a raw glyph — either pasting a Segoe @@ -367,35 +282,15 @@ management view, and a reusable fit for any future "choose a glyph" need. - Do CLI icons (today: uploaded image, identicon fallback) also gain a "pick a glyph instead" option, or stay image-only? Keep the first cut to tags. + --- -## Carried over from the phase stack - -These were trimmed out of Phase 4–6 to keep the PRs reviewable. None are -load-bearing for the v1 demo, but they're the obvious next-pulls. - -- **Hotkey rebinding UI.** The setting is editable in `AppConfig` already; - what's missing is a key-capture control on the Settings page and the call - to `IHotkeyService.TryRegister` after the change. Tooling: a small custom - `Control` that listens for a single key chord then displays it formatted. -- **Storage path: move / adopt / warn-on-conflict.** Per `CLAUDE.md`, when - the user changes the storage path we need three flows: move the existing - store to the new path; adopt a store already at the new path; warn when - both exist. UI: a "Change…" button next to the read-only path display. -- **Re-enable `PublishTrimmed` once JSON serialisation is trim-safe.** - Disabled in `Snipdeck.App.csproj` to unblock the first release. To - turn it back on: - 1. Move `JsonSnipStore` / `JsonSettingsStore` onto - `JsonSerializerContext` source generation - (`[JsonSerializable(typeof(SnipStoreDocument))]` etc.) so the - untyped `Serialize/Deserialize` calls disappear. Removes IL2026. - 2. Audit Jdenticon-net, Microsoft.Windows.SDK.NET and WinRT.Runtime - trim warnings (IL2104); either suppress per-assembly with - `` entries / `[DynamicallyAccessedMembers]` - attributes, or accept them via targeted - `false` carve-outs. - 3. Flip `PublishTrimmed` back to `True` for Release. - - Payoff is a meaningfully smaller self-contained Velopack package - (probably ~80 MB instead of ~150–200 MB). Not urgent for alpha but - worth doing before a stable cut. +## Resizable, size-remembering snip editor + +The New/Edit snip editor was widened to fit its content during the UI polish +pass, but it's still a `ContentDialog` (fixed size). Make it genuinely +user-resizable and persist the chosen size (to `AppConfig`) so it reopens at +the same dimensions. `ContentDialog` can't do this natively — the likely route +is to host the editor in a resizable secondary `Window` (native drag-resize) +rather than a dialog overlay, which means rethinking how the editor is shown +and how its result returns through `IShellInteractions`.