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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -15,7 +17,8 @@ draft, so pin a conformance claim to a commit or date.
`<prefix>/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
Expand Down Expand Up @@ -154,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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ 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/`. 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.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
```

Expand Down
2 changes: 1 addition & 1 deletion asdd_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <command>`.
See the [Goose quickstart](../docs/guides/operate-goose.md) for the end-to-end setup.
Expand Down
2 changes: 1 addition & 1 deletion cli/asdd-mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/adopt-govern.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
32 changes: 30 additions & 2 deletions docs/guides/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 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

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.2.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`,
Expand Down
9 changes: 8 additions & 1 deletion docs/guides/operate-goose.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 .
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/slash-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion docs/specs/one-line-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 6 additions & 5 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
# 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 install.sh uninstall
# sh -c "$(curl -fsSL https://github.com/OneHillAI/ASDD/releases/latest/download/install.sh)" sh --version 0.2.0
# 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:
# - 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
Expand Down Expand Up @@ -239,7 +240,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 ;;
Expand All @@ -249,7 +250,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"; }
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading