diff --git a/docs/superpowers/plans/2026-07-27-windows-pet-title-strip.md b/docs/superpowers/plans/2026-07-27-windows-pet-title-strip.md new file mode 100644 index 0000000..5f21931 --- /dev/null +++ b/docs/superpowers/plans/2026-07-27-windows-pet-title-strip.md @@ -0,0 +1,89 @@ +# Windows Pet Title Strip Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Remove the Windows pet's focus-related title strip without changing macOS or Linux behavior. + +**Architecture:** Keep the existing platform policy boundary and change only the `win32` focusability result. The pet window already consumes this policy, while the settings window does not. + +**Tech Stack:** Electron 35, JavaScript, Vitest, electron-builder + +## Global Constraints + +- macOS behavior must not change. +- Linux behavior must not change. +- The settings window must retain its normal title bar. +- The release version is `0.2.3`. + +--- + +### Task 1: Windows pet focus policy + +**Files:** +- Modify: `electron/window-policy.js` +- Test: `electron/window-policy.test.js` + +**Interfaces:** +- Consumes: `resolvePetWindowPolicy(platform: string)` +- Produces: `{ focusable: boolean }` with `false` for `win32` and `linux`, and `true` for `darwin` + +- [x] **Step 1: Run a failing Windows policy assertion** + +```bash +node --input-type=module -e "import { strict as assert } from 'node:assert'; import { resolvePetWindowPolicy } from './electron/window-policy.js'; assert.equal(resolvePetWindowPolicy('win32').focusable, false)" +``` + +Expected: FAIL because the existing result is `true`. + +- [x] **Step 2: Add the platform regression test** + +```js +it('makes the Windows pet non-focusable so changing focus cannot expose a title bar', () => { + expect(resolvePetWindowPolicy('win32')).toEqual({ focusable: false }); +}); +``` + +- [x] **Step 3: Implement the minimal platform policy** + +```js +export function resolvePetWindowPolicy(platform) { + return { + focusable: platform === 'darwin', + }; +} +``` + +- [ ] **Step 4: Run Electron tests** + +```bash +npm run test:electron +``` + +Expected: all Electron tests pass. + +### Task 2: Release metadata and verification + +**Files:** +- Modify: `package.json` +- Modify: `package-lock.json` + +**Interfaces:** +- Produces: package version `0.2.3` and release tag `v0.2.3` + +- [x] **Step 1: Bump package metadata** + +Set the root package version in both package files to `0.2.3`. + +- [ ] **Step 2: Run the complete desktop release gate** + +```bash +npm run check:desktop-release +``` + +Expected: Electron, unit, type, build, E2E, packaging-resource, workflow, and release checks all pass. + +- [ ] **Step 3: Commit and publish** + +Commit the tested files, open and merge a pull request, tag the resulting +`main` commit as `v0.2.3`, and confirm that all five platform artifacts are +attached to the GitHub release. diff --git a/docs/superpowers/specs/2026-07-27-windows-pet-title-strip-design.md b/docs/superpowers/specs/2026-07-27-windows-pet-title-strip-design.md new file mode 100644 index 0000000..f817d93 --- /dev/null +++ b/docs/superpowers/specs/2026-07-27-windows-pet-title-strip-design.md @@ -0,0 +1,34 @@ +# Windows Pet Title Strip Design + +## Goal + +Prevent the Windows desktop pet from exposing a native title strip after the +user clicks the pet and then switches to another application. + +## Root Cause + +The pet `BrowserWindow` is frameless, but the Windows platform policy still +allows it to receive focus. After focus moves away, Windows can expose the +window title associated with the focused transparent window. + +## Design + +Make only the Windows pet window non-focusable through +`resolvePetWindowPolicy`. Mouse input, dragging, reminders, and the native +context menu continue to use the existing renderer and IPC paths. The settings +window is a separate `BrowserWindow` and is unaffected. + +The final policy is: + +- `darwin`: `focusable: true` (unchanged) +- `linux`: `focusable: false` (unchanged) +- `win32`: `focusable: false` (changed) + +The page title and ElevenLabs attribution remain unchanged because the defect +is the appearance of native window chrome, not the attribution content. + +## Verification + +Add a policy regression test for Windows and retain explicit tests for macOS +and Linux. Run the Electron test suite and the complete desktop release gate. +Publish the fix as `v0.2.3` only after all automated checks pass. diff --git a/electron/window-policy.js b/electron/window-policy.js index b2177be..a142ab2 100644 --- a/electron/window-policy.js +++ b/electron/window-policy.js @@ -1,5 +1,5 @@ export function resolvePetWindowPolicy(platform) { return { - focusable: platform !== 'linux', + focusable: platform === 'darwin', }; } diff --git a/electron/window-policy.test.js b/electron/window-policy.test.js index c2d531d..18577e0 100644 --- a/electron/window-policy.test.js +++ b/electron/window-policy.test.js @@ -6,7 +6,11 @@ describe('pet window platform policy', () => { expect(resolvePetWindowPolicy('linux')).toEqual({ focusable: false }); }); - it.each(['darwin', 'win32'])('keeps the %s pet focusable', (platform) => { - expect(resolvePetWindowPolicy(platform)).toEqual({ focusable: true }); + it('makes the Windows pet non-focusable so changing focus cannot expose a title bar', () => { + expect(resolvePetWindowPolicy('win32')).toEqual({ focusable: false }); + }); + + it('keeps the macOS pet focusable', () => { + expect(resolvePetWindowPolicy('darwin')).toEqual({ focusable: true }); }); }); diff --git a/package-lock.json b/package-lock.json index 56b134c..ff040e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codex-pet-pause", - "version": "0.2.2", + "version": "0.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codex-pet-pause", - "version": "0.2.2", + "version": "0.2.3", "license": "MIT", "dependencies": { "@zip.js/zip.js": "^2.8.34", diff --git a/package.json b/package.json index 0aa33a8..e901d80 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "codex-pet-pause", "private": true, - "version": "0.2.2", + "version": "0.2.3", "description": "A playful, local-first break reminder PWA with interactive and Codex-compatible pets.", "license": "MIT", "repository": {