Skip to content

windows-v0.4.0: Mission Control on Windows - #7

Merged
boostedchaos merged 14 commits into
mainfrom
windows-0.4
Aug 9, 2026
Merged

windows-v0.4.0: Mission Control on Windows#7
boostedchaos merged 14 commits into
mainfrom
windows-0.4

Conversation

@boostedchaos

Copy link
Copy Markdown
Owner

Windows platform gaps + CI hardening for the Mission Control release. Phases: server-core CRLF fix, taskbar attention badge, real ade cli install, pipe-DACL spike closure, CI hardening, docs. Draft until the Codex review round and ship verifier pass. Do not merge manually.

boostedchaos and others added 14 commits August 9, 2026 15:22
…dows CI

readAdeWorkspaceSkill returned the bundled SKILL.md verbatim. On Windows the
file can be checked out (git autocrlf, the default on GitHub windows-latest) or
unzipped with CRLF, so the agentskills.io frontmatter starts with "---\r\n" and
the reader's one consumers install that copy. Normalize \r\n → \n on read, the
single chokepoint every consumer (createAdeWorkspaceSkill, scaffoldAgentSkills)
routes through, so the installed ~/.ade/skills copy is canonical LF on every
platform. Unblocks the ADE CI server-core suite on windows-latest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes the only user-facing platform gap for windows-v0.4.0. The macOS Dock
badge had no Windows equivalent; the taskbar carried no unread-attention signal.

- overlayBadgeKey(count) in attention/selectors: count → "1".."9"/"9+"/null,
  capped tighter than the Dock's 99+ for a legible 16px overlay icon.
- paintBadges(sink, count): one seam painting both platform badges, unit-tested
  with a mock (0 clears, forwards the raw count to the overlay sink).
- overlay-badge.ts loads pre-rendered 32x32 PNGs (red disc + white numeral) via
  nativeImage, resolving in dev/preview/packaged the way dock-icon.ts does.
- windows/main.ts: setOverlayBadge (win32 setOverlayIcon, null clears) and
  flashAttention (flashFrame when a new block arrives unfocused). Both no-op on
  macOS; macOS Dock/toast behavior unchanged.
- AttentionDeps widened with two optional callbacks; createNotification flashes
  on new attention rows (already deduped in handleAgentTransition).

Assets checked in; the count→PNG mapping and zero-clears path are covered in
attention/selectors.test.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…te mac-only tests

Windows install now adds ~/.ade[-ws]\bin to the user PATH instead of printing
"not supported yet". Reads/writes HKCU\Environment\Path via the Microsoft.Win32
registry API (never setx — no 1024-char truncation), preserving both the value
kind (REG_EXPAND_SZ vs REG_SZ) and unexpanded %VAR% entries, which a naive
[Environment]::SetEnvironmentVariable read-modify-write would corrupt.
Idempotent (case/trailing-slash tolerant), broadcasts WM_SETTINGCHANGE, and
prints a restart-your-shell note. PowerShell is invoked via -EncodedCommand:
a multi-line script piped to `-Command -` silently drops its stdout on Windows
PowerShell. There is no `uninstall` (POSIX has none either) — documented in help.

Verified with a live round-trip against the real registry: install appended the
dir, kind stayed ExpandString, %LOCALAPPDATA%/%USERPROFILE% survived, re-run was
idempotent, and an exact restore was byte-identical.

Also platform-gate the mac-only cli tests that spawn POSIX /bin/sh, assert
executable bits, or use ':'-delimited PATHs (tmux-compat quote/golden, claude-
teams, resolveInstallDir, the unix socket-path case) so the full cli suite is
0-fail on Windows without weakening mac coverage. The golden suite now skips
when its (uncommitted) probe-log fixture is absent rather than erroring.

browser --help: use ./shot.png instead of /tmp/shot.png in the screenshot example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
writeControlToken's mode 0o600 is a no-op on Windows, and ~/.ade can carry
env-added ACEs (e.g. an inherited CodexSandboxUsers:(RX)) that would let another
group read the token and drive the whole app. After writing, restrict the file
via icacls /inheritance:r /grant:r "<user>:F" so only the current user remains.
Best-effort: on failure warn and continue (pipe's Everyone=read-only DACL + 32B
token entropy still hold). Resolver falls back to USERPROFILE basename because
bun returns "unknown" from os.userInfo() on Windows.

Correct the stale tokensMatch/listen-site comments to the verified model: the
default named-pipe DACL grants Everyone READ-ONLY (no write, no command
injection); never pass readableAll/writableAll. Adds a win32-only ACL test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…port

Add WINDOWS.md at the repo root (referenced by docs/releasing-windows.md):
unsigned build + Get-FileHash verify, Mission Control on Windows (taskbar
overlay badge + flash), `ade cli install` (user-PATH edit, restart-shell,
manual removal), bun launcher requirement, claude-teams deferred (exits 2),
pipe/token security note (issue #8), and the issue #6 upgrade note.

Update docs/mission-control.md (Windows `cli install` supported; taskbar
overlay + flash in the badge section), link windows-v0.4.0 in CHANGELOG.md
with a Windows subsection, and add the WINDOWS-BUILD-REPORT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d-resource guard

Wires the two now-green Windows suites into the ground-truth job (fresh, no
ratchet) before the build; adds a post-boot smoke that drives the BUNDLED
`ade list-workspaces` over the control named pipe under a redirected profile
(self-contained separate step so a failure attributes cleanly); and asserts the
agent-runtime payload shipped — cli/index.mjs + skills loose under resources,
hook templates inside app.asar — as a complement to verify-win-package.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… + observable outcome)

Under bun on Windows os.userInfo().username returns "unknown" and %USERNAME%
is unset, so currentWindowsUser() fell through to the %USERPROFILE% basename.
On GH runners that bare SAM name can differ from the account icacls needs
(machine/domain-qualified), so `icacls /grant:r <user>:F` failed, the
best-effort catch swallowed it, and the token file kept its 3 inherited ACEs —
the "exactly one ACE" test then saw 3 on windows-latest.

Fix: resolve identity via `whoami` (prints the exact MACHINE\user principal
icacls always accepts; runs under bun via spawnSync) as the primary source,
keeping userInfo -> %USERNAME% -> %USERPROFILE% basename as fallback.

Make hardening OBSERVABLE: hardenTokenFileAcl is now exported and returns
{applied, reason} instead of only warning, so the best-effort catch can never
silently make the test vacuous. The test asserts hardening actually applied
(throwing the captured reason if not) and keeps the strict one-ACE assertion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ken file

Root cause of the windows-latest "expected 1 ACE, got 3" failure: /inheritance:r
removes only INHERITED ACEs. GitHub-hosted windows runners stamp EXPLICIT
(non-inherited) SYSTEM + BUILTIN\Administrators ACEs onto temp files, which
survive /inheritance:r — so `/inheritance:r /grant:r <user>:F` left 3 ACEs while
icacls still exited 0 (reproduced locally by seeding explicit SYSTEM/Admins
ACEs: 3 remain; adding /remove:g collapses to 1).

Fix: add `/remove:g *S-1-5-18 *S-1-5-32-544` (SYSTEM, Administrators by
locale-independent well-known SID) to the icacls call. Harmless no-op on a
normal box where those principals are only inherited; yields exactly one
explicit user ACE everywhere.

Test now carries the resolved user, harden result, and full icacls stdout into
the failure message so a surprising DACL is diagnosable from the CI log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
readAdeWorkspaceSkill only collapsed CRLF, so a BOM or lone CR would push
the '---' off byte 0 and break agentskills.io frontmatter parsing. Strip a
leading U+FEFF and normalize /\r\n?/g to \n. Extends the CRLF test with BOM +
lone-CR cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s die

/inheritance:r strips only INHERITED ACEs; an arbitrary explicit ACE stamped
onto a reused token file (any SID, not just SYSTEM/Administrators) would survive
a rotation and keep read access to the control token. Unlink the file before
writeFileSync so each launch starts from just the directory's inherited ACL,
which the existing hardening then locks to one user ACE. Kept the explicit
SYSTEM/Administrators /remove:g as a proven-needed no-op belt for GH runners.
Test: pre-stamp a Guests ACE, writeControlToken, assert it is gone (1 ACE).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
F1: the read script's stdout is decoded by spawnSync as utf8, but a console's
default OutputEncoding is the OEM code page (e.g. CP437), which mangled a
non-ASCII PATH entry (C:\工具) on read and wrote the corruption back. Force
[Console]::OutputEncoding=UTF8 before any output.

F2: the read and write were TWO PowerShell processes, so a concurrent PATH
editor between them got clobbered. Collapse read->check-membership->append->write
into ONE script (returns {action}), shrinking the race to an in-process window —
the residual race vs another editor mid-write is inherent to Windows PATH editing
(setx/the Settings dialog have the same window). %VAR% and REG kind preserved.
userPathHasDir/appendPathEntry kept as the unit-tested spec the PS mirrors.

Verified: cli suite 197 pass / 0 fail; pinned tsc exit 0; LIVE HKCU\Environment
\Path round-trip on a Windows box (append observed, kind preserved, registry
restored byte-identical).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ndows

The probe log is not committed, so describe.skipIf silently skipped the golden
suite on every platform — a regression would report green on macOS/Linux too.
Emit a console.warn naming the missing fixture and how to regenerate it when it
is absent on a non-Windows platform; the Windows skip stays silent (no /bin/sh
ran the probe there, an expected skip). Skip behavior itself is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…report

F1-F7 findings table with per-finding resolutions and commit SHAs; post-fix
suite tails (control-plane/cli/server-core all 0 fail) + pinned-tsc exit 0;
live HKCU PATH byte-identical round-trip evidence; base-head CI runs 31337152855
(windows-ci) + 31337152861 (ADE CI). Verifier + release slots left as TODO.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@boostedchaos
boostedchaos marked this pull request as ready for review August 9, 2026 22:24
@boostedchaos
boostedchaos merged commit b1384a5 into main Aug 9, 2026
3 checks passed
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.

1 participant