Native Windows 11 x64 client for TaskNotes. WinUI 3 renders the application, while the committed C# UniFFI binding calls the same pure Rust domain and sync engine as the macOS client.
Open an elevated PowerShell terminal. If winget is missing or broken, repair
App Installer first from Microsoft Store, then apply the checked-in WinUI
configuration. This follows Microsoft's
WinUI development setup:
winget configure --file .\packages\tasknotes-windows\dev\winui-configuration.winget --accept-configuration-agreements
winget install jdx.miseThe configuration enables Developer Mode and installs Visual Studio 2026 Community with .NET desktop, Universal Windows, Windows App SDK, Windows SDK 26100, and x64 MSVC components. Reopen an elevated terminal, install the CLI template, and provision this machine's development certificate:
dotnet new install Microsoft.WindowsAppSDK.WinUI.CSharp.Templates
.\packages\tasknotes-windows\scripts\provision-signing.ps1The certificate's private key stays in the current user's certificate store.
Only its public certificate is trusted in the local machine's Trusted People
store. Its thumbprint is written only to ignored
packages/tasknotes-windows/Directory.Build.local.props.
The pinned versions come from the official .NET 10 downloads, Windows App SDK releases, and UniFFI C# generator documentation.
Run these commands from the repository root:
mise install
bun install --frozen-lockfile
bunx turbo run generate
bun run windows:preflightbun run windows:build # locked release build, including WinUI
bun run windows:test:unit
bun run windows:test:integration
bun run windows:test:winui
bun run windows:coverage # Cobertura baselines plus changed-line ratchet
bun run windows:analysis # compiler, analyzers, architecture, duplication
bun run windows:format # CSharpier and XAML Styler
bun run windows:mutation # explicit Stryker.NET and cargo-mutants deep gate
bun run windows:package # signed MSIX under AppPackages/
bun run windows:run # register debug identity and launch
bun run windows:parity-check
bun run windows:e2e
bun run windows:e2e --scenario quick-add-create
bun run windows:e2e --keep-artifacts
bun run windows:accessibility # packaged keyboard and UIA contract scenario
bun run windows:visual-profile # requires TASKNOTES_VISUAL_PROFILE and matching OS state
bun run windows:visual-matrix # aggregates six fresh real-session profiles
bun run windows:verify # complete local release and packaged-E2E gatewindows:run is also the correct way to refresh an existing Developer Mode
registration. A plain Debug build updates compiler output but does not deploy
the new XAML resources into the registered package.
To install the newest signed release package after windows:package, run the
generated installer from the newest _Test directory. It installs the public
development certificate and required Windows App Runtime dependency before the
MSIX:
$installer = Get-ChildItem .\packages\tasknotes-windows\AppPackages -Recurse -Filter Install.ps1 |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
& $installer.FullName -Force -SkipLoggingTelemetryPortable Linux CI uses build, typecheck, lint, coverage:portable, and
test:ci. The checked-in projects.json classifies every project, and the
quality checker proves the portable solution includes every portable project
and excludes every WinUI, MSIX, and UI Automation project. The CI test
manifest lists both Windows-only suites with explicit reasons; they are not
silently omitted.
The boundary is strict:
WinUI -> Presentation -> TaskNotesStore -> EngineRunner -> generated C# UniFFI -> Rust core
Portable view models own navigation, command state, validation, projections,
deep-link interpretation, dialogs, editor state, and auxiliary-window state.
They consume immutable ITaskNotesStore snapshots and portable contracts;
only the App project references WinUI and Windows Runtime APIs.
The shell composes focused compiled views for task lists, Quick Add, the task editor, Board, and Settings. Native event adapters stay beside their WinUI views, while command state and validation remain in portable view models. This keeps generated XAML and UI-thread concerns out of the portable test surface.
TaskNotesStore exposes the complete task snapshot, fixed and dynamic query
projections, vocabulary, saved-view metadata, completion undo, live timing and
Pomodoro state, pending IDs, sync state, errors, and parked changes. A
single-reader channel executes every FFI call away from the UI thread. Its
bounded coalescing pump owns background drains and is awaited during disposal.
Host
callbacks supply atomic app-local files, bearer-authenticated HttpClient,
system time and timezone, cryptographic randomness, cancellation, and
idempotent retry timers. C# does not implement recurrence, mutation,
wire-protocol, filtering, sorting, or synchronization policy.
The server URL is non-secret and lives in local settings. The bearer token lives only in Windows Credential Locker.
The composition root uses Microsoft.Extensions.Hosting and writes allow-listed JSONL diagnostics under app-local storage. Logs contain operation metadata, correlation IDs, durations, status codes, and exception types; tokens, headers, request bodies, Markdown, and task content are never persisted. Files rotate at 25 MB and expire after seven days.
Coverage is a checked-in ratchet, not a one-time report. Full Windows line coverage is currently 90.3% for Host, 97.5% for Presentation, and 92.7% for handwritten adapters. Portable CI separately holds Host at 90.2% and Presentation at 96.3%. The shared Bun E2E harness and Rust core/client/FFI boundary have their own changed-line and non-regression checks.
The NavigationView contains Inbox, Today, Upcoming, Browse, completed tasks,
Board, saved views, projects, contexts, tags, Pomodoro, Time Report, and
Settings. The reusable task workspace supports search, filters, sorting,
grouping, multi-selection, bulk mutation, task editing, recurrence completion,
and LIFO completion undo. The shell also implements tasknotes:// activation,
singleton auxiliary windows, keyboard commands, a configurable global Quick
Add hotkey, persistence, and stable automation identifiers.
Apple-only widgets, Live Activities, Siri/App Intents, haptics, and Apple lifecycle behavior are explicit parity exclusions. Windows Widgets, notifications, Store publication, ARM64, and production signing remain deferred. Windows 11 x64 is the supported target.
@tasknotes/e2e creates a fresh seeded Markdown vault, starts the real
tasknotes-server on an ephemeral port, and fronts it with a deterministic
offline/fail-next proxy. windows:e2e builds and registers the isolated
red.sjer.TaskNotes.E2E package once, resets package data and Credential Locker
state between serial scenarios, and drives the app with direct Windows UI
Automation. Failed scenarios retain the redacted server/proxy logs, JUnit XML,
UIA tree, screenshot, process inventory, and vault under artifacts/e2e/.
The Windows UI lane remains local until Buildkite has unlocked interactive
Windows 11 x64 workers. The exact inactive lane contract is checked in at
ci/windows-buildkite.pipeline.yml; provisioning is tracked in Linear as
SJ-134. Until that issue is complete, a PR needs attached local
windows:verify evidence and must not claim packaged Windows tests are
CI-enforced.