Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions docs/superpowers/plans/2026-07-27-windows-pet-title-strip.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion electron/window-policy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export function resolvePetWindowPolicy(platform) {
return {
focusable: platform !== 'linux',
focusable: platform === 'darwin',
};
}
8 changes: 6 additions & 2 deletions electron/window-policy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
});
});
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
Loading