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
5 changes: 2 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ environment or in a repo-root `.env` (`pip install -r scripts/requirements-dev.t

The system prompt lives in `ai/prompts/repository-rules-review.md`. Two
deterministic checks run before the LLM and independently of it: secret-shaped
text in added lines blocks the upload entirely, and the **Retired Crate Freeze**
rejects source changes in the crates retired by
[#199](https://github.com/tensor4all/strided-rs/issues/199).
text in added lines blocks the upload entirely, and the **Deprecated Tree
Freeze** rejects source changes under `deprecated/`.

Maintainer escape hatches, both requiring the `maintain`/`admin` role and
reapplication after the latest push:
Expand Down
20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ members = [
resolver = "2"

[workspace.package]
version = "0.3.0"
version = "0.4.0"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["Satoshi Terasaki", "Hiroshi Shinaoka"]
repository = "https://github.com/tensor4all/strided-rs"

[workspace.dependencies]
strided-rs = { version = "0.3.0", path = "strided-rs" }
strided-traits = { version = "0.3.0", path = "strided-traits" }
strided-view = { version = "0.3.0", path = "strided-view" }
strided-perm = { version = "0.3.0", path = "strided-perm" }
strided-kernel = { version = "0.3.0", path = "strided-kernel" }
strided-einsum2 = { version = "0.3.0", path = "strided-einsum2", default-features = false }
strided-opteinsum = { version = "0.3.0", path = "strided-opteinsum", default-features = false }
mdarray-opteinsum = { version = "0.3.0", path = "mdarray-opteinsum", default-features = false }
ndarray-opteinsum = { version = "0.3.0", path = "ndarray-opteinsum", default-features = false }
strided-rs = { version = "0.4.0", path = "strided-rs" }
strided-traits = { version = "0.4.0", path = "strided-traits" }
strided-view = { version = "0.4.0", path = "strided-view" }
strided-perm = { version = "0.4.0", path = "strided-perm" }
strided-kernel = { version = "0.4.0", path = "strided-kernel" }
strided-einsum2 = { version = "0.4.0", path = "strided-einsum2", default-features = false }
strided-opteinsum = { version = "0.4.0", path = "strided-opteinsum", default-features = false }
mdarray-opteinsum = { version = "0.4.0", path = "mdarray-opteinsum", default-features = false }
ndarray-opteinsum = { version = "0.4.0", path = "ndarray-opteinsum", default-features = false }

approx = "0.5"
cblas-inject = "0.1.2"
Expand Down
15 changes: 3 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ It is inspired by Julia's [Strided.jl](https://github.com/Jutho/Strided.jl),
The recommended user-facing crate is [`strided-rs`](strided-rs/README.md).
Use individual crates such as `strided-perm`, `strided-view`, or
`strided-kernel` directly when you need a smaller dependency surface or a
lower-level API.
lower-level API. All nine workspace crates listed below are maintained.

## Workspace Layout

Expand All @@ -33,20 +33,11 @@ lower-level API.

## Installation

These crates are being prepared for crates.io publication, but this repository
does not publish them automatically. Until a release is published, use workspace
path dependencies:
Add the facade crate from crates.io:

```toml
[dependencies]
strided-rs = { path = "../strided-rs/strided-rs" }
```

After publication, use:

```toml
[dependencies]
strided-rs = "0.1"
strided-rs = "0.4"
```

## Documentation
Expand Down
22 changes: 13 additions & 9 deletions REPOSITORY_RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
These rules are adapted from `tenferro-rs/REPOSITORY_RULES.md` for the current
strided-rs workspace. Apply them in addition to the shared tensor4all rules.

## Retired Crate Freeze

- `strided-einsum2`, `strided-opteinsum`, `mdarray-opteinsum`,
`ndarray-opteinsum`, and everything under `deprecated/` are retired per
[#199](https://github.com/tensor4all/strided-rs/issues/199). Contraction is
owned by tenferro (`tenferro-einsum` plans, `tenferro-cpu` executes).
- Do not land new features, refactors, or performance work in the retired
crates. Only fixes that protect the current tenferro pin belong here, and
only when the tenferro-side absorption cannot deliver them first.
## Einsum Maintenance Ownership

- `strided-einsum2` is the minimum binary CPU einsum implementation.
- `strided-opteinsum` is its maintained N-ary frontend.
- `mdarray-opteinsum` and `ndarray-opteinsum` remain maintained adapters.

## Deprecated Tree Freeze

- Everything under `deprecated/` remains retired per
[#199](https://github.com/tensor4all/strided-rs/issues/199).
- Do not land new features, refactors, or performance work there. Only fixes
that protect the current tenferro pin belong there, and only when the
tenferro-side absorption cannot deliver them first.
- Deprecation notices are exempt: README banners, crate-level and item-level
doc comments, `#[deprecated]` attributes, and `Cargo.toml` metadata may
change freely.
Expand Down
209 changes: 209 additions & 0 deletions ai/contribution-workflows/release-publish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# Publishing a strided-rs release

Publish only a commit that has already landed on `main`. The release tag must
identify that exact commit, and every crate must be published from a clean
checkout of the tag.

## 1. Prepare and validate `main`

Complete all version and dependency changes in a reviewed commit before the
release. Do not edit manifests while publishing: crates.io must receive the
same manifests recorded by the tag.

```bash
set -euo pipefail

git switch main
git pull --ff-only origin main
cargo fmt --all -- --check
cargo test --workspace
```

Confirm all nine package file lists contain their license and provenance files:

```bash
set -euo pipefail

for crate in \
strided-traits strided-view strided-perm strided-kernel \
strided-einsum2 strided-opteinsum mdarray-opteinsum \
ndarray-opteinsum strided-rs
do
package_files=$(cargo package -p "$crate" --list)
printf '%s\n' "$package_files"
for required in LICENSE-APACHE LICENSE-MIT NOTICE; do
grep -Fxq "$required" <<<"$package_files"
done
case "$crate" in
strided-traits|strided-view|strided-perm|strided-kernel)
grep -Fxq THIRD-PARTY-LICENSES <<<"$package_files"
;;
*)
if grep -Fxq THIRD-PARTY-LICENSES <<<"$package_files"; then
echo "unexpected THIRD-PARTY-LICENSES in $crate" >&2
exit 1
fi
;;
esac
done
```

Every package must contain `LICENSE-APACHE`, `LICENSE-MIT`, and its
package-specific `NOTICE`. Only `strided-traits`, `strided-view`,
`strided-kernel`, and `strided-perm` contain ported or license-derived code, so
only those archives contain `THIRD-PARTY-LICENSES`.

## 2. Tag before publishing

Push the validated `main` commit before creating and pushing the release tag.
Replace `0.4.0` below for later releases.

```bash
set -euo pipefail

git push origin main
release_sha=$(git rev-parse HEAD)
test "$(git ls-remote origin refs/heads/main | cut -f1)" = "$release_sha"

# Wait for the required CI workflow triggered by this exact pushed commit.
run_id=
for attempt in {1..30}; do
run_id=$(gh run list --workflow ci.yml --branch main --event push \
--commit "$release_sha" --limit 1 --json databaseId --jq '.[0].databaseId // empty')
test -z "$run_id" || break
sleep 10
done
test -n "$run_id"
gh run watch "$run_id" --exit-status
test "$(gh run view "$run_id" --json headSha --jq .headSha)" = "$release_sha"
test "$(gh run view "$run_id" --json conclusion --jq .conclusion)" = success

git tag -a v0.4.0 "$release_sha" -m "strided-rs v0.4.0"
git push origin v0.4.0
git switch --detach v0.4.0
test -z "$(git status --porcelain)"
```

The detached tag checkout is the publication source. Do not create all nine
archives at once: Cargo cannot package a crate whose v0.4 workspace
prerequisites are not yet available from crates.io.

## 3. Package, inspect, and publish in dependency order

Process one crate completely before starting the next, in this exact order:

1. `strided-traits`
2. `strided-view`
3. `strided-perm`
4. `strided-kernel`
5. `strided-einsum2`
6. `strided-opteinsum`
7. `mdarray-opteinsum`
8. `ndarray-opteinsum`
9. `strided-rs`

The adapters occupy the same dependency layer and may be processed in either
order. For every crate, first query crates.io for the exact version. An absent
version is packaged, inspected, dry-run, published, and awaited. An existing
version is skipped only after its registry archive passes the same provenance
checks. Thus every prerequisite is registry-visible before Cargo packages a
dependent crate, and the first new archive is fully inspected before the first
irreversible publish.

```bash
set -euo pipefail

version=0.4.0
expected=$(git rev-parse HEAD)
test "$(git describe --exact-match --tags HEAD)" = "v$version"

download_dir=$(mktemp -d)
trap 'rm -rf "$download_dir"' EXIT

verify_archive() {
local crate=$1 archive=$2 prefix="${1}-${version}"
local vcs_info actual dirty archive_files

vcs_info=$(tar -xOf "$archive" "$prefix/.cargo_vcs_info.json")
actual=$(printf '%s' "$vcs_info" | python3 -c 'import json, sys; print(json.load(sys.stdin)["git"]["sha1"])')
dirty=$(printf '%s' "$vcs_info" | python3 -c 'import json, sys; print(str(json.load(sys.stdin)["git"].get("dirty", False)).lower())')
test "$actual" = "$expected"
test "$dirty" = false

for required in LICENSE-APACHE LICENSE-MIT NOTICE; do
tar -xOf "$archive" "$prefix/$required" | cmp - "$crate/$required"
done
case "$crate" in
strided-traits|strided-view|strided-perm|strided-kernel)
tar -xOf "$archive" "$prefix/THIRD-PARTY-LICENSES" |
cmp - "$crate/THIRD-PARTY-LICENSES"
;;
*)
archive_files=$(tar -tf "$archive")
if grep -q '/THIRD-PARTY-LICENSES$' <<<"$archive_files"; then
echo "unexpected THIRD-PARTY-LICENSES in $crate" >&2
exit 1
fi
;;
esac
}

for crate in \
strided-traits strided-view strided-perm strided-kernel \
strided-einsum2 strided-opteinsum mdarray-opteinsum \
ndarray-opteinsum strided-rs
do
test -z "$(git status --porcelain)"

registry_archive="$download_dir/${crate}-${version}.crate"
if ! http_status=$(curl --location --silent --show-error \
--user-agent "strided-rs-release/$version" \
--output "$registry_archive" --write-out '%{http_code}' \
"https://crates.io/api/v1/crates/$crate/$version/download"); then
echo "failed to query crates.io for $crate@$version" >&2
exit 1
fi

case "$http_status" in
200)
verify_archive "$crate" "$registry_archive"
echo "$crate@$version already exists and matches tag; skipping"
continue
;;
404)
rm -f "$registry_archive"
;;
*)
echo "unexpected HTTP status $http_status for $crate@$version" >&2
exit 1
;;
esac

cargo package -p "$crate" --no-verify
archive="target/package/${crate}-${version}.crate"
verify_archive "$crate" "$archive"

cargo publish -p "$crate" --dry-run
cargo publish -p "$crate"

visible=false
for attempt in {1..30}; do
if cargo info "$crate@$version"; then
visible=true
break
fi
sleep 10
done
test "$visible" = true
done

test -z "$(git status --porcelain)"
```

The visibility wait is bounded to 30 attempts and retries because registry
indexing is asynchronous. If it expires, rerun the same unchanged block: this
is safe only because every existing version is downloaded and
provenance-verified against the tag before it is skipped. Any network failure,
HTTP result other than 200 or 404, or archive mismatch aborts the release. Do
not edit a manifest, repackage with different metadata, or publish a dependent
early. After the facade is visible, leave the detached checkout unchanged.
10 changes: 6 additions & 4 deletions ai/prompts/repository-rules-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ strided-rs provides dynamic-rank strided views and cache-optimized CPU kernels:
kernel layers are ports of Julia's Strided.jl / StridedViews.jl; the
permutation engine follows HPTT.

`strided-einsum2`, `strided-opteinsum`, `mdarray-opteinsum`,
`ndarray-opteinsum`, and `deprecated/` are retired. Contraction is owned by
tenferro. A deterministic check already reports source changes there, so do not
duplicate that finding; review those diffs only for the rules that still apply.
`strided-einsum2` is the minimum binary CPU einsum implementation, and
`strided-opteinsum` is its maintained N-ary frontend. `mdarray-opteinsum` and
`ndarray-opteinsum` remain maintained adapters. Everything under `deprecated/`
remains retired. A deterministic check already reports source changes under
`deprecated/`, so do not duplicate that finding; review those diffs only for
the rules that still apply.

## Authority

Expand Down
10 changes: 7 additions & 3 deletions docs/PROVENANCE_AND_CITATION_POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ list is best-effort; corrections and additions are welcome.
| Blocked tensor transposition (dimension fusion, macro/micro kernels, recursive loop nest) | `strided-perm` | P. Springer, T. Su, P. Bientinesi, "HPTT: A High-Performance Tensor Transposition C++ Library", [ARRAY 2017](https://doi.org/10.1145/3091966.3091968), [arXiv:1704.04374](https://arxiv.org/abs/1704.04374) |
| Cache-blocked strided map/reduce (dimension fusion, stride-ordered loops, L1 blocking) | `strided-kernel` | Strided.jl has no accompanying paper; cite the [Strided.jl repository](https://github.com/Jutho/Strided.jl) |

License-bearing attributions are declared in `NOTICE` (Strided.jl /
StridedViews.jl, MIT) and `THIRD-PARTY-LICENSES` (HPTT, BSD-3-Clause); the
`strided-perm` crate is licensed as `(MIT OR Apache-2.0) AND BSD-3-Clause`.
Every published crate declares its component-specific lineage in its packaged
`NOTICE`. Crates containing ported or license-derived code also package the
applicable complete upstream license text in `THIRD-PARTY-LICENSES`:
`strided-traits` and `strided-kernel` carry Strided.jl's MIT notice,
`strided-view` carries StridedViews.jl's MIT notice, and `strided-perm` carries
HPTT's BSD-3-Clause notice. The `strided-perm` crate is licensed as
`(MIT OR Apache-2.0) AND BSD-3-Clause`.
2 changes: 2 additions & 0 deletions mdarray-opteinsum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ license.workspace = true
authors.workspace = true
repository.workspace = true
description = "N-ary einsum frontend for mdarray arrays, powered by strided-opteinsum."
keywords = ["tensor", "einsum", "mdarray", "contraction"]
categories = ["science", "mathematics", "algorithms"]

[dependencies]
mdarray.workspace = true
Expand Down
Loading
Loading