From c1f9f62bbcad133a1edff4a37d20b648ca0f9cac Mon Sep 17 00:00:00 2001 From: claude-code Date: Thu, 22 Oct 2026 09:48:51 +0200 Subject: [PATCH 1/3] docs(install): document the one-line install in the guides, not only the README The install guide (deploy.md, the docs-site Get started page) and the pages that told readers to pip install (adopt-govern, slash-commands, operate-goose, cli/README.md) now show the installer, with one full explanation in deploy.md that the others link to: flags, pinning in CI, what it checks, and uninstall. The README uninstall line now works for someone who only ran the one-liner. Signed-off-by: claude-code Agent: claude-code (Sonnet 5.5) (automated, instructed-by: welsbach) Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 3 ++- README.md | 2 +- cli/README.md | 4 +++- docs/guides/adopt-govern.md | 5 +++-- docs/guides/deploy.md | 32 ++++++++++++++++++++++++++++++-- docs/guides/operate-goose.md | 9 ++++++++- docs/guides/slash-commands.md | 5 +++-- docs/specs/one-line-install.md | 3 ++- 8 files changed, 52 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44233a1..8169305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ draft, so pin a conformance claim to a commit or date. `/versions/X.Y.Z` trees carrying its own marker, and has an `uninstall`. A new `release.yml` builds the archive from a `vX.Y.Z` tag, installs from it, and only then publishes. The installer's tests run it confined (fake `HOME`, an `rm` shim, and an OS sandbox on macOS), and `install.mutation.sh` removes each - safety check in turn and requires the tests to fail. + safety check in turn and requires the tests to fail. The install guide and the pages that told readers to + `pip install` now document it. - **The audit trail is complete: every agent's records reach the sink, not only the reviewer's.** Before, only the review exported, so a deployment that turned on `audit.sink` captured the reviewer's decisions but lost the produce side (the developer/council "coding"), the test and documentation agents, and the diff --git a/README.md b/README.md index 9e17cf0..643fa7f 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/i asdd init --goose /path/to/your-repo ``` -The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Before it installs anything it checks the archive's SHA-256, checks that the archive holds one `asdd-X.Y.Z/` tree with no absolute paths, `..` or links, and runs the extracted CLI once to confirm the version. It never overwrites an `asdd` or a directory it did not create, and `sh install.sh uninstall` removes only what it installed. To pin a version in CI, add one step; the installer puts its bin directory on `$GITHUB_PATH` for the steps after it: +The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Before it installs anything it checks the archive's SHA-256, checks that the archive holds one `asdd-X.Y.Z/` tree with no absolute paths, `..` or links, and runs the extracted CLI once to confirm the version. It never overwrites an `asdd` or a directory it did not create, and running the same command with `sh uninstall` at the end removes only what it installed. To pin a version in CI, add one step; the installer puts its bin directory on `$GITHUB_PATH` for the steps after it: ```yaml - run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 diff --git a/cli/README.md b/cli/README.md index acb9d82..f1b36b6 100644 --- a/cli/README.md +++ b/cli/README.md @@ -3,7 +3,9 @@ ## asdd (the unified CLI) One command for the whole toolkit, so you don't call the scripts by path. It dispatches to the -tools below (which stay the single source of truth). Put it on your PATH by symlinking the launcher +tools below (which stay the single source of truth). To install a release, use the one-line installer +(`sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)"`; see the +[install guide](../docs/guides/deploy.md#2-scaffold-asdd-into-your-repo)). From a checkout, put it on your PATH by symlinking the launcher (`ln -s "$PWD/asdd_cli.py" ~/.local/bin/asdd`; it resolves the symlink to find the tools) or, with a recent pip, `pip install -e .`. Or run it straight from a checkout: `python3 asdd_cli.py `. See the [Goose quickstart](../docs/guides/operate-goose.md) for the end-to-end setup. diff --git a/docs/guides/adopt-govern.md b/docs/guides/adopt-govern.md index f496b82..9244c89 100644 --- a/docs/guides/adopt-govern.md +++ b/docs/guides/adopt-govern.md @@ -9,11 +9,12 @@ covered by [operate-goose](operate-goose.md) and [operate-other](operate-other.m Install the CLI, then scaffold your repo: ```bash -pip install git+https://github.com/OneHillAI/ASDD +sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" asdd init /path/to/your-repo ``` -Or run `bash cli/init.sh /path/to/your-repo` from a checkout. +To pin the version in CI, see [Install in CI](deploy.md#install-in-ci). Or run +`bash cli/init.sh /path/to/your-repo` from a checkout. It writes [`AGENTS.md`](https://github.com/OneHillAI/ASDD/blob/main/AGENTS.md) (the constitution), `.asdd.yml` (config), the PR template (the disclosure block), and `CODEOWNERS` from your protected paths, and ensures the lane labels. Add `--goose` diff --git a/docs/guides/deploy.md b/docs/guides/deploy.md index fdd5fde..d057668 100644 --- a/docs/guides/deploy.md +++ b/docs/guides/deploy.md @@ -51,11 +51,39 @@ The ASDD recipes are provider-neutral; you set the model per run. See Install the CLI, then scaffold your repo: ```bash -pip install git+https://github.com/OneHillAI/ASDD +sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" asdd init --goose /path/to/your-repo ``` -Or run `bash cli/init.sh --goose /path/to/your-repo` from a checkout. +The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Flags go after the +command: `--version X.Y.Z` pins a release, and `--prefix DIR` and `--bin-dir DIR` change those two locations, for +example `sh -c "$(curl -fsSL ...)" sh --prefix DIR`. To remove it, run the same command with `sh uninstall` at the +end; it removes what it installed and nothing else. + +### Install in CI + +Pin a version so a pipeline never changes under you. The installer adds its bin directory to `$GITHUB_PATH`, so +the steps after it can call `asdd`: + +```yaml +- run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 +- run: asdd doctor +``` + +### What the installer checks + +Before it installs anything it downloads the release archive and its SHA-256 and stops if they differ. It also +stops if the archive holds anything but one `asdd-X.Y.Z/` tree, if a path is absolute or contains `..`, or if the +archive contains links. It then runs the extracted CLI once and stops unless it reports the version you asked for. +It never overwrites an `asdd` launcher or a directory it did not create, never edits your shell profile, and never +uses `sudo`. + +The checksum and the archive come from the same release, so the checksum catches a corrupted or swapped download +but does not prove who published it. Pin a version, and read +[`install.sh`](https://github.com/OneHillAI/ASDD/blob/main/install.sh) first if you want to be sure what it does. + +To skip the installer, `pip install git+https://github.com/OneHillAI/ASDD` works, or run +`bash cli/init.sh --goose /path/to/your-repo` from a checkout. This writes the constitution (`AGENTS.md`) and a pointer to it for the common assistants (`CLAUDE.md`, `.cursor/rules/asdd.mdc`; Codex reads `AGENTS.md` directly), `.asdd.yml`, the PR template and `CODEOWNERS`, diff --git a/docs/guides/operate-goose.md b/docs/guides/operate-goose.md index e9ab57a..78a25c2 100644 --- a/docs/guides/operate-goose.md +++ b/docs/guides/operate-goose.md @@ -16,7 +16,14 @@ Zero to a governed agentic-dev loop. You need Python 3.9+ and [Goose](https://bl ## 1. Get the CLI on your PATH -Clone ASDD, then either symlink the launcher (pip-free) or install it: +The quickest route is the one-line installer; it puts a pinned, checksum-verified release on your PATH +(see [the install guide](deploy.md#2-scaffold-asdd-into-your-repo)): + +```bash +sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" +``` + +To work from a checkout instead, clone ASDD, then either symlink the launcher (pip-free) or install it: ```bash ln -s "$PWD/asdd_cli.py" ~/.local/bin/asdd # pip-free; or, with a recent pip: pip install -e . diff --git a/docs/guides/slash-commands.md b/docs/guides/slash-commands.md index 58188cb..f9ccd51 100644 --- a/docs/guides/slash-commands.md +++ b/docs/guides/slash-commands.md @@ -30,8 +30,9 @@ feedback loop over the identical code, not a preview of it. Each command is a short Markdown prompt whose only job is to invoke a CLI subcommand and read back its output. To bring your assistant of choice: -1. Install the CLI: `pip install git+https://github.com/OneHillAI/ASDD` (or `pip install .` from a - checkout; the wheel is self-contained). +1. Install the CLI: `sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)"` (see [the install guide](deploy.md#2-scaffold-asdd-into-your-repo)), + or `pip install git+https://github.com/OneHillAI/ASDD`, or `pip install .` from a checkout (the wheel is + self-contained). 2. Copy the four prompts from [`.claude/commands/asdd/`](../../.claude/commands/asdd/) into your assistant's command format. The bodies are plain instructions; only the file location and front matter are Claude-Code-specific. diff --git a/docs/specs/one-line-install.md b/docs/specs/one-line-install.md index c2c2049..5d15121 100644 --- a/docs/specs/one-line-install.md +++ b/docs/specs/one-line-install.md @@ -26,7 +26,8 @@ on. - `install.sh` (POSIX `sh`), its test `install.test.sh`, and a mutation check `install.mutation.sh`. - `.github/workflows/release.yml` and `.github/workflows/install-test.yml`. -- The README quick start and a changelog entry. +- The README quick start, the install guide (`docs/guides/deploy.md`) and the pages that tell a reader how to + install the CLI (`adopt-govern`, `slash-commands`, `operate-goose`, `cli/README.md`), and a changelog entry. ## Out of scope From c74c32b2d5b4e46240768f5080b72d7e6978f153 Mon Sep 17 00:00:00 2001 From: claude-code Date: Thu, 22 Oct 2026 09:49:55 +0200 Subject: [PATCH 2/3] chore(release): prepare 0.2.0 so the one-line install has a release to download The documented install URL points at releases/latest/download/install.sh, which 404s until a release ships it; the latest release is 0.1.0 and predates the installer. Set asdd_cli.py, pyproject.toml and the MCP serverInfo to 0.2.0, cut the changelog section, and use 0.2.0 in the pinned-version examples. Pushing tag v0.2.0 runs release.yml, which checks the tag against these versions, installs from the archive it builds, then publishes the archive, its SHA-256 and install.sh. Signed-off-by: claude-code Agent: claude-code (Sonnet 5.5) (automated, instructed-by: welsbach) Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 3 +++ README.md | 2 +- asdd_cli.py | 2 +- cli/asdd-mcp.py | 2 +- docs/guides/deploy.md | 2 +- install.sh | 8 ++++---- pyproject.toml | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8169305..b970a71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ draft, so pin a conformance claim to a commit or date. ## [Unreleased] +## [0.2.0] - 2026-10-22 + ### Added - **A one-line install for the `asdd` CLI.** `sh -c "$(curl -fsSL .../releases/latest/download/install.sh)"` (add `sh --version X.Y.Z` after it to pin, in CI) downloads a release archive, verifies its SHA-256, checks that it holds @@ -155,4 +157,5 @@ Initial public release. runtime does and records each run). The tester never runs automatically on an untrusted open PR. - Optional profiles: **Assure** (integrity attestation) and the **spec-driven** profile. +[0.2.0]: https://github.com/OneHillAI/ASDD/releases/tag/v0.2.0 [0.1.0]: https://github.com/OneHillAI/ASDD/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 643fa7f..586eafd 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ asdd init --goose /path/to/your-repo The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Before it installs anything it checks the archive's SHA-256, checks that the archive holds one `asdd-X.Y.Z/` tree with no absolute paths, `..` or links, and runs the extracted CLI once to confirm the version. It never overwrites an `asdd` or a directory it did not create, and running the same command with `sh uninstall` at the end removes only what it installed. To pin a version in CI, add one step; the installer puts its bin directory on `$GITHUB_PATH` for the steps after it: ```yaml -- run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 +- run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 - run: asdd doctor ``` diff --git a/asdd_cli.py b/asdd_cli.py index 2671321..a015eff 100755 --- a/asdd_cli.py +++ b/asdd_cli.py @@ -15,7 +15,7 @@ import subprocess import sys -__version__ = "0.1.0" # keep in sync with pyproject.toml +__version__ = "0.2.0" # keep in sync with pyproject.toml HERE = os.path.dirname(os.path.realpath(__file__)) # realpath: a symlink resolves to the checkout diff --git a/cli/asdd-mcp.py b/cli/asdd-mcp.py index 3096e5a..973d84f 100755 --- a/cli/asdd-mcp.py +++ b/cli/asdd-mcp.py @@ -193,7 +193,7 @@ def main(): if method == "initialize": result = {"protocolVersion": msg.get("params", {}).get("protocolVersion", "2025-06-18"), "capabilities": {"tools": {}}, - "serverInfo": {"name": "asdd-gates", "version": "0.1.0"}} + "serverInfo": {"name": "asdd-gates", "version": "0.2.0"}} elif method == "notifications/initialized": continue elif method == "ping": diff --git a/docs/guides/deploy.md b/docs/guides/deploy.md index d057668..dd6419c 100644 --- a/docs/guides/deploy.md +++ b/docs/guides/deploy.md @@ -66,7 +66,7 @@ Pin a version so a pipeline never changes under you. The installer adds its bin the steps after it can call `asdd`: ```yaml -- run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 +- run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 - run: asdd doctor ``` diff --git a/install.sh b/install.sh index c088a37..bfec910 100755 --- a/install.sh +++ b/install.sh @@ -2,12 +2,12 @@ # ASDD installer: one line puts the `asdd` CLI on a developer machine or a CI runner. # # sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" -# sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 +# sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 # sh install.sh uninstall # # In GitHub Actions, add one step before anything that calls `asdd`; the installer puts its bin dir on # $GITHUB_PATH for you: -# - run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.1.0 +# - run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 # # What it does: downloads a release archive, verifies its SHA-256, checks the archive holds nothing but one # `asdd-X.Y.Z/` tree (no absolute paths, no `..`, no links), runs the extracted CLI once to confirm it is the @@ -239,7 +239,7 @@ main() { case "$1" in --version) [ $# -ge 2 ] && [ -n "$2" ] || die "--version needs a value (a release version, X.Y.Z)" VERSION=${2#v} - [ -n "$VERSION" ] || die "'$2' is not a release version (expected X.Y.Z, for example 0.1.0)" + [ -n "$VERSION" ] || die "'$2' is not a release version (expected X.Y.Z, for example 0.2.0)" shift 2 ;; --prefix) [ $# -ge 2 ] && [ -n "$2" ] || die "--prefix needs a directory"; PREFIX=$2; shift 2 ;; --bin-dir) [ $# -ge 2 ] && [ -n "$2" ] || die "--bin-dir needs a directory"; BIN_DIR=$2; shift 2 ;; @@ -249,7 +249,7 @@ main() { done if [ -n "$VERSION" ]; then - is_release_version "$VERSION" || die "'$VERSION' is not a release version (expected X.Y.Z, for example 0.1.0)" # guard:version + is_release_version "$VERSION" || die "'$VERSION' is not a release version (expected X.Y.Z, for example 0.2.0)" # guard:version fi [ -n "$PREFIX" ] || { [ -n "${HOME:-}" ] || die "HOME is not set; pass --prefix"; PREFIX="$HOME/.asdd"; } [ -n "$BIN_DIR" ] || { [ -n "${HOME:-}" ] || die "HOME is not set; pass --bin-dir"; BIN_DIR="$HOME/.local/bin"; } diff --git a/pyproject.toml b/pyproject.toml index ffa2ffd..40d86f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ build-backend = "setuptools.build_meta" [project] name = "asdd" -version = "0.1.0" +version = "0.2.0" description = "The ASDD CLI: the deterministic gates, the installer, and the Goose MCP extension under one command" readme = "README.md" requires-python = ">=3.9" From 75c40ab77832929466b8386041ce75ff5f9709c5 Mon Sep 17 00:00:00 2001 From: claude-code Date: Thu, 22 Oct 2026 09:54:27 +0200 Subject: [PATCH 3/3] docs(install): address review notes on the install docs Spell out the full URL in the --prefix example instead of a '...' placeholder that would not paste, show both uninstall forms in install.sh's header (saved copy and one-liner), and trim the README's list of installer checks to a link to the install guide so the two do not drift. Signed-off-by: claude-code Agent: claude-code (Sonnet 5.5) (automated, instructed-by: welsbach) Co-Authored-By: Claude Sonnet 5.5 --- README.md | 2 +- docs/guides/deploy.md | 4 ++-- install.sh | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 586eafd..231d4f0 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/i asdd init --goose /path/to/your-repo ``` -The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Before it installs anything it checks the archive's SHA-256, checks that the archive holds one `asdd-X.Y.Z/` tree with no absolute paths, `..` or links, and runs the extracted CLI once to confirm the version. It never overwrites an `asdd` or a directory it did not create, and running the same command with `sh uninstall` at the end removes only what it installed. To pin a version in CI, add one step; the installer puts its bin directory on `$GITHUB_PATH` for the steps after it: +The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. It checks the archive's SHA-256 and layout before installing anything, never overwrites an `asdd` or a directory it did not create, and running the same command with `sh uninstall` at the end removes only what it installed. The [install guide](docs/guides/deploy.md#2-scaffold-asdd-into-your-repo) lists every check. To pin a version in CI, add one step; the installer puts its bin directory on `$GITHUB_PATH` for the steps after it: ```yaml - run: sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 diff --git a/docs/guides/deploy.md b/docs/guides/deploy.md index dd6419c..bdca025 100644 --- a/docs/guides/deploy.md +++ b/docs/guides/deploy.md @@ -57,8 +57,8 @@ asdd init --goose /path/to/your-repo The installer puts `asdd` in `~/.local/bin` and keeps each version under `~/.asdd/versions/`. Flags go after the command: `--version X.Y.Z` pins a release, and `--prefix DIR` and `--bin-dir DIR` change those two locations, for -example `sh -c "$(curl -fsSL ...)" sh --prefix DIR`. To remove it, run the same command with `sh uninstall` at the -end; it removes what it installed and nothing else. +example `sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --prefix DIR`. To remove it, run the same command with `sh uninstall` +at the end; it removes what it installed and nothing else. ### Install in CI diff --git a/install.sh b/install.sh index bfec910..473e22d 100755 --- a/install.sh +++ b/install.sh @@ -3,7 +3,8 @@ # # sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" # sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0 -# sh install.sh uninstall +# sh install.sh uninstall (from a saved copy of this file) +# sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh uninstall (without one) # # In GitHub Actions, add one step before anything that calls `asdd`; the installer puts its bin dir on # $GITHUB_PATH for you: