From 31a1e069b3946fb51b3d8dcd2e811a355a5ae6a7 Mon Sep 17 00:00:00 2001 From: Thales Maciel Date: Thu, 12 Mar 2026 19:36:52 -0300 Subject: [PATCH] Prepare the 1.0.0 GA release surface Add the repo-side pieces for milestone 5: MIT licensing, real maintainer and forge metadata, a public support doc, 1.0.0 release notes, release-prep tooling, and CI uploads for the full candidate artifact set. Keep source-tree version surfaces honest by reading the local project version in the CLI and About dialog, and cover the new release-prep plus version-fallback behavior with focused tests. Document where raw validation evidence belongs, add the GA validation rollup, and archive the latest readiness review. Milestone 5 remains open until the forge release page is published and the milestone 2 and 3 matrices are filled with linked manual evidence. Validation: PYTHONPATH=src python3 -m unittest discover -s tests -p 'test_*.py'; PYTHONPATH=src python3 -m unittest tests.test_release_prep tests.test_portable_bundle tests.test_aman_cli tests.test_config_ui; python3 -m py_compile src/*.py tests/*.py; PYTHONPATH=src python3 -m aman version --- .github/workflows/ci.yml | 11 +- CHANGELOG.md | 15 ++- LICENSE | 21 ++++ Makefile | 7 +- README.md | 11 +- SUPPORT.md | 35 ++++++ docs/developer-workflows.md | 7 ++ docs/persona-and-distribution.md | 6 +- docs/portable-install.md | 8 +- docs/release-checklist.md | 20 ++-- docs/releases/1.0.0.md | 69 ++++++++++++ .../05-ga-candidate-validation-and-release.md | 1 + docs/x11-ga/README.md | 7 +- docs/x11-ga/ga-validation-report.md | 54 +++++++++ docs/x11-ga/portable-validation-matrix.md | 3 + docs/x11-ga/runtime-validation-report.md | 4 + packaging/arch/PKGBUILD.in | 4 +- packaging/deb/control.in | 2 +- pyproject.toml | 24 +++- scripts/prepare_release.sh | 63 +++++++++++ src/aman.py | 14 +++ src/config_ui.py | 16 ++- tests/test_aman_cli.py | 8 ++ tests/test_config_ui.py | 10 ++ tests/test_release_prep.py | 88 +++++++++++++++ user-readiness/1773354709.md | 105 ++++++++++++++++++ user-readiness/README.md | 9 +- uv.lock | 2 +- 28 files changed, 591 insertions(+), 33 deletions(-) create mode 100644 LICENSE create mode 100644 SUPPORT.md create mode 100644 docs/releases/1.0.0.md create mode 100644 docs/x11-ga/ga-validation-report.md create mode 100755 scripts/prepare_release.sh create mode 100644 tests/test_release_prep.py create mode 100644 user-readiness/1773354709.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a418c5b..a0c9b04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,12 +17,8 @@ jobs: python -m pip install --upgrade pip python -m pip install uv build uv sync --extra x11 - - name: Release quality checks - run: make release-check - - name: Build Debian package - run: make package-deb - - name: Build Arch package inputs - run: make package-arch + - name: Prepare release candidate artifacts + run: make release-prep - name: Upload packaging artifacts uses: actions/upload-artifact@v4 with: @@ -30,5 +26,8 @@ jobs: path: | dist/*.whl dist/*.tar.gz + dist/*.sha256 + dist/SHA256SUMS dist/*.deb dist/arch/PKGBUILD + dist/arch/*.tar.gz diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c37d25..64ac500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,19 @@ The format is based on Keep a Changelog and this project follows Semantic Versio ## [Unreleased] +## [1.0.0] - 2026-03-12 + ### Added -- Packaging scripts and templates for Debian (`.deb`) and Arch (`PKGBUILD` + source tarball). -- Make targets for build/package/release-check workflows. -- Persona and distribution policy documentation. +- Portable X11 bundle install, upgrade, uninstall, and purge lifecycle. +- Distinct `doctor` and `self-check` diagnostics plus a runtime recovery guide. +- End-user-first first-run docs, screenshots, demo media, release notes, and a public support document. +- `make release-prep` plus `dist/SHA256SUMS` for the GA release artifact set. +- X11 GA validation matrices and a final GA validation report surface. ### Changed -- README now documents package-first installation for non-technical users. -- Release checklist now includes packaging artifacts. +- Project metadata now uses the real maintainer, release URLs, and MIT license. +- Packaging templates now point at the public Aman forge location instead of placeholders. +- CI now prepares the full release-candidate artifact set instead of only Debian and Arch packaging outputs. ## [0.1.0] - 2026-02-26 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..919f772 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Thales Maciel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index 2358cbc..e58b75e 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ BUILD_DIR := $(CURDIR)/build RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) RUN_CONFIG := $(if $(RUN_ARGS),$(abspath $(firstword $(RUN_ARGS))),$(CONFIG)) -.PHONY: run doctor self-check runtime-check eval-models build-heuristic-dataset sync-default-model check-default-model sync test check build package package-deb package-arch package-portable release-check install-local install-service install clean-dist clean-build clean +.PHONY: run doctor self-check runtime-check eval-models build-heuristic-dataset sync-default-model check-default-model sync test check build package package-deb package-arch package-portable release-check release-prep install-local install-service install clean-dist clean-build clean EVAL_DATASET ?= $(CURDIR)/benchmarks/cleanup_dataset.jsonl EVAL_MATRIX ?= $(CURDIR)/benchmarks/model_matrix.small_first.json EVAL_OUTPUT ?= $(CURDIR)/benchmarks/results/latest.json @@ -77,6 +77,11 @@ release-check: $(MAKE) test $(MAKE) build +release-prep: + $(MAKE) release-check + $(MAKE) package + ./scripts/prepare_release.sh + install-local: $(PYTHON) -m pip install --user ".[x11]" diff --git a/README.md b/README.md index 16ce85d..7bd070e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ Aman is a local X11 dictation daemon for Linux desktops. The supported path is: install the portable bundle, save the first-run settings window once, then use a hotkey to dictate into the focused app. +Published bundles, checksums, and release notes live on the +[`git.thaloco.com` releases page](https://git.thaloco.com/thaloco/aman/releases). +Support requests and bug reports go to +[`SUPPORT.md`](SUPPORT.md) or `thales@thalesmaciel.com`. + ## Supported Path | Surface | Contract | @@ -62,7 +67,7 @@ sudo zypper install -y portaudio gtk3 libayatana-appindicator3-1 python3-gobject Then install Aman and run the first dictation: -1. Verify and extract the portable bundle. +1. Download, verify, and extract the portable bundle from the releases page. 2. Run `./install.sh`. 3. When `Aman Settings (Required)` opens, choose your microphone and keep `Clipboard paste (recommended)` unless you have a reason to change it. @@ -138,6 +143,8 @@ The canonical end-user guide lives in - Fresh install, upgrade, uninstall, and purge behavior are documented there. - The same guide covers distro-package conflicts and portable-installer recovery steps. +- Release-specific notes for `1.0.0` live in + [`docs/releases/1.0.0.md`](docs/releases/1.0.0.md). ## Daily Use and Support @@ -162,6 +169,8 @@ The canonical end-user guide lives in - Install, upgrade, uninstall: [docs/portable-install.md](docs/portable-install.md) - Runtime recovery and diagnostics: [docs/runtime-recovery.md](docs/runtime-recovery.md) +- Release notes: [docs/releases/1.0.0.md](docs/releases/1.0.0.md) +- Support and issue reporting: [SUPPORT.md](SUPPORT.md) - Config reference and advanced behavior: [docs/config-reference.md](docs/config-reference.md) - Developer, packaging, and benchmark workflows: [docs/developer-workflows.md](docs/developer-workflows.md) - Persona and distribution policy: [docs/persona-and-distribution.md](docs/persona-and-distribution.md) diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..a524137 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,35 @@ +# Support + +Aman supports X11 desktop sessions on mainstream Linux distros with the +documented runtime dependencies and `systemd --user`. + +For support, bug reports, or packaging issues, email: + +- `thales@thalesmaciel.com` + +## Include this information + +To make support requests actionable, include: + +- distro and version +- whether the session is X11 +- how Aman was installed: portable bundle, `.deb`, Arch package inputs, or + developer install +- the Aman version you installed +- the output of `aman doctor --config ~/.config/aman/config.json` +- the output of `aman self-check --config ~/.config/aman/config.json` +- the first relevant lines from `journalctl --user -u aman` +- whether the problem still reproduces with + `aman run --config ~/.config/aman/config.json --verbose` + +## Supported escalation path + +Use the supported recovery order before emailing: + +1. `aman doctor --config ~/.config/aman/config.json` +2. `aman self-check --config ~/.config/aman/config.json` +3. `journalctl --user -u aman` +4. `aman run --config ~/.config/aman/config.json --verbose` + +The diagnostic IDs and common remediation steps are documented in +[`docs/runtime-recovery.md`](docs/runtime-recovery.md). diff --git a/docs/developer-workflows.md b/docs/developer-workflows.md index 54a751d..2c4d60c 100644 --- a/docs/developer-workflows.md +++ b/docs/developer-workflows.md @@ -13,14 +13,21 @@ make package-deb make package-arch make runtime-check make release-check +make release-prep ``` - `make package-portable` builds `dist/aman-x11-linux-.tar.gz` plus its `.sha256` file. +- `make release-prep` runs `make release-check`, builds the packaged artifacts, + and writes `dist/SHA256SUMS` for the release page upload set. - `make package-deb` installs Python dependencies while creating the package. - For offline Debian packaging, set `AMAN_WHEELHOUSE_DIR` to a directory containing the required wheels. +For `1.0.0`, the manual publication target is the forge release page at +`https://git.thaloco.com/thaloco/aman/releases`, using +[`docs/releases/1.0.0.md`](./releases/1.0.0.md) as the release-notes source. + ## Developer setup `uv` workflow: diff --git a/docs/persona-and-distribution.md b/docs/persona-and-distribution.md index 5b2254e..e15dbbc 100644 --- a/docs/persona-and-distribution.md +++ b/docs/persona-and-distribution.md @@ -36,7 +36,7 @@ Design implications: The current release channels are: -1. Current canonical end-user channel: portable X11 bundle (`aman-x11-linux-.tar.gz`). +1. Current canonical end-user channel: portable X11 bundle (`aman-x11-linux-.tar.gz`) published on `https://git.thaloco.com/thaloco/aman/releases`. 2. Secondary packaged channel: Debian package (`.deb`) for Ubuntu/Debian users. 3. Secondary maintainer channel: Arch package inputs (`PKGBUILD` + source tarball). 4. Developer: wheel and sdist from `python -m build`. @@ -75,7 +75,7 @@ variant. ## Release and Support Policy -- App versioning follows SemVer (`0.y.z` until API/UX stabilizes). +- App versioning follows SemVer starting with `1.0.0` for the X11 GA release. - Config schema versioning is independent (`config_version` in config). - Docs must always separate: - Current release channels @@ -86,5 +86,7 @@ variant. - Daily-use service mode versus manual foreground mode - Canonical recovery sequence - Representative validation families +- Public support and issue reporting currently use email only: + `thales@thalesmaciel.com` - GA means the support contract, validation evidence, and release surface are consistent. It does not require a native package for every distro. diff --git a/docs/portable-install.md b/docs/portable-install.md index 9113f21..21a241e 100644 --- a/docs/portable-install.md +++ b/docs/portable-install.md @@ -5,6 +5,9 @@ This is the canonical end-user install path for Aman on X11. For the shortest first-run path, screenshots, and the expected tray/dictation result, start with the quickstart in [`README.md`](../README.md). +Download published bundles, checksums, and release notes from +`https://git.thaloco.com/thaloco/aman/releases`. + ## Supported environment - X11 desktop session @@ -42,7 +45,7 @@ sudo zypper install -y portaudio gtk3 libayatana-appindicator3-1 python3-gobject ## Fresh install -1. Download `aman-x11-linux-.tar.gz` and `aman-x11-linux-.tar.gz.sha256`. +1. Download `aman-x11-linux-.tar.gz` and `aman-x11-linux-.tar.gz.sha256` from the releases page. 2. Verify the checksum. 3. Extract the bundle. 4. Run `install.sh`. @@ -150,3 +153,6 @@ If installation succeeds but runtime behavior is wrong, use the supported recove The failure IDs and example outputs for this flow are documented in [`docs/runtime-recovery.md`](./runtime-recovery.md). + +Public support and issue reporting instructions live in +[`SUPPORT.md`](../SUPPORT.md). diff --git a/docs/release-checklist.md b/docs/release-checklist.md index 1a42780..e53a7de 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -5,26 +5,27 @@ GA signoff bar. The GA signoff sections are required for `v1.0.0` and later. 1. Update `CHANGELOG.md` with final release notes. 2. Bump `project.version` in `pyproject.toml`. -3. Run quality and build gates: - - `make release-check` - - `make runtime-check` - - `make check-default-model` -4. Ensure model promotion artifacts are current: +3. Ensure model promotion artifacts are current: - `benchmarks/results/latest.json` has the latest `winner_recommendation.name` - `benchmarks/model_artifacts.json` contains that winner with URL + SHA256 - `make sync-default-model` (if constants drifted) -5. Build packaging artifacts: - - `make package` -6. Verify artifacts: +4. Prepare the release candidate: + - `make release-prep` +5. Verify artifacts: - `dist/*.whl` - `dist/aman-x11-linux-.tar.gz` - `dist/aman-x11-linux-.tar.gz.sha256` + - `dist/SHA256SUMS` - `dist/*.deb` - `dist/arch/PKGBUILD` +6. Verify checksums: + - `sha256sum -c dist/SHA256SUMS` 7. Tag release: - `git tag vX.Y.Z` - `git push origin vX.Y.Z` -8. Publish release and upload package artifacts from `dist/`. +8. Publish `vX.Y.Z` on `https://git.thaloco.com/thaloco/aman/releases` and upload package artifacts from `dist/`. + - Use [`docs/releases/1.0.0.md`](./releases/1.0.0.md) as the release-notes source for the GA release. + - Include `dist/SHA256SUMS` with the uploaded artifacts. 9. Portable bundle release signoff: - `README.md` points end users to the portable bundle first. - [`docs/portable-install.md`](./portable-install.md) matches the shipped install, upgrade, uninstall, and purge behavior. @@ -49,3 +50,4 @@ GA signoff bar. The GA signoff sections are required for `v1.0.0` and later. - The portable installer, upgrade path, and uninstall path are validated. - End-user docs and release notes match the shipped artifact set. - Public metadata, checksums, and support/reporting surfaces are complete. + - [`docs/x11-ga/ga-validation-report.md`](./x11-ga/ga-validation-report.md) links the release page, matrices, and raw evidence files. diff --git a/docs/releases/1.0.0.md b/docs/releases/1.0.0.md new file mode 100644 index 0000000..a3bd191 --- /dev/null +++ b/docs/releases/1.0.0.md @@ -0,0 +1,69 @@ +# Aman 1.0.0 + +This is the first GA-targeted X11 release for Aman. + +- Canonical release page: + `https://git.thaloco.com/thaloco/aman/releases/tag/v1.0.0` +- Canonical release index: + `https://git.thaloco.com/thaloco/aman/releases` +- Support and issue reporting: + `thales@thalesmaciel.com` + +## Supported environment + +- X11 desktop sessions only +- `systemd --user` for supported daily use +- System CPython `3.10`, `3.11`, or `3.12` for the portable installer +- Runtime dependencies installed from the distro package manager +- Representative validation families: Debian/Ubuntu, Arch, Fedora, openSUSE + +## Artifacts + +The release page should publish: + +- `aman-x11-linux-1.0.0.tar.gz` +- `aman-x11-linux-1.0.0.tar.gz.sha256` +- `SHA256SUMS` +- wheel artifact from `dist/*.whl` +- Debian package from `dist/*.deb` +- Arch package inputs from `dist/arch/PKGBUILD` and `dist/arch/*.tar.gz` + +## Install, update, and uninstall + +- Install: download the portable bundle and checksum from the release page, + verify the checksum, extract the bundle, then run `./install.sh` +- Update: extract the newer bundle and run its `./install.sh` +- Uninstall: run `~/.local/share/aman/current/uninstall.sh` +- Purge uninstall: run `~/.local/share/aman/current/uninstall.sh --purge` + +The full end-user lifecycle is documented in +[`docs/portable-install.md`](../portable-install.md). + +## Recovery path + +If the supported path fails, use: + +1. `aman doctor --config ~/.config/aman/config.json` +2. `aman self-check --config ~/.config/aman/config.json` +3. `journalctl --user -u aman` +4. `aman run --config ~/.config/aman/config.json --verbose` + +Reference diagnostics and failure IDs live in +[`docs/runtime-recovery.md`](../runtime-recovery.md). + +## Support + +Email `thales@thalesmaciel.com` with: + +- distro and version +- X11 confirmation +- install channel and Aman version +- `aman doctor` output +- `aman self-check` output +- relevant `journalctl --user -u aman` lines + +## Non-goals + +- Wayland support +- Flatpak or snap as the canonical GA path +- Native-package parity across every Linux distro diff --git a/docs/x11-ga/05-ga-candidate-validation-and-release.md b/docs/x11-ga/05-ga-candidate-validation-and-release.md index d107360..23622df 100644 --- a/docs/x11-ga/05-ga-candidate-validation-and-release.md +++ b/docs/x11-ga/05-ga-candidate-validation-and-release.md @@ -58,3 +58,4 @@ The final step to GA is not more feature work. It is proving that Aman has a rea - Completed validation report for the representative distro families. - Updated release checklist with signed-off GA criteria. - Public support/reporting instructions that match the shipped product. +- Raw validation evidence stored in `user-readiness/.md` and linked from the validation matrices. diff --git a/docs/x11-ga/README.md b/docs/x11-ga/README.md index 381d002..fca3f86 100644 --- a/docs/x11-ga/README.md +++ b/docs/x11-ga/README.md @@ -106,7 +106,12 @@ Any future docs, tray copy, and release notes should point users to this same se [`first-run-review-notes.md`](./first-run-review-notes.md) plus [`user-readiness/1773352170.md`](../../user-readiness/1773352170.md). - [ ] [Milestone 5: GA Candidate Validation and Release](./05-ga-candidate-validation-and-release.md) - Close the remaining trust, legal, release, and validation work for a public 1.0 launch. + Implementation landed on 2026-03-12: repo metadata now uses the real + maintainer and forge URLs, `LICENSE`, `SUPPORT.md`, `docs/releases/1.0.0.md`, + `make release-prep`, and [`ga-validation-report.md`](./ga-validation-report.md) + now exist. Leave this milestone open until the release page is published and + the milestone 2 and 3 validation matrices are filled with linked raw + evidence. ## Cross-milestone acceptance scenarios diff --git a/docs/x11-ga/ga-validation-report.md b/docs/x11-ga/ga-validation-report.md new file mode 100644 index 0000000..1a81ca9 --- /dev/null +++ b/docs/x11-ga/ga-validation-report.md @@ -0,0 +1,54 @@ +# GA Validation Report + +This document is the final rollup for the X11 GA release. It does not replace +the underlying evidence sources. It links them and records the final signoff +state. + +## Where to put validation evidence + +- Put raw manual validation notes in `user-readiness/.md`. +- Use one timestamped file per validation session, distro pass, or reviewer + handoff. +- In the raw evidence file, record: + - distro and version + - reviewer + - date + - release artifact version + - commands run + - pass/fail results + - failure details and recovery outcome +- Reference those timestamped files from the `Notes` columns in: + - [`portable-validation-matrix.md`](./portable-validation-matrix.md) + - [`runtime-validation-report.md`](./runtime-validation-report.md) + +## Release metadata + +- Release version: `1.0.0` +- Release page: + `https://git.thaloco.com/thaloco/aman/releases/tag/v1.0.0` +- Support channel: `thales@thalesmaciel.com` +- License: MIT + +## Evidence sources + +- Portable lifecycle matrix: + [`portable-validation-matrix.md`](./portable-validation-matrix.md) +- Runtime reliability matrix: + [`runtime-validation-report.md`](./runtime-validation-report.md) +- First-run review: + [`first-run-review-notes.md`](./first-run-review-notes.md) +- Raw evidence archive: + [`user-readiness/README.md`](../../user-readiness/README.md) +- Release notes: + [`docs/releases/1.0.0.md`](../releases/1.0.0.md) + +## Final signoff status + +| Area | Status | Evidence | +| --- | --- | --- | +| Milestone 2 portable lifecycle | Pending | Fill `portable-validation-matrix.md` and link raw timestamped evidence | +| Milestone 3 runtime reliability | Pending | Fill `runtime-validation-report.md` and link raw timestamped evidence | +| Milestone 4 first-run UX/docs | Complete | `first-run-review-notes.md` and `user-readiness/1773352170.md` | +| Release metadata and support surface | Repo-complete | `LICENSE`, `SUPPORT.md`, `pyproject.toml`, packaging templates | +| Release artifacts and checksums | Repo-complete | `make release-prep`, `dist/SHA256SUMS`, `docs/releases/1.0.0.md` | +| Published release page | Pending | Publish `v1.0.0` on the forge release page and attach the prepared artifacts | diff --git a/docs/x11-ga/portable-validation-matrix.md b/docs/x11-ga/portable-validation-matrix.md index 526ff67..26486f1 100644 --- a/docs/x11-ga/portable-validation-matrix.md +++ b/docs/x11-ga/portable-validation-matrix.md @@ -20,6 +20,9 @@ Completed on 2026-03-12: These rows must be filled with real results before milestone 2 can be closed as fully complete for GA evidence. +Store raw evidence for each distro pass in `user-readiness/.md` +and reference that file in the `Notes` column. + | Distro family | Fresh install | First service start | Upgrade | Uninstall | Reinstall | Reboot or service restart | Missing dependency recovery | Conflict with prior package install | Reviewer | Status | Notes | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Debian/Ubuntu | Pending | Pending | Pending | Pending | Pending | Pending | Pending | Pending | Pending | Pending | | diff --git a/docs/x11-ga/runtime-validation-report.md b/docs/x11-ga/runtime-validation-report.md index 586bafc..88e77ac 100644 --- a/docs/x11-ga/runtime-validation-report.md +++ b/docs/x11-ga/runtime-validation-report.md @@ -34,6 +34,10 @@ Completed on 2026-03-12: These rows must be filled with release-specific evidence before milestone 3 can be closed as complete for GA signoff. +Store raw evidence for each runtime validation pass in +`user-readiness/.md` and reference that file in the `Notes` +column. + | Scenario | Debian/Ubuntu | Arch | Fedora | openSUSE | Reviewer | Status | Notes | | --- | --- | --- | --- | --- | --- | --- | --- | | Service restart after a successful install | Pending | Pending | Pending | Pending | Pending | Pending | Verify `systemctl --user restart aman` returns to the tray/ready state | diff --git a/packaging/arch/PKGBUILD.in b/packaging/arch/PKGBUILD.in index 8fc7e86..f29ab99 100644 --- a/packaging/arch/PKGBUILD.in +++ b/packaging/arch/PKGBUILD.in @@ -1,10 +1,10 @@ -# Maintainer: Aman Maintainers +# Maintainer: Thales Maciel pkgname=aman pkgver=__VERSION__ pkgrel=1 pkgdesc="Local amanuensis daemon for X11 desktops" arch=('x86_64') -url="https://github.com/example/aman" +url="https://git.thaloco.com/thaloco/aman" license=('MIT') depends=('python' 'python-pip' 'python-setuptools' 'portaudio' 'gtk3' 'libayatana-appindicator' 'python-gobject' 'python-xlib') makedepends=('python-build' 'python-installer' 'python-wheel') diff --git a/packaging/deb/control.in b/packaging/deb/control.in index 74a906d..345868b 100644 --- a/packaging/deb/control.in +++ b/packaging/deb/control.in @@ -3,7 +3,7 @@ Version: __VERSION__ Section: utils Priority: optional Architecture: __ARCH__ -Maintainer: Aman Maintainers +Maintainer: Thales Maciel Depends: python3, python3-venv, python3-gi, python3-xlib, libportaudio2, gir1.2-gtk-3.0, libayatana-appindicator3-1 Description: Aman local amanuensis daemon for X11 desktops Aman records microphone input, transcribes speech, optionally rewrites output, diff --git a/pyproject.toml b/pyproject.toml index c2db65e..f96230d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,10 +4,26 @@ build-backend = "setuptools.build_meta" [project] name = "aman" -version = "0.1.0" +version = "1.0.0" description = "X11 STT daemon with faster-whisper and optional AI cleanup" readme = "README.md" requires-python = ">=3.10" +license = { file = "LICENSE" } +authors = [ + { name = "Thales Maciel", email = "thales@thalesmaciel.com" }, +] +maintainers = [ + { name = "Thales Maciel", email = "thales@thalesmaciel.com" }, +] +classifiers = [ + "Environment :: X11 Applications", + "License :: OSI Approved :: MIT License", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] dependencies = [ "faster-whisper", "llama-cpp-python", @@ -26,6 +42,12 @@ x11 = [ ] wayland = [] +[project.urls] +Homepage = "https://git.thaloco.com/thaloco/aman" +Source = "https://git.thaloco.com/thaloco/aman" +Releases = "https://git.thaloco.com/thaloco/aman/releases" +Support = "https://git.thaloco.com/thaloco/aman" + [tool.setuptools] package-dir = {"" = "src"} packages = ["engine", "stages"] diff --git a/scripts/prepare_release.sh b/scripts/prepare_release.sh new file mode 100755 index 0000000..510443d --- /dev/null +++ b/scripts/prepare_release.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +source "${SCRIPT_DIR}/package_common.sh" + +require_command sha256sum + +VERSION="$(project_version)" +PACKAGE_NAME="$(project_name)" +DIST_DIR="${DIST_DIR:-${ROOT_DIR}/dist}" +ARCH_DIST_DIR="${DIST_DIR}/arch" +PORTABLE_TARBALL="${DIST_DIR}/${PACKAGE_NAME}-x11-linux-${VERSION}.tar.gz" +PORTABLE_CHECKSUM="${PORTABLE_TARBALL}.sha256" +ARCH_TARBALL="${ARCH_DIST_DIR}/${PACKAGE_NAME}-${VERSION}.tar.gz" +ARCH_PKGBUILD="${ARCH_DIST_DIR}/PKGBUILD" +SHA256SUMS_PATH="${DIST_DIR}/SHA256SUMS" + +require_file() { + local path="$1" + if [[ -f "${path}" ]]; then + return + fi + echo "missing required release artifact: ${path}" >&2 + exit 1 +} + +require_file "${PORTABLE_TARBALL}" +require_file "${PORTABLE_CHECKSUM}" +require_file "${ARCH_TARBALL}" +require_file "${ARCH_PKGBUILD}" + +shopt -s nullglob +wheels=("${DIST_DIR}/${PACKAGE_NAME//-/_}-${VERSION}-"*.whl) +debs=("${DIST_DIR}/${PACKAGE_NAME}_${VERSION}_"*.deb) +shopt -u nullglob + +if [[ "${#wheels[@]}" -eq 0 ]]; then + echo "missing required release artifact: wheel for ${PACKAGE_NAME} ${VERSION}" >&2 + exit 1 +fi +if [[ "${#debs[@]}" -eq 0 ]]; then + echo "missing required release artifact: deb for ${PACKAGE_NAME} ${VERSION}" >&2 + exit 1 +fi + +mapfile -t published_files < <( + cd "${DIST_DIR}" && find . -type f ! -name "SHA256SUMS" -print | LC_ALL=C sort +) + +if [[ "${#published_files[@]}" -eq 0 ]]; then + echo "no published files found in ${DIST_DIR}" >&2 + exit 1 +fi + +( + cd "${DIST_DIR}" + rm -f "SHA256SUMS" + sha256sum "${published_files[@]}" >"SHA256SUMS" +) + +echo "generated ${SHA256SUMS_PATH}" diff --git a/src/aman.py b/src/aman.py index abad3ff..1aedda4 100755 --- a/src/aman.py +++ b/src/aman.py @@ -770,7 +770,21 @@ def _build_editor_stage(cfg: Config, *, verbose: bool) -> LlamaEditorStage: ) +def _local_project_version() -> str | None: + pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml" + if not pyproject_path.exists(): + return None + for line in pyproject_path.read_text(encoding="utf-8").splitlines(): + stripped = line.strip() + if stripped.startswith('version = "'): + return stripped.split('"')[1] + return None + + def _app_version() -> str: + local_version = _local_project_version() + if local_version: + return local_version try: return importlib.metadata.version("aman") except importlib.metadata.PackageNotFoundError: diff --git a/src/config_ui.py b/src/config_ui.py index a3bcfaa..dcc6c39 100644 --- a/src/config_ui.py +++ b/src/config_ui.py @@ -1,6 +1,7 @@ from __future__ import annotations import copy +import importlib.metadata import logging import time from dataclasses import dataclass @@ -642,9 +643,22 @@ def show_about_dialog() -> None: def _present_about_dialog(parent) -> None: about = Gtk.AboutDialog(transient_for=parent, modal=True) about.set_program_name("Aman") - about.set_version("pre-release") + about.set_version(_app_version()) about.set_comments("Local amanuensis for X11 desktop dictation and rewriting.") about.set_license("MIT") about.set_wrap_license(True) about.run() about.destroy() + + +def _app_version() -> str: + pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml" + if pyproject_path.exists(): + for line in pyproject_path.read_text(encoding="utf-8").splitlines(): + stripped = line.strip() + if stripped.startswith('version = "'): + return stripped.split('"')[1] + try: + return importlib.metadata.version("aman") + except importlib.metadata.PackageNotFoundError: + return "unknown" diff --git a/tests/test_aman_cli.py b/tests/test_aman_cli.py index 37bd1e6..8677ee5 100644 --- a/tests/test_aman_cli.py +++ b/tests/test_aman_cli.py @@ -242,6 +242,14 @@ class AmanCliTests(unittest.TestCase): self.assertEqual(exit_code, 0) self.assertEqual(out.getvalue().strip(), "1.2.3") + def test_app_version_prefers_local_pyproject_version(self): + pyproject_text = '[project]\nversion = "9.9.9"\n' + + with patch.object(aman.Path, "exists", return_value=True), patch.object( + aman.Path, "read_text", return_value=pyproject_text + ), patch("aman.importlib.metadata.version", return_value="1.0.0"): + self.assertEqual(aman._app_version(), "9.9.9") + def test_doctor_command_json_output_and_exit_code(self): report = DiagnosticReport( checks=[DiagnosticCheck(id="config.load", status="ok", message="ok", next_step="")] diff --git a/tests/test_config_ui.py b/tests/test_config_ui.py index 5b22a04..7c0c8d5 100644 --- a/tests/test_config_ui.py +++ b/tests/test_config_ui.py @@ -11,9 +11,11 @@ from config import Config from config_ui import ( RUNTIME_MODE_EXPERT, RUNTIME_MODE_MANAGED, + _app_version, apply_canonical_runtime_defaults, infer_runtime_mode, ) +from unittest.mock import patch class ConfigUiRuntimeModeTests(unittest.TestCase): @@ -38,6 +40,14 @@ class ConfigUiRuntimeModeTests(unittest.TestCase): self.assertFalse(cfg.models.allow_custom_models) self.assertEqual(cfg.models.whisper_model_path, "") + def test_app_version_prefers_local_pyproject_version(self): + pyproject_text = '[project]\nversion = "9.9.9"\n' + + with patch("config_ui.Path.exists", return_value=True), patch( + "config_ui.Path.read_text", return_value=pyproject_text + ), patch("config_ui.importlib.metadata.version", return_value="1.0.0"): + self.assertEqual(_app_version(), "9.9.9") + if __name__ == "__main__": unittest.main() diff --git a/tests/test_release_prep.py b/tests/test_release_prep.py new file mode 100644 index 0000000..07c6234 --- /dev/null +++ b/tests/test_release_prep.py @@ -0,0 +1,88 @@ +import os +import subprocess +import tempfile +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +def _project_version() -> str: + for line in (ROOT / "pyproject.toml").read_text(encoding="utf-8").splitlines(): + if line.startswith('version = "'): + return line.split('"')[1] + raise RuntimeError("project version not found") + + +def _write_file(path: Path, content: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + + +class ReleasePrepScriptTests(unittest.TestCase): + def test_prepare_release_writes_sha256sums_for_expected_artifacts(self): + with tempfile.TemporaryDirectory() as tmp: + tmp_path = Path(tmp) + dist_dir = tmp_path / "dist" + arch_dir = dist_dir / "arch" + version = _project_version() + + _write_file(dist_dir / f"aman-{version}-py3-none-any.whl", "wheel\n") + _write_file(dist_dir / f"aman-x11-linux-{version}.tar.gz", "portable\n") + _write_file(dist_dir / f"aman-x11-linux-{version}.tar.gz.sha256", "checksum\n") + _write_file(dist_dir / f"aman_{version}_amd64.deb", "deb\n") + _write_file(arch_dir / "PKGBUILD", "pkgbuild\n") + _write_file(arch_dir / f"aman-{version}.tar.gz", "arch-src\n") + + env = os.environ.copy() + env["DIST_DIR"] = str(dist_dir) + + subprocess.run( + ["bash", "./scripts/prepare_release.sh"], + cwd=ROOT, + env=env, + text=True, + capture_output=True, + check=True, + ) + + sha256sums = (dist_dir / "SHA256SUMS").read_text(encoding="utf-8") + self.assertIn(f"./aman-{version}-py3-none-any.whl", sha256sums) + self.assertIn(f"./aman-x11-linux-{version}.tar.gz", sha256sums) + self.assertIn(f"./aman-x11-linux-{version}.tar.gz.sha256", sha256sums) + self.assertIn(f"./aman_{version}_amd64.deb", sha256sums) + self.assertIn(f"./arch/PKGBUILD", sha256sums) + self.assertIn(f"./arch/aman-{version}.tar.gz", sha256sums) + + def test_prepare_release_fails_when_expected_artifact_is_missing(self): + with tempfile.TemporaryDirectory() as tmp: + tmp_path = Path(tmp) + dist_dir = tmp_path / "dist" + arch_dir = dist_dir / "arch" + version = _project_version() + + _write_file(dist_dir / f"aman-{version}-py3-none-any.whl", "wheel\n") + _write_file(dist_dir / f"aman-x11-linux-{version}.tar.gz", "portable\n") + _write_file(dist_dir / f"aman-x11-linux-{version}.tar.gz.sha256", "checksum\n") + _write_file(arch_dir / "PKGBUILD", "pkgbuild\n") + _write_file(arch_dir / f"aman-{version}.tar.gz", "arch-src\n") + + env = os.environ.copy() + env["DIST_DIR"] = str(dist_dir) + + result = subprocess.run( + ["bash", "./scripts/prepare_release.sh"], + cwd=ROOT, + env=env, + text=True, + capture_output=True, + check=False, + ) + + self.assertNotEqual(result.returncode, 0) + self.assertIn("missing required release artifact", result.stderr) + + +if __name__ == "__main__": + unittest.main() diff --git a/user-readiness/1773354709.md b/user-readiness/1773354709.md new file mode 100644 index 0000000..51d626a --- /dev/null +++ b/user-readiness/1773354709.md @@ -0,0 +1,105 @@ +# User Readiness Review + +- Date: 2026-03-12 +- Reviewer: Codex +- Scope: documentation, packaged artifacts, and CLI help surface +- Live run status: documentation-and-artifact based plus `python3 -m aman --help`; I did not launch the GTK daemon in a live X11 session + +## Verdict + +A new X11 user can now tell what Aman is for, how to install it, what success +looks like, and what recovery path to follow when the first run goes wrong. +That is a real improvement over an internal-looking project surface. + +It still does not feel fully distribution-ready. The first-contact and +onboarding story are strong, but the public release and validation story still +looks in-progress rather than complete. + +## What A New User Would Experience + +A new user lands on a README that immediately states the product, the supported +environment, the install path, the expected first dictation result, and the +recovery flow. The quickstart is concrete, with distro-specific dependency +commands, screenshots, demo media, and a plain-language description of what the +tray and injected text should do. The install and support docs stay aligned +with that same path, which keeps the project from feeling like it requires +author hand-holding. + +Confidence drops once the user looks for proof that the release is actually +published and validated. The repo-visible evidence still shows pending GA +publication work and pending manual distro validation, so the project reads as +"nearly ready" instead of "safe to recommend." + +## Top Blockers + +1. The public release trust surface is still incomplete. The supported install + path depends on a published release page, but + `docs/x11-ga/ga-validation-report.md` still marks `Published release page` + as `Pending`. +2. The artifact story still reads as pre-release. `docs/releases/1.0.0.md` + says the release page "should publish" the artifacts, and local `dist/` + contents are still `0.1.0` wheel and tarball outputs rather than a visible + `1.0.0` portable bundle plus checksum set. +3. Supported-distro validation is still promise, not proof. + `docs/x11-ga/portable-validation-matrix.md` and + `docs/x11-ga/runtime-validation-report.md` show good automated coverage, but + every manual Debian/Ubuntu, Arch, Fedora, and openSUSE row is still + `Pending`. +4. The top-level CLI help still mixes end-user and maintainer workflows. + Commands like `bench`, `eval-models`, `build-heuristic-dataset`, and + `sync-default-model` make the help surface feel more internal than a focused + desktop product when a user checks `--help`. + +## What Is Already Working + +- A new user can tell what Aman is and who it is for from `README.md`. +- A new user can follow one obvious install path without being pushed into + developer tooling. +- A new user can see screenshots, demo media, expected tray states, and a + sample dictated phrase before installing. +- A new user gets a coherent support and recovery story through `doctor`, + `self-check`, `journalctl`, and `aman run --verbose`. +- The repo now has visible trust signals such as a real `LICENSE`, + maintainer/contact metadata, and a public support document. + +## Quick Wins + +- Publish the `1.0.0` release page with the portable bundle, checksum files, + and final release notes, then replace every `Pending` or "should publish" + wording with completed wording. +- Make the local artifact story match the docs by generating or checking in the + expected `1.0.0` release outputs referenced by the release documentation. +- Fill at least one full manual validation pass per supported distro family and + link each timestamped evidence file into the two GA matrices. +- Narrow the top-level CLI help to the supported user commands, or clearly + label maintainer-only commands so the main recovery path stays prominent. + +## What Would Make It Distribution-Ready + +Before broader distribution, it needs a real published `1.0.0` release page, +artifact and checksum evidence that matches the docs, linked manual validation +results across the supported distro families, and a slightly cleaner user-facing +CLI surface. Once those land, the project will look like a maintained product +rather than a well-documented release candidate. + +## Evidence + +### Commands Run + +- `bash /home/thales/projects/personal/skills-exploration/.agents/skills/user-readiness-review/scripts/collect_readiness_context.sh` +- `PYTHONPATH=src python3 -m aman --help` +- `find docs/media -maxdepth 1 -type f | sort` +- `ls -la dist` + +### Files Reviewed + +- `README.md` +- `docs/portable-install.md` +- `SUPPORT.md` +- `pyproject.toml` +- `CHANGELOG.md` +- `docs/releases/1.0.0.md` +- `docs/persona-and-distribution.md` +- `docs/x11-ga/ga-validation-report.md` +- `docs/x11-ga/portable-validation-matrix.md` +- `docs/x11-ga/runtime-validation-report.md` diff --git a/user-readiness/README.md b/user-readiness/README.md index 9ef921f..53c954c 100644 --- a/user-readiness/README.md +++ b/user-readiness/README.md @@ -1,4 +1,4 @@ -# User Readiness Reports +# User Readiness Reports And Validation Evidence Each Markdown file in this directory is a user readiness report for the project. @@ -6,3 +6,10 @@ project. The filename title is a Linux timestamp. In practice, a report named `1773333303.md` corresponds to a report generated at Unix timestamp `1773333303`. + +This directory also stores raw manual validation evidence for GA signoff. +Use one timestamped file per validation session and reference those files from: + +- `docs/x11-ga/portable-validation-matrix.md` +- `docs/x11-ga/runtime-validation-report.md` +- `docs/x11-ga/ga-validation-report.md` diff --git a/uv.lock b/uv.lock index e69b422..93dcd92 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "aman" -version = "0.1.0" +version = "1.0.0" source = { editable = "." } dependencies = [ { name = "faster-whisper" },