ic-memory 0.26.1

Durable stable-memory allocation governance for Internet Computer canisters
Documentation
<p align="center">
  <img src="https://raw.githubusercontent.com/dragginzgame/shared-assets/main/ic-memory/ic-memory-readme-header.svg" alt="IC Memory — Stops upgrades from mixing up stored data" width="100%">
</p>

# Releasing ic-memory

This guide is for maintainers. The maintainer owns all commits, tags and pushes.
Agents leave source, documentation and focused checks unstaged and uncommitted;
see [AGENTS.md](AGENTS.md). The Rust `repo-tool` example is development tooling,
not canister runtime code. Prerequisites and native host evidence are in
[host support](docs/host-support.md).

## Source and dependency preparation

Before 1.0, breaking consumer contracts require a minor release; compatible work
uses a patch. Maintain one numbered, undated pending entry, `## [X.Y.Z]`, in both
`CHANGELOG.md` and `docs/changelog/<major>.<minor>.md`. Notes select the candidate
without changing package versions. Preparation refuses mismatched or duplicate
identities and preserves historical entries.

The maintainer commits implementation and pending notes before releasing. The
selected source must be clean, on the selected branch, with no active build.
Select dependencies explicitly in a fresh checkout and prepare their cache:

```sh
cargo generate-lockfile # Fresh checkout only; preserve an existing selection.
make fetch-dependencies
```

The untracked `Cargo.lock` is a required qualification input. Release preflight
checks the selected cache with `cargo fetch --locked --offline`; it never retries
online or regenerates the lockfile. Validation, version refresh and packaging
remain offline. A root-version refresh may change only the `ic-memory` entry,
never dependency selection. Cache preparation is a separate network operation.

## Maintainer commands and recovery

```sh
make release-patch
make release-minor
make release-major
# Defaults: RELEASE_REMOTE=origin RELEASE_BRANCH=main
```

All three delegate to the unchanged vendored Shared Tooling runner. It owns
preflight, the full gate, exact preparation, explicit staging, the `Release X.Y.Z`
commit, annotated `vX.Y.Z` tag and atomic branch/tag push. All kinds use the same
pinned `make validate` gate. The branch must already exist remotely, with its
refreshed remote head an ancestor of local HEAD. Overrides select a remote name
and branch explicitly; the saved push URL identity must remain unchanged.

Rerun the **same normal target** after interruption. Once preparation may start,
the runner selects unfinished intent before computing any new increment. Its
plan and directory lock live in Git's `release-state` directory; the plan fixes
kind, previous/candidate versions, source commit, UTC date, branch and destination.
Matching effects are reconciled without a second bump or commit. Conflicting
source, payload, index, destination, tag or unfinished intent stops recovery.
Inspect a stale lock's recorded owner before manual removal; do not steal it.

Preflight and validation failures restart fresh gates through the normal target,
preserving prior attempts. Optional explicit selection uses the same checks:

```sh
make release-resume VERSION=X.Y.Z
```

Push uses `--no-follow-tags --atomic` and exactly the selected branch and candidate
tag refspecs. There is no force push or non-atomic fallback. A lost push reply is
reconciled with exact remote identities; a failed remote query stops recovery.
Success retains plans, logs, receipts and archives. Cleanup and package
publication are separate operations.

The Rust consumer adapters consume the runner's seven `RELEASE_*` selections.
They validate source/input identities, finalize the root and detail notes with
the saved UTC date, update Cargo/README metadata and qualify the packages. The
explicit staged file set is `Cargo.toml`, `README.md`, `CHANGELOG.md` and the
candidate minor-line detail file. The ignored lockfile is evidence, not a staged
release file. Git mutations belong exclusively to the common runner.

Metadata writes use same-directory atomic replacement, with `Cargo.toml` last.
An interrupted earlier write can resume from exact original/prepared files. Once
the candidate manifest is present, prepared checks can finish lock refresh and
packaging from saved successful validation, without another bump or full gate.
Returned preparation failures restore only owned edits; conflicting files and
independently changed dependency selections are preserved and refused.

`release-version`, `release-files` and the other named adapters are runner
interfaces, not alternative maintainer orchestration. They require the saved
selection and evidence where applicable. `make qualify-release` can finish final
package qualification without Git effects, using the original prepared evidence.

## Evidence and publication

Under Cargo's actual target directory (including configured overrides),
`release-validation/` contains:

- `<version>-validated.json`: successful full-gate source, saved selection,
  original lock bytes, toolchain identities, configuration and exact command.
- `<version>-prepared.json`: that validation plus refreshed lock digest and the
  package qualified before the release commit.
- `<version>.json`: final package bound to the exact release commit. Cargo embeds
  Git metadata, so final packaging follows commit creation.
- `artifacts/<sha256>.crate`: retained qualified archives independent of Cargo's
  replaceable working package path.
- `attempts/verify.*`: unique stdout/stderr logs, including failed full gates.
  Replaced successful validation receipts are also archived here before replacement.

Receipts are written atomically. Existing prepared/final receipts and archives
are checked, never silently repaired. Missing/corrupted prepared evidence stops
final qualification before packaging; a working archive replaced by failed final
packaging does not invalidate its intact retained prepared archive. Completed
prepared/final checks reuse valid evidence without repackaging.

Compiler identities include pinned Cargo/rustc and MSRV rustc. Discovered Cargo
configuration digests and build flags/profile overrides are recorded. Qualification
rejects compiler/wrapper replacements: `RUSTC`, `RUSTC_WRAPPER`,
`RUSTC_WORKSPACE_WRAPPER`, `RUSTDOC`, their `CARGO_BUILD_*` aliases and corresponding
`build` keys in checkout, ancestor and Cargo-home configuration. Unset even empty
assignments. Ordinary recorded flags/profile settings remain supported.

The current receipt schema is a hard cut from the earlier phase workflow. Old
receipts are not accepted or migrated. Finish outstanding earlier releases with
their original tooling before adopting this workflow. Preserve old evidence;
there is no automatic deletion or conversion of it or canister stable data.

```sh
make publish-dry-run
make publish # Separate network effect; requires crates.io credentials.
```

`PUBLISH_DRY_RUN=1 make publish` also selects a dry run. Publication requires the
exact commit, annotated tag, selected dependencies and qualified archive; it
never creates replacement evidence. A fresh checkout alone is not qualification.
If publication is interrupted, inspect crates.io's exact version before retrying;
a lost reply is not proof of failure. Release targets never publish implicitly.

## Focused workflow checks

- `make test-tooling`: Rust adapters with substituted Git/Cargo/gate effects;
  recovery, rollback, input binding, artifact refusal and publication checks.
- `make test-release-adapters`: actual consumer Make recipes with substituted
  helper/runner; all entry points, selection forwarding and unique gate logs.
- `make test-release-runner`: unchanged canonical runner with command substitutes;
  ordering, all increments, Git effect scope, locks and interruption reconciliation.
- `make verify-shared-tooling`, `make test-hooks`, `make fmt-check` and
  `make lint-tooling`: snapshot, setup/formatting and portable tooling checks.

These tests create no commits/tags/pushes and perform no publication or full gate.
They do not prove a live release or native macOS behavior. The declared native CI
matrix includes them in `make validate-toolchain`. Full gates (`make validate`,
`make validate-toolchain`, `make wasm-size`, package qualification) run only on
explicit request or in configured CI. Current focused evidence is recorded in
[release workflow qualification](docs/release-workflow-qualification.md).