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
51 changes: 33 additions & 18 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,47 +186,62 @@ Build caching: ccache (macOS/Linux) and sccache (Windows) with GitHub Actions ca

## Release Process

Versions are defined in `versions.cmake`. The CI workflow (`.github/workflows/ci.yml`) triggers releases on `v*` tags.
Versions are defined in `versions.cmake`. The CI workflow (`.github/workflows/ci.yml`) triggers releases on `v*` tags. Tags can be created on either `develop` or `main`:
- **`develop`** — alpha/dev pre-releases (tagged with `-alpha`, `-dev`, etc.)
- **`main`** — stable releases only (tagged without suffix)

**Important**: The `main` branch is protected — it requires pull requests and passing status checks. You cannot push directly to `main`.

### Steps
1. Ensure you are on `develop`:
### Alpha/Pre-release (from `develop`)
1. Bump version in `versions.cmake` on `develop`:
```bash
git checkout develop
sed -i '' 's/PROJECT_CORE_VERSION ".*"/PROJECT_CORE_VERSION "0.4.9"/' versions.cmake
git add versions.cmake
git commit -m "bump version to 0.4.9"
git push origin develop
```
2. Update version in `versions.cmake` (edit the `PROJECT_CORE_VERSION` line):
2. Tag the `develop` HEAD and push — this triggers the release jobs:
```bash
# Example: bump to 0.4.9
sed -i '' 's/PROJECT_CORE_VERSION ".*"/PROJECT_CORE_VERSION "0.4.9"/' versions.cmake
git tag v0.4.9-alpha
git push origin v0.4.9-alpha
```
3. Commit and push to `develop`:

### Stable Release (from `main`)
1. Bump version in `versions.cmake` on `develop`:
```bash
git checkout develop
sed -i '' 's/PROJECT_CORE_VERSION ".*"/PROJECT_CORE_VERSION "0.5.0"/' versions.cmake
git add versions.cmake
git commit -m "bump version to 0.4.9"
git commit -m "bump version to 0.5.0"
git push origin develop
```
4. Create a PR from `develop` to `main`:
2. Create a PR from `develop` to `main`:
```bash
gh pr create --base main --head develop \
--title "Bump version to 0.4.9" \
--body "Version bump for v0.4.9-alpha release."
--title "Release v0.5.0" \
--body "Stable release v0.5.0."
```
5. Wait for CI to pass, then merge the PR (via GitHub UI or CLI):
3. Wait for CI to pass, then merge the PR (via GitHub UI or CLI):
```bash
gh pr merge --merge
```
6. Tag the merged commit on `main` and push — this triggers the release jobs:
4. Tag the merged commit on `main` and push — this triggers the release jobs:
```bash
git fetch origin main
git tag v0.4.9-alpha origin/main
git push origin v0.4.9-alpha
git tag v0.5.0 origin/main
git push origin v0.5.0
```

### Version Tag Convention
- Stable release: `v0.5.0`
- Alpha/pre-release: `v0.4.9-alpha`
- The version in `versions.cmake` should match the numeric part of the tag

| Tag | Branch | Meaning |
|-----|--------|---------|
| `v0.5.0` | `main` | Stable release |
| `v0.4.9-alpha` | `develop` | Alpha pre-release |
| `v0.4.9-dev` | `develop` | Dev pre-release |

The version in `versions.cmake` should match the numeric part of the tag.

### CI Behavior
- **Branch push**: runs `build` matrix job across macOS/Linux/Windows (tests only, with ccache/sccache)
Expand Down
94 changes: 94 additions & 0 deletions .claude/skills/release-process/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
name: release-process
description: GitHub release policy and CI/CD pipeline for uZX. Handles version bumping, tagging, and triggering releases. Use when bumping versions, creating alpha/dev pre-releases from develop, creating stable releases from main, or checking release status.
user-invocable: true
allowed-tools: Read, Edit, Bash, Glob, Grep, AskUserQuestion
---

# uZX Release Process

## Branching Model

| Branch | Purpose | Tag suffix |
|--------|---------|------------|
| `develop` | Alpha/dev pre-releases | `-alpha`, `-dev`, etc. |
| `main` | Stable releases only | none (e.g. `v0.5.0`) |

`main` is protected — requires PRs and passing CI. Never push directly to `main`.

## Version File

Version is defined in `versions.cmake` as `PROJECT_CORE_VERSION`. This value propagates to all app targets (Studio, Tuning, Player).

## Release Flows

### Alpha/Pre-release (from `develop`)

No PR to `main` required. Steps:

1. Ensure on `develop` branch
2. Bump `PROJECT_CORE_VERSION` in `versions.cmake`
3. Commit: `git commit -m "bump version to X.Y.Z"`
4. Push: `git push origin develop`
5. Tag: `git tag vX.Y.Z-alpha` (or `-dev`, `-beta`, etc.)
6. Push tag: `git push origin vX.Y.Z-alpha`

### Stable Release (from `main`)

Requires PR from `develop` to `main`. Steps:

1. Ensure on `develop` branch
2. Bump `PROJECT_CORE_VERSION` in `versions.cmake`
3. Commit and push to `develop`
4. Create PR: `gh pr create --base main --head develop --title "Release vX.Y.Z" --body "Stable release vX.Y.Z."`
5. Wait for CI, merge the PR
6. Tag merged commit: `git fetch origin main && git tag vX.Y.Z origin/main`
7. Push tag: `git push origin vX.Y.Z`

## CI Pipeline (`.github/workflows/ci.yml`)

### Branch push (`main`/`develop`)
- Runs `build` job (Debug, tests only) on macOS, Linux, Windows
- Uses ccache (macOS/Linux) and sccache (Windows)

### Tag push (`v*`) — Release Pipeline
Triggers regardless of which branch the tag points to.

1. **`create-release`** — Creates a draft GitHub Release
- Sets `prerelease: true` if tag contains `-alpha` or `-beta`
- Generates release notes automatically
2. **`release-macos`** / **`release-linux`** / **`release-windows`** — Build + test + package + upload (in parallel)
- Builds Release config for targets: `uZX`, `uZXPlayer`, `uZXTests`
- Runs tests
- Packages and uploads artifacts:
- macOS: `uZX-{ver}-macOS.zip`, `uZXPlayer-{ver}-macOS.zip`
- Linux: `uZX-{ver}-linux-x86_64.tar.gz`, `uZXPlayer-{ver}-linux-x86_64.tar.gz`
- Windows: `uZX-{ver}-windows-x64.zip`, `uZXPlayer-{ver}-windows-x64.zip`
3. **`publish-release`** — After all platforms finish:
- Downloads all artifacts, generates `SHA256SUMS.txt`
- Publishes the release (removes draft status)

### Concurrency
- Branch runs are auto-cancelled when superseded
- Tag (release) runs are never cancelled

## Instructions for Claude

When the user asks to create a release:

1. **Verify branch**: Must be on `develop` for alpha/dev, or have a clean `develop` for stable.
2. **Check current version**: Read `versions.cmake` to know the current version.
3. **Ask if needed**: If the user doesn't specify a version or tag suffix, ask.
4. **Bump version**: Edit `versions.cmake` if the version needs changing.
5. **Commit and push**: Stage, commit with message `bump version to X.Y.Z`, push to the correct branch.
6. **Tag and push**: Create the tag and push it. This triggers the CI release pipeline.
7. **For stable releases**: Create the PR to `main` first, wait for merge, then tag `origin/main`.

Always confirm before pushing tags or creating PRs — these are visible actions that trigger CI pipelines.

### Checking release status
```bash
gh run list --workflow=ci.yml --limit=5
gh run view <run-id>
gh release view <tag>
```
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ jobs:
build-target: uZXTests
test-bin: build/src/uZXTests_artefacts/Debug/uZXTests
cache-path: ~/.cache/ccache
# Linux runners have 16 GB RAM; JUCE/Tracktion TUs are memory-heavy.
# Unbounded -j OOM-kills the runner (SIGTERM/143), so cap parallelism.
parallel: 3
install-deps: true
configure-extra: ""
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ Testing/

.claude/settings.local.json
src/version.h
DEVLOG.md
31 changes: 31 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Repository Guidelines

## Project Structure & Module Organization

uZX is a C++23 JUCE/Tracktion Engine application. App and library code lives under `src/`: `controllers`, `models`, `viewmodels`, `gui`, `plugins/uZX`, `formats`, and `util`. `src/sources.cmake` is authoritative for source membership: add shared code to `SHARED_SOURCES`, UI/app-only code to `GUI_SOURCES`, and tests to `TEST_SOURCES`. Unit tests are colocated with implementation as `*.test.cpp`; `tests/main.cpp` provides the JUCE test runner. Assets live in `resources/`, docs in `docs/`, CMake helpers in `cmake/`, and vendored dependencies in `third_party/`.

## Build, Test, and Development Commands

- `git submodule update --init --depth=1`: fetch JUCE, Tracktion, and ayumi dependencies after cloning.
- `cmake --preset default`: configure a Debug build in `build/`.
- `cmake --build --preset default`: build the default targets.
- `cmake --build build --target uZX`: build Studio; use `uZXTuning`, `uZXPlayer`, or `uZXTests` for other targets.
- `ctest --preset default --output-on-failure`: run CTest after `uZXTests` has been built.
- `build/src/uZXTests_artefacts/Debug/uZXTests AYChip`: run tests matching a filter.
- `./format-code.sh -n` then `./format-code.sh`: dry-run and apply clang-format.

## Coding Style & Naming Conventions

Use `.clang-format`: 4 spaces, no tabs, 120 columns, C++23, sorted include blocks, and left-aligned pointers. Namespaces use `MoTool::` with sub-namespaces where appropriate. Classes and types use PascalCase; functions and methods use camelCase; private members use a trailing underscore; constants use upper-case or enum-style PascalCase. Put opening braces on the same line for functions and on a new line for classes and structs.

## Testing Guidelines

Add JUCE `UnitTest` classes in adjacent `*.test.cpp` files and register them with a static instance. Name tests by feature, such as `TuningViewModel` or `AYChip`, so direct binary filtering remains useful. Cover changed model, tuning, plugin, and controller behavior; add regression tests for bug fixes. Remember to list new test files in `TEST_SOURCES`.

## Commit & Pull Request Guidelines

Prefer concise imperative messages; use a lowercase scope when helpful (`docs:`, `ci:`, `build:`). Branch from `develop` and open PRs back to `develop`; `main` is stable and protected. PRs should describe behavior changes, link issues, list tests run, and include screenshots or recordings for UI changes.

## Agent-Specific Instructions

Do not edit generated build trees or vendored `third_party/` code unless explicitly required. Keep build artifacts out of commits.
18 changes: 12 additions & 6 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [ ] Some bug with pure env bass viz on B channel in SkyTrainFunk close to the start
- [ ] Playhead disappears while dragging fast enough
- [ ] **Fix** sometimes stopping after 2 seconds of playback
- [ ] **Tone/envelope visual mismatch** — detuning between tone and envelope viz when periods are in ratio
- [x] **Drag-and-drop** — accept `.psg` and `.uzx` files dropped onto the window
- [x] **Open from Finder** — handle `anotherInstanceStarted()` / command-line args
- [x] **File association** — `.psg` and `.uzx` macOS file types
Expand All @@ -23,8 +24,8 @@

#### P1 — Important

- [ ] **Add left padding for player**
- [ ] **Global master volume** saved in app settings, not per-edit
- [x] **Add left padding for player**
- [ ] Save/Save As.. menu item for Player
- [ ] Beat+frames-based timeline
- [ ] Different rendering in seconds-only and beat-based timeline
- [x] **PSG** file icons in Finder
Expand All @@ -37,13 +38,18 @@
- [ ] **AY reset** at the start of playback
- [x] **Shift-wheel** horizontal scrolling
- [x] **Mouse gestures** work over the playhead (transparent hit zone)
- [ ] **Middle mouse drag-pan** — pan timeline by dragging with middle mouse button (DAW convention)
- [ ] **Global master volume** — save master volume in app settings, apply to all opened files
- [ ] **UI shortcuts documentation** — document keyboard/mouse shortcuts for users
- [ ] **Cross-platform shortcut unification** — check modifier key behavior consistency across macOS/Windows
- [ ] **Last opened edit** not always working

#### P2 — Nice to have

- [ ] **GitHub Actions CI for macOS** — build, upload as release artifact
- [ ] **Windows build** — GitHub Actions
- [ ] **Linux build** — GitHub Actions
- [x] **GitHub Actions CI for macOS** — build, upload as release artifact
- [x] **Windows build** — GitHub Actions
- [x] **Linux build** — GitHub Actions
- [ ] **Global default AY settings** — apply saved AY config (frequency, stereo, channels) when opening PSG from command line
- [ ] **Mute/solo buttons** — per-channel mute in AY side panel

---
Expand All @@ -64,7 +70,7 @@

#### P1 — Important

- [ ] **Release branch strategy** — tagging `main` recommended
- [x] **Release branch strategy** — tagging `main` recommended
- [ ] **About dialog** — working links to GitHub repo, scroller for greets
- [ ] **Error handling** — graceful message for corrupt/invalid PSG files
- [ ] **Audio device fallback** — handle "no audio device" cleanly
Expand Down
1 change: 1 addition & 0 deletions docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Granular tasks and implementation notes for active development.

## Arranger mode

- [x] Bug with playhead in uZX Studio (not in uZX Player) — root cause: failed audio device freezes audible time; now detected with an error alert + Audio Settings
- [ ] Timecode switching (frames, seconds, bars/beats)
- [ ] Grid respect new timecode format with beats and frames
- [ ] FPS editing of timecode or of a separate edit FPS setting
Expand Down
46 changes: 35 additions & 11 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ build/tests/MoToolTests_artefacts/Debug/uZXTests AYChip # filter by name

## Release Process

Releases are triggered by pushing a `v*` tag. The `main` branch is protected, so changes must go through a PR.
Releases are triggered by pushing a `v*` tag. Tags can be created on either `develop` or `main`:
- **`develop`** — alpha/dev pre-releases (tagged with `-alpha`, `-dev`, etc.)
- **`main`** — stable releases only (tagged without suffix)

### Steps
The `main` branch is protected, so changes must go through a PR.

### Alpha/Pre-release (from `develop`)

1. **Bump the version** on `develop`:
```bash
Expand All @@ -55,30 +59,50 @@ Releases are triggered by pushing a `v*` tag. The `main` branch is protected, so
git push origin develop
```

2. **Tag `develop` HEAD** and push:
```bash
git tag v0.4.9-alpha
git push origin v0.4.9-alpha
```

No PR to `main` needed — this triggers the full release pipeline directly from `develop`.

### Stable Release (from `main`)

1. **Bump the version** on `develop`:
```bash
git checkout develop
# Edit versions.cmake — update PROJECT_CORE_VERSION
git add versions.cmake
git commit -m "bump version to 0.5.0"
git push origin develop
```

2. **Create a PR** from `develop` to `main`:
```bash
gh pr create --base main --head develop \
--title "Bump version to 0.4.9" \
--body "Version bump for v0.4.9-alpha release."
--title "Release v0.5.0" \
--body "Stable release v0.5.0."
```

3. **Wait for CI**, then merge the PR.

4. **Tag the merged commit** on `main`:
```bash
git fetch origin main
git tag v0.4.9-alpha origin/main
git push origin v0.4.9-alpha
git tag v0.5.0 origin/main
git push origin v0.5.0
```

This triggers the full release pipeline: build + test + package on macOS/Linux/Windows, then upload artifacts to a GitHub Release with SHA256 checksums.
Both flows trigger the full release pipeline: build + test + package on macOS/Linux/Windows, then upload artifacts to a GitHub Release with SHA256 checksums.

### Version Tag Convention

| Tag format | Meaning |
|---|---|
| `v0.5.0` | Stable release |
| `v0.4.9-alpha` | Pre-release / alpha |
| Tag | Branch | Meaning |
|-----|--------|---------|
| `v0.5.0` | `main` | Stable release |
| `v0.4.9-alpha` | `develop` | Alpha pre-release |
| `v0.4.9-dev` | `develop` | Dev pre-release |

The version in `versions.cmake` (`PROJECT_CORE_VERSION`) should match the numeric part of the tag.

Expand Down
Loading
Loading