Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

80
docs/API_SPEC.md Normal file
View File

@@ -0,0 +1,80 @@
# Sprimo Frontend API Specification (v1)
Base URL: `http://127.0.0.1:<port>`
Auth: `Authorization: Bearer <token>` required on all endpoints except `/v1/health`.
## Endpoints
### `GET /v1/health`
- Auth: none
- Response `200`:
```json
{
"version": "0.1.0",
"build": "dev",
"uptime_seconds": 12,
"active_sprite_pack": "default",
"capabilities": {
"supports_click_through": true,
"supports_transparency": true,
"supports_tray": true,
"supports_global_hotkey": true,
"supports_skip_taskbar": true
}
}
```
### `GET /v1/state`
- Auth: required
- Response `200`: current frontend snapshot.
- Response `401`: missing/invalid token.
- Includes optional `last_error` diagnostic field for latest runtime command-application error.
### `POST /v1/command`
- Auth: required
- Body: one command envelope.
- Response `202`: accepted.
- Response `400`: malformed JSON.
- Response `401`: missing/invalid token.
- Runtime note for `SetSpritePack`:
- successful load switches sprite atlas immediately.
- failed load keeps current in-memory sprite/animation unchanged and reports the failure via `/v1/state.last_error`.
### `POST /v1/commands`
- Auth: required
- Body: ordered array of command envelopes.
- Response `202`: accepted.
- Response `400`: malformed JSON.
- Response `401`: missing/invalid token.
- Commands are applied in-order by the frontend runtime after transport acceptance.
## Command Envelope
```json
{
"id": "2d95f8a8-65cc-4309-8f76-4881949d7f4b",
"ts_ms": 1737000000000,
"command": {
"type": "set_state",
"payload": {
"state": "active",
"ttl_ms": null
}
}
}
```
## Error Response
```json
{
"code": "unauthorized",
"message": "missing or invalid bearer token"
}
```

43
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,43 @@
# Sprimo Frontend Architecture
## Workspace Layout
- `crates/sprimo-app`: process entrypoint and runtime wiring.
- `crates/sprimo-api`: axum-based localhost control server.
- `crates/sprimo-config`: config schema, path resolution, persistence.
- `crates/sprimo-platform`: platform abstraction for overlay operations.
- `crates/sprimo-protocol`: shared API/state/command protocol types.
- `crates/sprimo-sprite`: sprite pack manifest loading and fallback logic.
## Runtime Data Flow
1. `sprimo-app` loads or creates `config.toml`.
2. App builds initial `FrontendStateSnapshot`.
3. App starts `sprimo-api` on a Tokio runtime.
4. API authenticates commands and deduplicates IDs.
5. Commands are bridged from Tokio channel to Bevy main-thread systems.
6. Bevy systems apply commands to sprite state, window/platform operations, and config persistence.
7. Shared snapshot is exposed by API via `/v1/state` and `/v1/health`.
## Sprite Reload Semantics
- `SetSpritePack` uses a two-phase flow:
1. Validate and build candidate pack runtime (manifest + clips + atlas layout + texture handle).
2. Commit atomically only on success.
- On reload failure, current pack remains active and snapshot `last_error` is updated.
## Threading Model
- Main task: startup + shutdown signal.
- API task: axum server.
- Bridge task: forwards API commands into Bevy ingest channel.
- Bevy main thread: rendering, animation, command application, and window behavior.
- Optional hotkey thread (Windows): registers global hotkey and pushes recovery events.
- Snapshot is shared via `Arc<RwLock<_>>`.
## Design Constraints
- Bind API to localhost only.
- Token auth by default for mutating and state endpoints.
- Keep protocol crate renderer-agnostic for future backend/frontend reuse.
- Keep platform crate isolated for per-OS implementations.

45
docs/CONFIG_REFERENCE.md Normal file
View File

@@ -0,0 +1,45 @@
# Sprimo Config Reference
File location:
- Windows: `%APPDATA%/sprimo/config.toml`
- macOS: `~/Library/Application Support/sprimo/config.toml`
- Linux: `~/.config/sprimo/config.toml`
## Schema
```toml
[window]
x = 200.0
y = 200.0
monitor_id = ""
scale = 1.0
always_on_top = true
click_through = false
visible = true
[animation]
fps = 30
idle_timeout_ms = 3000
[sprite]
selected_pack = "default"
sprite_packs_dir = "sprite-packs"
[api]
port = 32145
auth_token = "generated-uuid-token"
[logging]
level = "info"
[controls]
hotkey_enabled = true
recovery_hotkey = "Ctrl+Alt+P"
```
## Notes
- `auth_token` is generated on first run if config does not exist.
- `window.x`, `window.y`, `window.scale`, and flag fields are persisted after matching commands.
- On Windows, `recovery_hotkey` provides click-through recovery even when the window is non-interactive.

View File

@@ -0,0 +1,497 @@
## Frontend Requirements Document — **sprimo-frontend**
**Document type:** Product + Engineering requirements (frontend scope only)
**Version:** v0.1
**Date:** 2026-02-12
**Scope:** Bevy-based overlay renderer + local control server + minimal UI.
**Out of scope:** Backend detection/rules engine (assumed external), cloud services.
---
# 1. Overview
The frontend is a **desktop overlay pet renderer** implemented in Rust (Bevy). It presents an animated character in a **transparent, borderless window** that can be **always-on-top** and optionally **click-through**. It receives control instructions from a local backend process via **localhost REST API**, applies them to its animation/state machine, and persists user preferences locally.
The frontend must be able to run standalone (idle animation) even if the backend is not running.
---
# 2. Goals
> Note: Windows and Linux should be first-hand support, macOS support is optional.
1. **Render a cute animated character overlay** with smooth sprite animation.
2. Provide a **stable command interface** (REST) for backend control.
3. Offer **essential user controls** (tray/menu + hotkeys optional) to avoid “locking” the pet in click-through mode.
4. Persist **window position, scale, sprite pack choice, and flags**.
5. Be **cross-platform** (Windows/macOS/Linux) with documented degradations, especially on Linux Wayland.
---
# 3. Non-Goals (Frontend v0.1)
* Tool activity detection (backend responsibility).
* Online sprite gallery, accounts, telemetry.
* Complex rigged animation (Live2D/3D). Sprite atlas only.
* Full settings UI panel (tray + config file is enough for v0.1).
---
# 4. User Stories
## Core
* As a user, I can see the pet on my desktop immediately after launch.
* As a user, I can drag the pet to a preferred location.
* As a user, I can toggle click-through so the pet doesnt block my mouse.
* As a user, I can toggle always-on-top so the pet stays visible.
* As a user, I can change the character (sprite pack).
## Backend control
* As a backend process, I can instruct the frontend to play specific animations and switch states via REST.
* As a backend process, I can update position/scale/visibility.
* As a backend process, I can query frontend health/version.
## Safety
* As a user, I can always recover control of the pet even if click-through is enabled (hotkey/tray item).
---
# 5. Functional Requirements
## 5.1 Window & Overlay Behavior
### FR-FW-1 Borderless + transparent
* Window must be **borderless** and **no title bar**.
* Background must be **transparent** so only the pet is visible.
**Acceptance**
* Screenshot shows only pet pixels; underlying desktop visible.
* No OS window chrome visible.
### FR-FW-2 Always-on-top
* Support always-on-top toggle.
* Default: ON (configurable).
**Acceptance**
* When ON, window stays above normal windows.
### FR-FW-3 Click-through (mouse pass-through)
* Support enabling/disabling click-through:
* ON: mouse events pass to windows underneath.
* OFF: pet receives mouse input (drag, context menu).
* Must provide a **failsafe** mechanism to disable click-through without clicking the pet.
**Acceptance**
* With click-through enabled, user can click apps behind pet.
* User can disable click-through via tray or hotkey reliably.
### FR-FW-4 Dragging & anchoring
* When click-through is OFF, user can drag the pet.
* Dragging updates persisted position in config.
* Optional: snapping to screen edges.
**Acceptance**
* Drag works smoothly, without major jitter.
* Relaunch restores position.
### FR-FW-5 Multi-monitor + DPI
* Window positioning must respect:
* multiple monitors
* per-monitor DPI scaling
* Position stored in a device-independent way where possible.
**Acceptance**
* Pet stays at expected corner after moving between monitors.
### FR-FW-6 Taskbar/Dock visibility
* Prefer not showing a taskbar entry for the overlay window (where supported).
* If not feasible cross-platform, document behavior.
**Acceptance**
* On Windows/macOS: overlay window ideally hidden from taskbar/dock.
* If not implemented, doesnt break core usage.
### Platform notes (requirements)
* **Windows:** click-through uses extended window styles (WS_EX_TRANSPARENT / layered), always-on-top via SetWindowPos.
* **macOS:** NSWindow level + ignoresMouseEvents.
* **Linux:** best effort:
* X11: possible with shape/input region.
* Wayland: click-through may be unavailable; document limitation.
---
## 5.2 Rendering & Animation
### FR-ANI-1 Sprite pack format
Frontend must load sprite packs from local disk with:
* `manifest.json` (required)
* atlas image(s) (PNG; required)
* optional metadata (author, license, preview)
**Manifest must define:**
* sprite sheet dimensions and frame rects (or grid)
* animations: name → ordered frame list + fps
* anchor point (pivot) for positioning
* optional hitbox (for drag region)
* optional offsets per frame (advanced)
**Acceptance**
* Default bundled pack loads with no config.
* Invalid packs fail gracefully with error message/log and fallback to default pack.
### FR-ANI-2 Animation playback
* Play loop animations (idle/dance).
* Support one-shot animations (celebrate/error) with:
* duration or “until frames complete”
* return-to-previous-state behavior
**Acceptance**
* Switching animations is immediate and consistent.
### FR-ANI-3 FPS control
* Configurable target FPS for animation updates (e.g., 30/60).
* Rendering should remain stable.
**Acceptance**
* Low CPU usage when idle animation running.
### FR-ANI-4 Layering
* Single character is mandatory for v0.1.
* Optional: accessory layers (future).
---
## 5.3 State Machine & Command Application
### FR-STM-1 Core states
Frontend supports at minimum:
* `Idle`
* `Active`
* `Success`
* `Error`
* `Dragging` (internal)
* `Hidden` (window hidden but process alive)
Each state maps to a default animation (configurable by sprite pack):
* Idle → idle animation
* Active → typing/dance
* Success → celebrate then return to Active/Idle
* Error → upset then return
### FR-STM-2 Transition rules
* Backend commands can:
* set state directly
* request specific animation with priority
* Frontend must implement:
* debouncing/cooldown (avoid flicker)
* priority arbitration (e.g., Error overrides Active)
**Acceptance**
* Repeated Active commands dont restart animation constantly.
* Error state overrides Active for N seconds.
### FR-STM-3 Local autonomy (no backend)
* If backend is absent:
* frontend stays in Idle with periodic idle animation
* user controls still function
* If backend connects later, commands apply immediately.
---
## 5.4 REST Control Server (Frontend-hosted)
### FR-API-1 Local binding only
* HTTP server must bind to `127.0.0.1` by default.
* Port configurable; recommended default fixed port (e.g., 32145).
### FR-API-2 Authentication token
* Frontend generates a random token on first run.
* Stored in local config directory.
* Backend must provide `Authorization: Bearer <token>` for all non-health endpoints.
* Health endpoint may be unauthenticated (optional).
### FR-API-3 Endpoints (v0.1)
**Required:**
* `GET /v1/health`
* returns: version, build, uptime, active_sprite_pack
* `POST /v1/command`
* accept a single command
* `POST /v1/commands`
* accept batch of commands
* `GET /v1/state` (debug)
* current state, current animation, flags, position/scale
**Command types required:**
* `SetState { state, ttl_ms? }`
* `PlayAnimation { name, priority, duration_ms?, interrupt? }`
* `SetSpritePack { pack_id_or_path }`
* `SetTransform { x?, y?, anchor?, scale?, opacity? }`
* `SetFlags { click_through?, always_on_top?, visible? }`
* `Toast { text, ttl_ms? }` (optional but recommended)
### FR-API-4 Idempotency & dedupe
* Commands include:
* `id` (ULID/UUID)
* `ts_ms`
* Frontend must ignore duplicate command IDs for a short window (e.g., last 5k IDs or last 10 minutes).
### FR-API-5 Error handling
* Invalid commands return 400 with error details.
* Auth failure returns 401.
* Server never crashes due to malformed input.
**Acceptance**
* Fuzzing basic JSON payload does not crash.
---
## 5.5 User Controls
### FR-CTL-1 Tray/menu bar controls (preferred)
Provide tray/menu bar items:
* Show/Hide
* Toggle Click-through
* Toggle Always-on-top
* Sprite Pack selection (at least “Default” + “Open sprite folder…”)
* Reload sprite packs
* Quit
If tray is too hard on Linux in v0.1, provide a fallback (hotkey + config).
### FR-CTL-2 Hotkeys (failsafe)
At minimum one global hotkey:
* Toggle click-through OR “enter interactive mode”
Example default:
* `Ctrl+Alt+P` (Windows/Linux), `Cmd+Option+P` (macOS)
**Acceptance**
* User can recover control even if pet is click-through and cannot be clicked.
### FR-CTL-3 Context menu (optional)
Right click pet (when interactive) to open a minimal menu.
---
## 5.6 Persistence & Configuration
### FR-CFG-1 Config storage
* Store config in OS-appropriate directory:
* Windows: `%APPDATA%/sprimo/config.toml`
* macOS: `~/Library/Application Support/sprimo/config.toml`
* Linux: `~/.config/sprimo/config.toml`
### FR-CFG-2 Config fields
* window:
* position (x,y) + monitor id (best-effort)
* scale
* always_on_top
* click_through
* visible
* animation:
* fps
* idle_timeout_ms
* sprite:
* selected_pack
* sprite_packs_dir
* api:
* port
* auth_token
* logging:
* level
### FR-CFG-3 Live reload (nice-to-have)
* v0.1: reload on tray action (“Reload config”).
* v0.2+: auto reload.
---
## 5.7 Logging & Diagnostics
### FR-LOG-1 Logging
* Log to file + console (configurable).
* Include:
* API requests summary
* command application
* sprite pack load errors
* platform overlay operations outcomes
### FR-LOG-2 Diagnostics endpoint (optional)
* `GET /v1/diag` returns recent errors and platform capability flags.
---
# 6. Non-Functional Requirements
## Performance
* Idle: < 2% CPU on typical dev laptop (target).
* Memory: should not grow unbounded; texture caching bounded.
## Reliability
* Should run for 8 hours without crash under command load.
* If REST server fails to bind port, show clear error and fallback behavior.
## Security
* Localhost only binding.
* Token auth by default.
* No file system access beyond sprite/config/log directories.
## Compatibility
* Windows 10/11
* macOS 12+ recommended
* Linux:
* X11 supported
* Wayland: documented limitations, still runs
---
# 7. Platform Capability Matrix (deliverable)
Frontend must expose in logs (and optionally `/v1/health`) capability flags:
* `supports_click_through`
* `supports_transparency`
* `supports_tray`
* `supports_global_hotkey`
* `supports_skip_taskbar`
Example:
* Windows: all true
* macOS: all true
* Linux X11: most true
* Linux Wayland: click-through likely false, skip-taskbar variable
---
# 8. Acceptance Test Plan (v0.1)
## Window
1. Launch: window appears borderless & transparent.
2. Drag: with click-through OFF, drag updates position; restart restores.
3. Click-through: toggle via hotkey; pet becomes non-interactive; toggle back works.
4. Always-on-top: verify staying above typical apps.
## Animation
1. Default pack: idle animation loops.
2. Command: `PlayAnimation("dance")` plays immediately.
3. One-shot: `Success` plays then returns to previous.
## API
1. Health returns correct version/build.
2. Auth required for commands; invalid token rejected.
3. Batch endpoint applies multiple commands in order.
4. Malformed JSON returns 400, app remains running.
## Persistence
1. Settings persist across restart.
2. Missing sprite pack falls back to default.
---
# 9. Implementation Constraints / Suggested Stack (not mandatory but recommended)
* Renderer/engine: **Bevy 2D**
* REST server: **axum + tokio** in background thread
* Shared protocol: `protocol` crate with `serde` structs
* Platform overlay: separate crate/module with per-OS implementations:
* Windows: `windows` crate (Win32 APIs)
* macOS: `objc2`/`cocoa` bindings
* Linux X11: `x11rb` (best effort)
* Config: `toml`
* IDs: `ulid` or `uuid`
---
# 10. Open Questions (Frontend)
1. Do we require Linux Wayland support beyond “runs but limited overlay features”?
2. Do we want multiple pets (multiple windows) in v0.1 or later?
3. Do we embed a default sprite pack (license?), or ship an empty skeleton?
---
If you want, I can turn this into:
* a `docs/FRONTEND_REQUIREMENTS.md`
* plus a concrete **REST API spec** (OpenAPI-like) and a **sprite-pack manifest schema** with examples (JSON).

View File

@@ -0,0 +1,26 @@
# Sprimo Frontend Implementation Status
Date: 2026-02-12
## MVP Vertical Slice
| Area | Status | Notes |
|------|--------|-------|
| Workspace split | Implemented | `sprimo-app`, `sprimo-api`, `sprimo-config`, `sprimo-platform`, `sprimo-protocol`, `sprimo-sprite` |
| Local REST server | Implemented | `/v1/health`, `/v1/state`, `/v1/command`, `/v1/commands`; localhost bind and bearer auth |
| Command/state pipeline | Implemented | Command queue, state snapshot updates, transient state TTL rollback |
| Config persistence | Implemented | `config.toml` bootstrap/load/save with generated token |
| Sprite pack contract | Implemented | `manifest.json` loader and selected->default fallback |
| Platform abstraction | Implemented | Windows adapter now applies click-through/top-most/visibility/position using Win32 APIs |
| Overlay rendering | Implemented (MVP) | Bevy runtime with transparent undecorated window, sprite playback, command bridge |
| Global failsafe | Implemented (Windows) | Global recovery hotkey `Ctrl+Alt+P` disables click-through and forces visibility |
| Embedded default pack | Implemented | Bundled under `assets/sprite-packs/default/` using `sprite.png` (8x7, 512x512 frames) |
| Build/package automation | Implemented (Windows) | `justfile` and `scripts/package_windows.py` generate portable ZIP + SHA256 |
| QA/documentation workflow | Implemented | `docs/QA_WORKFLOW.md`, issue/evidence templates, and `scripts/qa_validate.py` with `just qa-validate` |
## Next Major Gaps
1. Tray/menu controls are still not implemented.
2. Linux/macOS overlay behavior remains best-effort with no-op platform adapter.
3. `/v1/state` diagnostics are minimal; error history is not persisted beyond latest runtime error.
4. Issue 1 runtime after-fix screenshot evidence is still pending before closure.

62
docs/ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,62 @@
# Issue Template (`issues/issueN.md`)
## Title
## Severity
## Environment
- OS:
- App version/build:
- Renderer/backend details:
## Summary
## Reproduction Steps
1.
2.
## Expected Result
## Actual Result
## Root Cause Analysis
## Fix Plan
## Implementation Notes
## Verification
### Commands Run
- [ ] `cargo check --workspace`
- [ ] `cargo test --workspace`
- [ ] `just qa-validate`
### Visual Checklist
- [ ] Before screenshot(s): `issues/screenshots/issueN-before-YYYYMMDD-HHMMSS.png`
- [ ] After screenshot(s): `issues/screenshots/issueN-after-YYYYMMDD-HHMMSS.png`
### Result
- Status:
- Notes:
## Status History
- `YYYY-MM-DD HH:MM` - `<actor>` - `Reported` - note
## Closure
- Current Status: `Reported`
- Close Date:
- Owner:
- Linked PR/commit:
## Original Report (if migrated)
Paste the initial report verbatim when migrating legacy issues.

41
docs/MVP_ACCEPTANCE.md Normal file
View File

@@ -0,0 +1,41 @@
# MVP Acceptance Checklist
## API
- [x] `GET /v1/health` returns version/build/uptime and active sprite pack.
- [x] `GET /v1/state` requires bearer token.
- [x] `POST /v1/command` requires bearer token and returns `202` for valid command.
- [x] `POST /v1/commands` accepts batch in-order.
- [x] malformed JSON returns `400`, server remains alive.
## Command Pipeline
- [x] duplicate command IDs are ignored within dedupe window.
- [x] `SetState` updates state and default animation mapping.
- [x] transient state with `ttl_ms` returns to durable state.
- [x] `SetTransform` persists x/y/scale.
- [x] `SetFlags` persists click-through/always-on-top/visible.
## Config
- [x] first run bootstraps `config.toml`.
- [x] `auth_token` generated and reused across restarts.
## Sprite
- [x] selected sprite pack loads when present.
- [x] missing selected pack falls back to `default`.
- [x] runtime `SetSpritePack` successfully switches pack without restart.
- [x] failed runtime `SetSpritePack` keeps current visuals and reports error in state snapshot.
## Platform
- [x] capability flags are exposed in `/v1/health`.
- [x] non-supported platform operations do not crash the process.
## Evidence
- `cargo test --workspace` passes.
- API auth coverage exists in `crates/sprimo-api/src/lib.rs` tests.
- Config bootstrap and roundtrip coverage exists in `crates/sprimo-config/src/lib.rs` tests.
- Sprite fallback coverage exists in `crates/sprimo-sprite/src/lib.rs` tests.

View File

@@ -0,0 +1,17 @@
# Platform Capability Matrix (MVP)
Date: 2026-02-12
| Capability | Windows | Linux X11 | Linux Wayland | macOS |
|------------|---------|-----------|---------------|-------|
| `supports_click_through` | true (implemented) | false (current) | false | false (current) |
| `supports_transparency` | true | true | true | true |
| `supports_tray` | false (current) | false (current) | false (current) | false (current) |
| `supports_global_hotkey` | true (implemented) | false (current) | false (current) | false (current) |
| `supports_skip_taskbar` | true (target) | false (current) | false (current) | false (current) |
## Notes
- Current code applies real Win32 operations for click-through, visibility, top-most, and positioning.
- Non-Windows targets currently use a no-op adapter with conservative flags.
- Wayland limitations remain an expected degradation in v0.1.

View File

@@ -0,0 +1,38 @@
# QA Evidence Template
Use this block inside `issues/issueN.md` under `## Verification`.
```md
### Commands Run
- [ ] `cargo check --workspace`
- [ ] `cargo test --workspace`
- [ ] `just qa-validate`
### Command Output Summary
- `cargo check --workspace`: pass/fail, key notes
- `cargo test --workspace`: pass/fail, key notes
- `just qa-validate`: pass/fail, key notes
### Screenshots
- Before:
- `issues/screenshots/issueN-before-YYYYMMDD-HHMMSS.png`
- After:
- `issues/screenshots/issueN-after-YYYYMMDD-HHMMSS.png`
### Visual Assertions
- [ ] Overlay is transparent where expected
- [ ] Window size/placement behavior matches expected result
- [ ] Sprite/background alpha behavior matches expected result
### Reviewer Record
- Date:
- Verified by:
- Final result:
- Notes:
```

85
docs/QA_WORKFLOW.md Normal file
View File

@@ -0,0 +1,85 @@
# Sprimo QA and Documentation Workflow
## Purpose
This workflow defines how bug reports, runtime evidence, and documentation updates are
maintained so every issue is auditable from first report to closure.
## Issue Lifecycle
All issues use a single file: `issues/issueN.md`.
Allowed lifecycle states:
1. `Reported`
2. `Triaged`
3. `In Progress`
4. `Fix Implemented`
5. `Verification Passed`
6. `Closed`
Each state transition must include:
- local timestamp (`YYYY-MM-DD HH:MM`)
- actor
- short note
- evidence links when available
## Evidence Requirements
Screenshots are stored under `issues/screenshots/`.
Naming convention:
- before: `issueN-before-YYYYMMDD-HHMMSS.png`
- after: `issueN-after-YYYYMMDD-HHMMSS.png`
- optional checkpoint suffix: `-step1`, `-step2`
For UI/runtime behavior bugs:
- at least one before screenshot is required at report/triage time
- at least one after screenshot is required before `Verification Passed` or `Closed`
Legacy reports may keep `issues/screenshots/issueN.png` as before evidence.
## Verification Gate
Before marking an issue `Closed`, all conditions must be met:
1. Relevant checks/tests are recorded:
- `cargo check --workspace`
- `cargo test --workspace` (or documented rationale for targeted tests)
2. Visual checklist is completed with before/after screenshot references.
3. Docs are synchronized:
- `issues/issueN.md` lifecycle and verification sections updated
- impacted files under `docs/` updated when behavior/spec/status changed
## Documentation Sync Rules
Update these files when applicable:
- `docs/IMPLEMENTATION_STATUS.md` for milestone-level implementation status
- `docs/RELEASE_TESTING.md` when release/manual QA steps change
- `docs/API_SPEC.md`, `docs/CONFIG_REFERENCE.md`, or other contracts if behavior changed
## Command Checklist
Minimum command set for fix validation:
```powershell
cargo check --workspace
cargo test --workspace
just qa-validate
```
For runtime behavior issues, include screenshot capture paths in the issue file.
## Definition of Done
An issue is done only when:
- lifecycle state is `Closed`
- verification gate passed
- evidence links resolve to files in repository
- `just qa-validate` passes

72
docs/RELEASE_TESTING.md Normal file
View File

@@ -0,0 +1,72 @@
# Release Packaging and Behavior Testing (Windows)
## Artifact Layout
Current release package type: portable ZIP.
Expected contents:
- `sprimo-app.exe`
- `assets/sprite-packs/default/manifest.json`
- `assets/sprite-packs/default/sprite.png`
- `README.txt`
Generated outputs:
- `dist/sprimo-windows-x64-v<version>.zip`
- `dist/sprimo-windows-x64-v<version>.zip.sha256`
## Commands
Use `just` for command entry:
```powershell
just check
just test
just build-release
just package-win
just smoke-win
```
`just package-win` calls `scripts/package_windows.py package`.
`just smoke-win` calls `scripts/package_windows.py smoke`.
## Behavior Test Checklist (Packaged App)
Run tests from an unpacked ZIP folder, not from the workspace run.
1. Launch `sprimo-app.exe`; verify default sprite renders.
2. Verify no terminal window appears when launching release build by double-click.
3. Verify global hotkey recovery (`Ctrl+Alt+P`) forces interactive mode.
4. Verify click-through and always-on-top toggles via API commands.
5. Verify `/v1/health` and `/v1/state` behavior with auth.
6. Verify `SetSpritePack`:
- valid pack switches runtime visuals
- invalid pack keeps current visuals and sets `last_error`
7. Restart app and verify persisted config behavior.
8. Confirm overlay background is transparent (desktop visible behind non-sprite pixels).
9. Confirm no magenta matte remains around sprite in default pack.
## Test Log Template
- Date:
- Artifact:
- Commit:
- Tester:
- Result:
- Notes:
## Issue Evidence Gate
Before release sign-off for a bug fix:
1. Link the issue file (`issues/issueN.md`) in the test log.
2. Ensure before/after screenshot evidence is referenced from the issue:
- before: `issues/screenshots/issueN-before-YYYYMMDD-HHMMSS.png`
- after: `issues/screenshots/issueN-after-YYYYMMDD-HHMMSS.png`
3. Record verification commands and outcomes in the issue:
- `cargo check --workspace`
- `cargo test --workspace`
- `just qa-validate`
Legacy issues may reference `issues/screenshots/issueN.png` as before evidence.

View File

@@ -0,0 +1,66 @@
# Sprite Pack Manifest Schema (MVP)
Path: `<pack_dir>/manifest.json`
## Required Fields
- `id` (string): unique sprite pack ID.
- `version` (string): schema/pack version label.
- `image` (string): atlas image filename, e.g. `atlas.png`.
- `frame_width` (u32): frame width in pixels.
- `frame_height` (u32): frame height in pixels.
- `animations` (array): list of animation definitions.
- `anchor` (object): sprite anchor/pivot.
## Animation Definition
- `name` (string)
- `fps` (u16)
- `frames` (array of u32 frame indices)
- `one_shot` (optional bool)
## Anchor Object
- `x` (f32)
- `y` (f32)
## Example
```json
{
"id": "default",
"version": "1",
"image": "atlas.png",
"frame_width": 64,
"frame_height": 64,
"animations": [
{ "name": "idle", "fps": 8, "frames": [0, 1, 2, 3] },
{ "name": "success", "fps": 12, "frames": [20, 21, 22], "one_shot": true }
],
"anchor": { "x": 0.5, "y": 1.0 }
}
```
## Runtime Fallback Behavior
- The selected pack is attempted first.
- If selected pack is missing/invalid, frontend falls back to `default`.
- If `default` is missing/invalid, loading fails with error.
## Alpha Handling
- If the source image already has an alpha channel, runtime uses it directly.
- If the source image is RGB-only, runtime can apply chroma-key conversion:
- default key color: `#FF00FF`
- matching pixels become transparent.
- Manifest optional fields:
- `chroma_key_color` (string `#RRGGBB`)
- `chroma_key_enabled` (bool)
## Grid Derivation Rule
- Runtime derives atlas grid from image dimensions:
- `columns = image_width / frame_width`
- `rows = image_height / frame_height`
- Image dimensions must be divisible by frame dimensions.
- Every animation frame index must be `< columns * rows`.