Files
gui-video-clipper/docs/superpowers/specs/2026-09-22-build-cleanup-release-packaging-design.md
cottongin d46973a719 v0.1.1: fix .app bundle PATH for pyenv/nvm, detect yt-dlp pot-provider plugin
- fix_path_env() now adds ~/.pyenv/shims (with PYENV_ROOT) before
  Homebrew paths so pyenv-managed yt-dlp (with pip-installed plugins)
  takes priority over Homebrew's bare yt-dlp binary
- Also handles ~/.nvm, ~/.deno/bin, ~/.cargo/bin for broader coverage
- check_pot_plugin uses lightweight 'yt-dlp -v' instead of network
  simulation for reliable plugin detection
- Bump version to 0.1.1

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 14:09:23 -04:00

113 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Build Cleanup & Release Packaging
**Date:** 2026-09-22
**Status:** Approved
## Overview
Resolve all build warnings and errors across the frontend (svelte-check, Vite) and backend (cargo), fix the failing test, and implement a release build script that produces a distributable `GUI Video Clipper.app` bundle.
## Scope
Two workstreams:
1. **Warning/Error Cleanup** — zero warnings from `npm run check`, `cargo build`, and `npm test`
2. **Release Build Packaging** — `scripts/build-release.sh` that produces a signed `.app` in `dist/release/`
## 1. TypeScript Errors (4)
All in `vite.config.ts`:
| Error | Root Cause | Fix |
|-------|-----------|-----|
| Cannot find `node:path` | Missing `@types/node` | `npm install -D @types/node`, add `"types": ["node"]` to `tsconfig.json` |
| Cannot find `node:process` | Same | Same |
| Cannot find `node:url` | Same | Same |
| `test` not in `UserConfigExport` | `defineConfig` from `vite` doesn't know vitest's `test` field | Import `defineConfig` from `vitest/config` instead |
## 2. Svelte A11y Warnings (19)
### 2a. Labels not associated with controls (9 in CaptionSettingsPanel.svelte)
Labels are siblings of their controls rather than wrapping them. Fix by either:
- Wrapping the `<input>`/`<select>` inside the `<label>` element, or
- Adding `id` to the control and `for` to the label
Prefer the wrapping approach where layout allows.
### 2b. Dialog divs missing tabindex (4 files)
Add `tabindex="-1"` to `<div role="dialog">` in `PreferencesPanel`, `ExportDialog`, `AboutDialog`, and `<div role="listbox">` in `ClipList`. Makes them programmatically focusable without entering the tab order.
### 2c. Click handlers without key handlers (4 files)
Dialog overlay `onclick={onClose}` divs need corresponding `onkeydown` handlers. Add Escape key handling on the overlay. For `ClipList`'s listbox container, add an `onkeydown` handler mirroring the container click logic.
### 2d. `<video>` without `<track>` (1 in VideoPlayer.svelte)
Add an empty `<track kind="captions" default />` to the `<video>` element. Our custom caption overlay handles actual rendering.
### 2e. Resize handle (1 in App.svelte)
The resize handle `<div>` with `role="separator"` and `onmousedown` needs:
- `tabindex="0"` for keyboard focusability
- `onkeydown` handler for arrow key resizing
- `aria-valuenow`, `aria-valuemin`, `aria-valuemax` attributes
## 3. Rust Dead Code Warnings (6)
Add `#[allow(dead_code)]` with explanatory comments:
| Warning | Location | Annotation Rationale |
|---------|----------|---------------------|
| `ExportEvent::Error` unused | `commands/export.rs:23` | Reserved for future error-channel reporting |
| `DownloadEvent::Error` unused | `commands/video.rs:23` | Reserved for future error-channel reporting |
| `sanitize_vtt_for_ffmpeg` unused | `clip_exporter.rs:10` | Scaffolded for caption burn-in pipeline |
| `opacity_to_ass_back_colour` unused | `clip_exporter.rs:204` | Scaffolded for caption burn-in pipeline |
| `caption_style_to_force_style` unused | `clip_exporter.rs:210` | Scaffolded for caption burn-in pipeline |
| `SubtitleFormat.ext`/`.url` unread | `video_resolver.rs:8-9` | Fields required for serde deserialization |
## 4. Test Fix
**File:** `tests/lib/stores/clips.test.ts`
**Test:** "updates selected clip start when I is pressed"
The test calls `markInPoint(5)` on a clip spanning 10–20. With `EDIT_TOLERANCE` of 0.5s, time 5 is outside the clip boundary (needs ≥ 9.5). The test was written before the tolerance check existed.
**Fix:** Change `markInPoint(5)` to `markInPoint(12)` (inside the clip, within tolerance). Update the assertion to `expect(getClips()[0].startTime).toBe(12)`. This verifies the edit actually changes the start time (unlike `markInPoint(10)` which would pass trivially since start is already 10).
After fix: 31/31 tests pass.
## 5. Release Build Script
### 5a. `scripts/build-release.sh`
A shell script that:
1. Reads `VERSION` from the project root
2. Runs `npm install`
3. Runs `npx tauri build` (builds frontend + Rust + bundles .app and .dmg)
4. Ad-hoc code signs the `.app`: `codesign --force --deep -s - <path>`
5. Copies `.app` (and `.dmg` if built) to `dist/release/`
6. Prints summary: version, output path, bundle size
### 5b. Configuration changes
- `tauri.conf.json`: Change `"targets": "all"` to `"targets": ["app", "dmg"]`
- `.gitignore`: Add `dist/`
- `package.json`: Add `"release": "bash scripts/build-release.sh"`
### 5c. README update
Add a "Release Build" section documenting `npm run release` and its outputs.
## Verification
After all changes:
- `npm run check` exits 0 with 0 errors, 0 warnings
- `cargo build 2>&1 | grep warning` returns nothing
- `npm test` shows 31/31 pass
- `npm run release` produces `dist/release/GUI Video Clipper.app`
- The `.app` launches without the Gatekeeper right-click workaround