| name | release-personal-macos-app |
| description | Build, development-sign, verify, install, and accept the Voice Layer macOS application for personal use on the current Mac. Use when creating a local release candidate, installing or replacing Voice Layer.app in the user's Applications directory, auditing a personal release artifact, or recording release evidence. Do not use this workflow as proof of Developer ID distribution or notarization. |
Release Personal macOS App
Produce one traceable Voice Layer.app for the current Mac. Keep source, artifact, installed-app, and device evidence distinct.
Boundaries
- Read the repository
AGENTS.md and .agents/skills/test-voice-layer-app/SKILL.md before acting.
- Limit this workflow to a locally built app installed on the same Mac. If the app will be downloaded, transferred, or run on another Mac, stop and scope Developer ID signing, hardened runtime, and notarization separately.
- Preserve unrelated source changes. Record a dirty checkout and obtain explicit user acceptance before including it; never clean, reset, stage, or commit it implicitly.
- Never store a certificate name, Apple ID, password, private key, or notarization credential in the repository.
- Treat
llama-server as user-managed. Check it when relevant, but do not start, stop, or reconfigure it without explicit permission.
- Treat replacing an installed app as a recoverable but authority-bearing action. Inspect the exact target and obtain confirmation before moving or overwriting an existing bundle.
- Preserve
~/Library/Application Support/com.wcygan.voice-layer and ~/Library/WebKit/com.wcygan.voice-layer. Do not clear sessions, credentials, models, logs, or microphone permission state during release validation.
1. Establish provenance
Run from the repository root:
git status --short --branch
git rev-parse HEAD
git diff --check
security find-identity -v -p codesigning
uname -m
sw_vers
Inspect the source diff before accepting a dirty release. Check whether ~/Applications/Voice Layer.app or /Applications/Voice Layer.app already exists and whether Voice Layer is running.
Use an Apple Development identity for the personal build. Use ad-hoc identity - only when no development identity exists and the user explicitly accepts manual Privacy & Security approval. Do not treat either identity as public-distribution trust.
2. Validate and build
Run the supported checks before packaging:
just test
just check
Build with the exact identity returned by security find-identity:
APPLE_SIGNING_IDENTITY="<exact Apple Development identity>" just bundle
The release candidate is:
src-tauri/target/release/bundle/macos/Voice Layer.app
Never use a pre-existing bundle after source, configuration, resources, or the signing selection changes.
3. Verify the candidate
Run the bundled read-only verifier:
.agents/skills/release-personal-macos-app/scripts/verify-release.sh \
"src-tauri/target/release/bundle/macos/Voice Layer.app"
Require strict code-signature verification, the stable com.wcygan.voice-layer identifier, a nonempty microphone usage description, the signed com.apple.security.device.audio-input entitlement, a host-compatible executable, and the expected bundled notices. A usage description without the entitlement is not sufficient for a hardened-runtime build: macOS will deny capture without prompting. Treat spctl as informational for an Apple Development build because it is not notarized.
4. Install recoverably
Prefer the user-owned location:
~/Applications/Voice Layer.app
For a first installation, create ~/Applications, copy with ditto, verify the installed copy with verify-release.sh, and launch the .app with open. Do not launch Contents/MacOS/voice-layer directly, and do not use just open, which is a development helper that injects a workspace environment variable.
If the target already exists:
- Quit Voice Layer and confirm its process has exited.
- Verify and record the existing bundle before changing it.
- Obtain explicit user approval for the exact replacement.
- Move the existing bundle to a timestamped sibling backup rather than deleting it.
- Copy and verify the new bundle before launch.
- Retain the backup until the new app passes relaunch acceptance.
5. Accept the installed app
Read and follow $test-voice-layer-app, substituting the installed bundle path for the build-tree path. Do not rebuild between installation and acceptance unless source or bundle inputs changed.
At minimum, verify:
- the native window, navigation, composer, microphone label, and 1200x900 layout;
- one fresh deterministic Chat session when the existing local server is healthy;
- relaunch persistence from the installed path;
- no unexpected startup download or microphone request;
- a microphone permission prompt appears only when Chat recording or Live capture is first started, and denial produces an actionable Privacy & Security message;
- the correct application-data and log identity.
Exercise real microphone, Live duplex audio, and audible TTS only when that device testing is explicitly in scope. When microphone behavior is part of the release, require native meter movement from real input and one completed spoken turn; a permission prompt, status label, or animated UI is not capture evidence. Report dimensions not actually observed by a human as untested.
6. Report the release receipt
Report:
- commit, dirty files, and whether the user accepted them;
- application version, identifier, architecture, minimum macOS version, installed path, and executable hash;
- signing authority, Team ID, CDHash, strict verification result, and informational Gatekeeper result;
just test, just check, and just bundle results;
- candidate and installed-bundle verification;
- installed-app accessibility, screenshot, chat, and relaunch evidence;
- retained test-session data and any untested microphone, audible playback, failure, or rollback states.
Never call a development-signed personal build notarized, publicly distributable, or accepted on another Mac.