# Release

Weyaw uses a shell script to build cross-platform archives and optionally
upload them to GitHub Releases.

## Prerequisites

- Rust 1.96+ via [rustup](https://rustup.rs)
- Rust targets for all platforms you want to build:
  ```bash
  rustup target add x86_64-pc-windows-gnu x86_64-unknown-linux-gnu aarch64-apple-darwin
  ```
- For Windows x64 cross-compilation from WSL2/Linux:
  ```bash
  sudo apt install gcc-mingw-w64-x86-64-win32 mingw-w64-x86-64-dev zip
  ```
  The default Windows release target is `x86_64-pc-windows-gnu`. The
  `x86_64-pc-windows-msvc` target remains available only as an explicit
  alternate target for environments that provide an MSVC-compatible toolchain.
- For macOS cross-compilation from Linux:
  [cargo-zigbuild](https://github.com/rust-cross/cargo-zigbuild),
  [Zig](https://ziglang.org/), and an Apple macOS SDK that you are authorized
  to use. Point cargo-zigbuild at the extracted SDK before running the release:
  ```bash
  export SDKROOT=/path/to/MacOSX.sdk
  ```
  A full Xcode or osxcross installation is not required; the SDK directory is
  the only additional platform payload needed by the existing Zig toolchain.
- For upload: [GitHub CLI](https://cli.github.com/) (`gh`)
- For npm publish: [Node.js](https://nodejs.org/) 18+ and an npm account
  with publish access to the `weyaw`, `weyaw-linux-x64`, `weyaw-darwin-arm64`,
  and `weyaw-win32-x64` packages. Run `npm login` before publishing.

## Build

```bash
./scripts/release.sh
```

This reads the version from `Cargo.toml`, builds all targets, packages each
with the dashboard frontend into platform archives, and writes everything to
`releases/v<version>/`.

### Options

| Flag | Description |
|---|---|
| `--targets TARGET[,…]` | Build only specific targets |
| `--skip-dashboard` | Skip the dashboard dist check |
| `--skip-build` | Package existing binaries without rebuilding |
| `--upload` | Upload archives to GitHub Releases via `gh` |
| `--publish` | Stage binaries into platform packages and npm publish |

### Examples

Build only Linux:

```bash
./scripts/release.sh --targets x86_64-unknown-linux-gnu
```

Build only Windows x64 from WSL2/Linux:

```bash
./scripts/release.sh --targets x86_64-pc-windows-gnu
```

Build and upload:

```bash
./scripts/release.sh --upload
```

Build and publish to npm:

```bash
./scripts/release.sh --publish
```

## npm distribution

Weyaw is distributed via npm. Each platform has its own package containing
the pre-built binary:

| Package | Platform |
|---|---|
| `weyaw-linux-x64` | Linux x86_64 |
| `weyaw-darwin-arm64` | macOS Apple Silicon |
| `weyaw-win32-x64` | Windows x86_64 |

The main `weyaw` package declares these as `optionalDependencies`. npm
automatically installs only the one matching the user's platform. The
`bin/aw.js` wrapper resolves the binary from the platform package at runtime.

### Publish workflow

The `--publish` flag handles the full sequence:

1. Builds and archives all targets (same as default).
2. Stages each platform's `aw` binary and `dashboard/` into
   `platforms/<pkg>/`.
3. Publishes each platform package (`npm publish --access public`).
4. Publishes the main `weyaw` package last (it must come after its
   `optionalDependencies` are live).

For partial release recovery, do not use `--publish` blindly after any platform
package version has already been published. npm package versions are immutable,
so publish only the missing platform package versions first, then publish the
main `weyaw` package after all optional dependencies for that version exist.

Manual publish (if needed):

```bash
# Platform packages first, in any order:
npm publish platforms/weyaw-linux-x64 --access public
npm publish platforms/weyaw-darwin-arm64 --access public
npm publish platforms/weyaw-win32-x64 --access public

# Main package last:
npm publish --access public
```

### Version bump

Update `Cargo.toml`, the `weyaw-rs` entry in `Cargo.lock`, all four release `package.json` files (root + `platforms/*/`), and the root package's three `optionalDependencies` pins. Keep current-runtime test fixtures aligned; historical version-identity fixtures and documentation examples do not need a bump. The private dashboard and internal crates retain their independent versions.

Validate and commit the release preparation, then create `v<version>` at that commit. Build the final archives from that clean tagged checkout so the embedded binary identity reports the plain release version. Builds made before the matching tag exists are development builds, even when archive filenames use the release version. Rebuild rather than using `--skip-build` with pre-tag binaries. The release script reads the package version from `Cargo.toml`; it does not enforce clean-tag provenance.

### Binary version identity

`aw --version` and the existing `version` field in `aw doctor --json` report the same identity embedded at build time. A clean checkout at `v<Cargo package version>` reports the plain version, such as `0.3.8`. Later commits report `0.3.8+dev.29.gab92835`: the count is `git rev-list --count v0.3.8..HEAD`, and the suffix identifies the build commit. Changes to Git-tracked files, including staged additions, append `.dirty`; changes at the tag itself produce `+dev.0.g<hash>.dirty`. Untracked files alone do not mark the build dirty. The short hash identifies a commit, not uncommitted content.

Absent Git metadata, a missing or unreachable matching tag, or incomplete history reports `0.3.8+dev.unknown` rather than claiming a release or inventing a distance. An exact clean tag remains identifiable in a shallow checkout. Source archives without Git metadata also report unknown. A plain version identifies tagged source; trusted distribution and checksums, not this string alone, establish official release provenance.

Ordinary `cargo build` and `cargo build --release` both capture identity; optimization mode does not determine release status. Cargo watches tracked files and Git-resolved HEAD, index, refs and existing packed-ref/fetch/shallow metadata, including linked-worktree paths. It does not watch the entire shared Git directory or force every invocation to recompile. Unchanged checkouts reuse compiled output; changes to watched metadata can trigger a rebuild. Without a `.git` entry, Cargo rechecks on each invocation so a subsequently initialized checkout does not retain an unknown identity. An existing binary never reads the runtime working directory to determine its version.

The `+` suffix is SemVer build metadata and does not affect version precedence. Package versions, workflow provenance, guidance fingerprints and skill compatibility retain the Cargo package version; no additional doctor fields are introduced. This does not update installed binaries or authorize publication.

## Output

```
releases/v0.1.0/
  weyaw-v0.1.0-x64-linux.tar.gz
  weyaw-v0.1.0-arm64-macos.tar.gz
  weyaw-v0.1.0-x64-windows.zip
  checksums.txt
  download.html
```

Each archive contains the `aw` binary and a `dashboard/` directory with the
built frontend assets.

`download.html` is a self-contained page (generated from
`scripts/download-template.html`) with per-platform download links, install
instructions, and checksums.
