diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7541165..76eb66c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,3 +42,14 @@ jobs: - name: The docs are wrapped to their own convention # fixtures/ is excluded: those files are test input, and their bytes are the test. run: python3 scripts/reflow-docs.py --check $(git ls-files '*.md' ':!fixtures/*') + + # Packaging gate: catches missing files, bad manifest metadata, and lockfile + # drift before a real crates.io publish. Needs no token. + publish-dry-run: + name: cargo publish --dry-run + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Package as crates.io would + run: cargo publish --dry-run --locked diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f002a8..00a6e7b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,14 @@ name: release on: push: tags: ['v*'] + # crates.io is intentional and manual until one publish has landed. Tags cut + # GitHub release assets only; they do not surprise-publish to the registry. + workflow_dispatch: + inputs: + publish_crates_io: + description: 'Publish this ref to crates.io as clank-cli-app (manual gate)' + type: boolean + default: false permissions: contents: write @@ -20,6 +28,7 @@ permissions: jobs: draft: name: draft the release + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -105,3 +114,31 @@ jobs: run: | gh release edit "$GITHUB_REF_NAME" --draft=false --latest gh release view "$GITHUB_REF_NAME" --json assets --jq '.assets[].name' + + # Manual only. After one successful dispatch publish, tag→crates.io can be + # wired; until then a v* tag must not publish the renamed package by surprise. + crates-io: + name: crates.io + if: github.event_name == 'workflow_dispatch' && inputs.publish_crates_io + runs-on: ubuntu-latest + environment: crates-io + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + + - name: The tag (when present) names the version in Cargo.toml + if: startsWith(github.ref, 'refs/tags/v') + run: | + version=$(cargo metadata --no-deps --format-version 1 \ + | python3 -c 'import json,sys; print(json.load(sys.stdin)["packages"][0]["version"])') + if [ "v$version" != "$GITHUB_REF_NAME" ]; then + echo "tag $GITHUB_REF_NAME does not name Cargo.toml's version $version" >&2 + exit 1 + fi + echo "tag and manifest agree on $version" + + - name: Publish to crates.io + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish --locked diff --git a/CHEATSHEET.md b/CHEATSHEET.md index d09fa9f..5939161 100644 --- a/CHEATSHEET.md +++ b/CHEATSHEET.md @@ -14,6 +14,16 @@ context is exactly what was piped. Set `CLANK_BASE_URL` and `CLANK_MODEL` (flags override `$CLANK_*`). Do not rely on a laptop-only built-in default — point at your OpenAI-compatible server. + +## Install + +```sh +cargo install clank-cli-app --locked # package name; runs as clank / clank-jev +# fallback: cargo install --locked --git https://github.com/makefunstuff/clank --tag v0.1.0 +``` + +Never `cargo install clank` (unrelated crates.io crate). + ## Contract | stream | carries | diff --git a/Cargo.lock b/Cargo.lock index 293d4db..8b259e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] -name = "clank" +name = "clank-cli-app" version = "0.1.0" dependencies = [ "clap", diff --git a/Cargo.toml b/Cargo.toml index f45c543..f89aea0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [package] -name = "clank" +name = "clank-cli-app" version = "0.1.0" edition = "2021" license = "MIT" repository = "https://github.com/makefunstuff/clank" description = "Minimal unix-style local-inference harness: stdin/stdout CLI with read-only filesystem tools" +readme = "README.md" [[bin]] name = "clank" diff --git a/README.md b/README.md index 7bb892b..e9a2413 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,14 @@ context, `--each`, schema through `jq`, failure with reason and `exit 1`. ## Install -Not on crates.io: the crate named `clank` there is an unrelated project. Two -binaries, `clank` and its decision-stage sibling `clank-jev`, six direct -dependencies, and nothing system-provided beyond a C compiler (`ring`, for TLS; -no OpenSSL to find). +**Install line 1:** package `clank-cli-app` → binaries `clank` and `clank-jev` +(package ≠ binary). The crates.io crate named `clank` is unrelated — never +`cargo install clank`. Six direct dependencies, and nothing system-provided +beyond a C compiler (`ring`, for TLS; no OpenSSL to find). + +```sh +cargo install clank-cli-app --locked # -> ~/.cargo/bin/clank and clank-jev +``` Prebuilt archives are attached to each [release](https://github.com/makefunstuff/clank/releases) — linux x86_64, macOS @@ -45,13 +49,14 @@ sha256sum -c clank-*.tar.gz.sha256 # macOS: shasum -a 256 -c tar xzf clank-*.tar.gz ``` -From source, which is what you want if you are wiring it into something else: +Until the first crates.io publish (manual Actions dispatch with +`publish_crates_io` — not auto on tag), or as a pinable fallback: ```sh -cargo install --locked --git https://github.com/makefunstuff/clank # -> ~/.cargo/bin/clank +cargo install --locked --git https://github.com/makefunstuff/clank --tag v0.1.0 ``` -`--locked` holds the dependency graph to the committed `Cargo.lock`; +`--locked` holds the dependency graph to the committed `Cargo.lock`; `--tag` / `--rev ` pins clank itself. That directory is on `PATH` if you have installed anything with cargo before. From a checkout instead — `src/` is 2.8k lines: diff --git a/STATUS.md b/STATUS.md index 1e3d50b..e80557e 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,6 +1,6 @@ # clank — status -Project log, last written 2026-09-20. The contract is +Project log, last written 2026-09-22. The contract is [PROTOCOL.md](PROTOCOL.md); the reference is [README.md](README.md); the dated evidence is [docs/history/verification-log.md](docs/history/verification-log.md). This file @@ -18,9 +18,11 @@ says where the project is, what is open, and how to check any of it. floor cannot yet be set just above it. Re-run with `:Jev inspect` after a rules edit, or `jev inspect --force` with `JEV_DECIDE_BASE_URL` pointed at a local `kev`. -2. **The repository has not been released.** No tag exists, so the release - workflow's Actions plumbing is unexercised; only its shell has been run, - locally. The first `git tag v0.1.0 && git push origin v0.1.0` is the test. +2. **crates.io publish is gated, not automatic yet.** GitHub release `v0.1.0` is + out. The package is renamed to `clank-cli-app` (binaries stay `clank` / + `clank-jev`). CI dry-runs `cargo publish --locked` on every PR; a real + publish is `workflow_dispatch` only until one manual publish has landed — do + not trust auto tag→crates.io on the first renamed tag. 3. **Whether to keep the 2026-09-20 splits**: `docs/clank-jev.md` (out of README) and `docs/history/` (closed records). Both are reversible with `git mv`. @@ -59,11 +61,15 @@ says where the project is, what is open, and how to check any of it. network. `tests/wire.rs` (24, the protocol), `tests/jev.rs` (10, the sibling), `tests/docs.rs` (6, docs vs code), `tests/rules.rs` (3, the rules themselves), plus 38 unit tests in `src/`. +- Package name on crates.io is `clank-cli-app`; the installed binaries remain + `clank` and `clank-jev`. Install: `cargo install clank-cli-app --locked`. - CI on every push and pull request: warnings are errors, `cargo test` (including `tests/jev_ci_stub.rs`, which drives `clank-jev` against a local - stub — no secret and no provider), and the docs wrapping check. Release on a - `v*` tag: three native targets, each archive smoke-tested before it is - attached, published only when all of them are up. + stub — no secret and no provider), the docs wrapping check, and + `cargo publish --dry-run --locked`. Release on a `v*` tag: three native + targets, each archive smoke-tested before it is attached, published only when + all of them are up. crates.io is a separate manual `workflow_dispatch` until + that path has been exercised once. - `.jev/rules/` holds 26 rules, in three groups: the contract's invariants, the taste the code is held to (weightless code, needless abstraction, avoidable copies, silent fallbacks, a value with two homes, comments that restate the