agentleFS
fzyzcjyfzyzcjy/torch_memory_saver/.claude/skills/tms-publish-release/SKILL.md

tms-publish-release

Skill279 starsChanged 34 days agoMITView on GitHub

Use when preparing, building, validating, publishing, or verifying torch_memory_saver beta and stable releases across x86_64, aarch64, CUDA 12, and CUDA 13.

  • Deletes or force-pushes
  • Installs packages
  • Commits and pushes

We split this skill into the rules it gives an agent

45 rules. About 0 are common, 30 are distinctive, and 15 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈30

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 15

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use canonical PEP 440 versions in setup.py:

    line 9
  2. Distinctive:

    Never persist PyPI credentials on the GPU host.

    line 20
  3. Distinctive:

    Never create a GitHub Release.

    line 21
  4. Distinctive:

    Treat PyPI upload and Git tag push as irreversible.

    line 22
  5. Distinctive:

    Never reuse a local or remote source or artifact directory, even for the same version and commit.

    line 39
  6. Distinctive:

    Keep every build, validation, environment, and recheck log under the unique artifact directories.

    line 40
  7. Very specific:

    Stop if the tree is dirty, HEAD differs from origin/master, or the release commit is detached.

    line 57
  8. Very specific:

    Read and validate the version without importing setup.py:

    line 58
  9. Very specific:

    Use c29087a58db9d120b3e69623714c5dd043029d77 as the historical source baseline for the first tagged release after 0.0.9.post1.

    line 78
  10. Distinctive:

    Use the previous release tag after the first tagged release.

    line 79
  11. Distinctive:

    Stop if GPU 0 is busy, Docker is unavailable, or the host lacks enough space for the PyTorch builder images.

    line 94
  12. Very specific:

    Never copy it to tom-workstation.

    line 97
  13. Distinctive:

    Never mount it into a long-lived container.

    line 98
  14. Distinctive:

    Check for an existing ARM64 binfmt handler:

    line 103
  15. Distinctive:

    If it is missing, stop for approval before installing QEMU binfmt.

    line 111
  16. Distinctive:

    Treat installation as privileged and host-wide.

    line 112
  17. Very specific:

    Use the pinned tonistiigi/binfmt image.

    line 113
  18. Distinctive:

    After approval, install only ARM64 and verify it with an ARM64 Alpine container:

    line 114
  19. Distinctive:

    Treat binfmt as boot-scoped unless the host has an explicit persistent registration.

    line 126
  20. Distinctive:

    Keep upload and tag creation outside every release script.

    line 137
  21. Distinctive:

    Do not create, query, attach artifacts to, or require a GitHub Release.

    line 138
  22. Very specific:

    Use sdist only for focused diagnostics.

    line 139
  23. Very specific:

    Use artifacts for the canonical release workflow after all three distributions exist.

    line 140
  24. Very specific:

    Do not use rsync --delete.

    line 162
  25. Distinctive:

    Run long commands in a background exec session and babysit with:

    line 180
  26. Distinctive:

    Do not upload directly from the remote build directory.

    line 332
  27. Distinctive:

    Keep all three distribution files and full logs at the permanent local artifact path.

    line 333
  28. Very specific:

    Treat artifacts.sha256 as the immutable human-review boundary.

    line 334
  29. Distinctive:

    Never overwrite or regenerate the manifest after human review.

    line 335
  30. Very specific:

    Write one Markdown report in the matching local agent-context project agent-drafts/ directory.

    line 339
  31. Distinctive:

    Use the exact version and run ID in the filename.

    line 340
  32. Distinctive:

    Do not copy raw logs into the report.

    line 342
  33. Distinctive:

    Stop after writing the report.

    line 371
  34. Very specific:

    Run one fail-closed command that appends every immediate pre-upload check and its complete output to publish-recheck.log:

    line 377
  35. Very specific:

    Treat an existing PyPI version or remote v<VERSION> tag as a hard failure.

    line 393
  36. Distinctive:

    Treat network and authentication errors as hard failures.

    line 394
  37. Distinctive:

    Create and push an annotated tag only after PyPI confirms the version:

    line 404
  38. Distinctive:

    Do not create a GitHub Release for beta, release-candidate, stable, or post releases.

    line 412
  39. Distinctive:

    Never reuse or move a published version tag.

    line 413
  40. Distinctive:

    Run this chapter only after PyPI and the Git tag exist.

    line 430
  41. Distinctive:

    Keep Chapter 9 implemented as auditable shell.

    line 432
  42. Very specific:

    Start one fresh --rm container for each CUDA major.

    line 434
  43. Very specific:

    Before installation, require Python to report that torch_memory_saver is absent.

    line 435
  44. Distinctive:

    Run the complete runtime pytest suite with the exact structured skip gate in both containers.

    line 438
  45. Distinctive:

    Never delete a published PyPI version to make a retry look clean.

    line 441

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

1 Release contract

  • Work from the repository root and publish only a clean commit already merged into the latest origin/master.
  • Use canonical PEP 440 versions in setup.py:
    • Beta: 0.0.10b1, not 0.0.10.beta-1, 0.0.10-beta.1, or 0.0.10beta1.
    • Release candidate: 0.0.10rc1.
    • Stable: 0.0.10.
    • Post release: 0.0.10.post1 only for a source-equivalent packaging correction.
  • Publish exactly three distributions:
    • cp39-abi3-manylinux2014_x86_64 wheel.
    • cp39-abi3-manylinux2014_aarch64 wheel.
    • Source distribution.
  • Build and test on tom-workstation.
  • Publish from the local controller.
  • Never persist PyPI credentials on the GPU host.
  • Never create a GitHub Release. Publish only the PyPI distributions and an annotated Git tag.
  • Treat PyPI upload and Git tag push as irreversible.
  • Complete the Section 8 confirmation gate before either action.

2 Prepare isolated paths

set -euxo pipefail
export TMS_RELEASE_VERSION="<VERSION>"
export TMS_RELEASE_SHA="$(git rev-parse --short=12 HEAD)"
export TMS_RELEASE_RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)-$$"
export TMS_REMOTE_ROOT="/home/tom/workspace/torch_memory_saver_release_${TMS_RELEASE_VERSION}_${TMS_RELEASE_SHA}_${TMS_RELEASE_RUN_ID}"
export TMS_REMOTE_ARTIFACTS="${TMS_REMOTE_ROOT}_artifacts"
export TMS_LOCAL_ARTIFACTS="/Users/tom/domains/human/others/artifacts/torch_memory_saver/${TMS_RELEASE_VERSION}-${TMS_RELEASE_SHA}-${TMS_RELEASE_RUN_ID}-release"
export TMS_RELEASE_CHECKS="$PWD/.claude/skills/tms-publish-release/scripts/release_checks.py"
mkdir "$TMS_LOCAL_ARTIFACTS"
  • Never reuse a local or remote source or artifact directory, even for the same version and commit.
  • Keep every build, validation, environment, and recheck log under the unique artifact directories.

3 Preflight

3.1 Repository and version

  • Append every command, complete output, and exit result to release-preflight.log:
set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- git fetch origin master
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- git status --short --branch
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- git rev-parse HEAD
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- git rev-parse origin/master
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- git diff --stat origin/master...HEAD
  • Stop if the tree is dirty, HEAD differs from origin/master, or the release commit is detached.
  • Read and validate the version without importing setup.py:
set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  uv run --script "$TMS_RELEASE_CHECKS" version \
  --setup-py setup.py \
  --expected-version "$TMS_RELEASE_VERSION"
  • Confirm the target version does not already exist on PyPI:
set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  uv run --script "$TMS_RELEASE_CHECKS" pypi \
  --expected-version "$TMS_RELEASE_VERSION"
  • Review every change since the previous release commit.
  • Use c29087a58db9d120b3e69623714c5dd043029d77 as the historical source baseline for the first tagged release after 0.0.9.post1.
  • Use the previous release tag after the first tagged release.

3.2 Host and credential checks

set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation 'set -euxo pipefail; curl --retry 5 --retry-delay 1 --retry-all-errors -x http://127.0.0.1:7890 -I --max-time 20 https://registry-1.docker.io/v2/'
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation 'set -euxo pipefail; test -x /home/tom/.local/bin/uv; nvidia-smi --query-gpu=index,name,driver_version,memory.total,memory.used,utilization.gpu --format=csv,noheader; docker version; df -h / /home/tom'
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  /usr/bin/stat -f '%N mode=%Lp size=%z' "$HOME/.pypirc"
  • Expect HTTP 401 from the Docker Hub registry probe; it proves official registry reachability.
  • Stop if GPU 0 is busy, Docker is unavailable, or the host lacks enough space for the PyTorch builder images.
  • Require local $HOME/.pypirc mode 0600.
  • Never print $HOME/.pypirc.
  • Never copy it to tom-workstation.
  • Never mount it into a long-lived container.

3.3 ARM64 emulation on the x86_64 host

  • The official manylinuxaarch64-builder images are Linux ARM64 images, not x86 cross-compiler images.
  • Check for an existing ARM64 binfmt handler:
set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation 'set -euxo pipefail; test -r /proc/sys/fs/binfmt_misc/qemu-aarch64; cat /proc/sys/fs/binfmt_misc/qemu-aarch64'
  • If it is missing, stop for approval before installing QEMU binfmt.
  • Treat installation as privileged and host-wide.
  • Use the pinned tonistiigi/binfmt image.
  • After approval, install only ARM64 and verify it with an ARM64 Alpine container:
set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation 'set -euxo pipefail
docker run --privileged --rm tonistiigi/binfmt@sha256:400a4873b838d1b89194d982c45e5fb3cda4593fbfd7e08a02e76b03b21166f0 --install arm64
cat /proc/sys/fs/binfmt_misc/qemu-aarch64
docker run --rm --platform linux/arm64 alpine:3.22 uname -m'
  • Require the smoke test to print aarch64.
  • Treat binfmt as boot-scoped unless the host has an explicit persistent registration. Recheck this section after every workstation reboot.

3.4 Release script roles

ScriptResponsibilityMutates release state
.claude/skills/tms-publish-release/scripts/release_checks.pyVersion, namespace, artifact, manifest, one-command pre-upload, and append-only command-log gatesNo
.claude/skills/tms-publish-release/scripts/gpu_validation.pyFour-cell fresh-container GPU runtime harness with exact skip enforcementCreates only temporary validation resources
.claude/skills/tms-publish-release/scripts/pytest_skip_gate.pyExact pytest skipped-node and reason validator loaded by the harnessNo
.claude/skills/tms-publish-release/scripts/verify_published_release.shAuditable post-release PyPI, CUDA 12, and CUDA 13 verificationCreates only temporary validation containers
  • Keep upload and tag creation outside every release script.
  • Do not create, query, attach artifacts to, or require a GitHub Release.
  • Use sdist only for focused diagnostics.
  • Use artifacts for the canonical release workflow after all three distributions exist.

3.5 Create and synchronize the remote source tree

set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation "set -euxo pipefail; test ! -e '$TMS_REMOTE_ROOT'; test ! -e '$TMS_REMOTE_ARTIFACTS'; mkdir '$TMS_REMOTE_ROOT' '$TMS_REMOTE_ARTIFACTS'"
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  rsync -a \
  --exclude .git \
  --exclude build \
  --exclude dist \
  --exclude torch_memory_saver.egg-info \
  --exclude .pytest_cache \
  --exclude '*.so' \
  ./ "tom-workstation:$TMS_REMOTE_ROOT/"
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- shasum -a 256 setup.py
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/release-preflight.log" -- \
  ssh tom-workstation "set -euxo pipefail; sha256sum '$TMS_REMOTE_ROOT/setup.py'"
  • Do not use rsync --delete.
  • Require the local and remote setup.py hashes to match.
  • The fail-if-present remote mkdir makes every rehearsal independent.

4 Build release distributions

4.1 x86_64 wheel

  • Build with the official PyTorch CUDA 12.8 and CUDA 13.0 manylinux images.
set -euxo pipefail
ssh tom-workstation "set -euxo pipefail; cd '$TMS_REMOTE_ROOT' \
  && make clean \
  && TMS_PYTHON_BUILD_IMAGE=python:3.11 make build-wheel-multi-cuda \
  > '$TMS_REMOTE_ARTIFACTS/build-x86_64.log' 2>&1"
  • Run long commands in a background exec session and babysit with:
set -euxo pipefail
ssh tom-workstation "set -euxo pipefail; tail -80 '$TMS_REMOTE_ARTIFACTS/build-x86_64.log'"

4.2 aarch64 wheel on the x86_64 host

  • Build with the official ARM64 PyTorch CUDA 12.8 and CUDA 13.0 manylinux images.
set -euxo pipefail
ssh tom-workstation "set -euxo pipefail; cd '$TMS_REMOTE_ROOT' \
  && rm -rf build torch_memory_saver.egg-info \
  && DOCKER_DEFAULT_PLATFORM=linux/arm64 \
    TMS_PYTHON_BUILD_IMAGE=python:3.11 \
    make build-wheel-multi-cuda-aarch64 \
  > '$TMS_REMOTE_ARTIFACTS/build-aarch64.log' 2>&1"

4.3 Source distribution and artifact gate

set -euxo pipefail
ssh tom-workstation "set -euxo pipefail; cd '$TMS_REMOTE_ROOT' \
  && TMS_PYTHON_BUILD_IMAGE=python:3.11 make build-sdist \
  > '$TMS_REMOTE_ARTIFACTS/build-sdist.log' 2>&1 \
  && HTTP_PROXY=http://127.0.0.1:7890 HTTPS_PROXY=http://127.0.0.1:7890 \
    /home/tom/.local/bin/uv run --script .claude/skills/tms-publish-release/scripts/release_checks.py artifacts \
    --dist-dir dist \
    --expected-version '$TMS_RELEASE_VERSION' \
    --repo-root . \
  > '$TMS_REMOTE_ARTIFACTS/validate-artifacts.log' 2>&1"
Input: $TMS_REMOTE_ROOT/dist
Exact set: x86_64 wheel, aarch64 wheel, sdist
Wheel gate:
  - Filename and internal metadata tags
  - ELF machine for every binary
  - CUDA 12 and CUDA 13 binary families
  - Unsuffixed CUDA 12 compatibility binaries
  - RECORD integrity
Sdist gate: canonical version, metadata, complete native sources
Ownership: dist, build, and torch_memory_saver.egg-info belong to the SSH user
Failure policy: stop on any mismatch or extra artifact

5 Validate both wheels in fresh GPU containers

5.1 Harness specification

CaseRuntime path
x86_64 CUDA 12PyTorch CUDA 12 container, direct NVIDIA runtime
x86_64 CUDA 13PyTorch CUDA 13 container, direct NVIDIA runtime
ARM64 CUDA 12Official Lupine 12.8.1 PyTorch worker under QEMU to matched x86 server
ARM64 CUDA 13Official Lupine 13.0.2 PyTorch worker under QEMU to matched x86 server

5.1.1 Common contract

Host: x86_64 tom-workstation
Inputs: final x86_64 wheel, final aarch64 wheel, runtime tests only
Image acquisition: docker run --pull missing
Source mount: release root at /workspace, read-only
Install root: final wheel into site-packages or dist-packages
Test root: /validation, outside the source checkout
x86_64 test suite: full single-GPU runtime pytest
ARM64 test suite: full runtime pytest with in-test Lupine skip markers
Lupine signal: TMS_TEST_LUPINE=1 in ARM64 validation containers only
Lupine skip 1: test_cpu_backup_preload_backend_from_env
Lupine skip 2: test_disk_backup, including both hook-mode parameters
CUDA major: matches the matrix cell
CUDA availability: torch.cuda.is_available() is true
GPU identity: NVIDIA GeForce RTX 4090 D
CUDA runtime: matching packaged libcudart added before preload children start
Process architecture: matches the matrix cell
Binary architecture: every loaded ELF machine matches the matrix cell
Inventory gate: every repository test_*.py classified as runtime or build tooling
Build-tool UT: build phase only
Success: zero failures in all four cells
Allowed skips: documented Lupine host-memory cases, single-GPU multi-device cases, XPU-only cases
Skip gate: exact node ID and normalized reason map passed through TMS_EXPECTED_PYTEST_SKIPS
Skip result: SKIP_GATE_ACTUAL and SKIP_GATE_RESULT recorded in the cell log
CLI deselection: forbidden
Missing, additional, duplicated, or reason-changed skip: cell failure
Evidence: image identity, environment, commands, installed paths, binaries, pytest output
Command log: EXEC line, complete stdout/stderr, terminal RESULT line
Container shell trace: set -euxo pipefail records each in-container command
Cleanup: named clients, servers, containers, and private networks removed on success or failure

5.1.2 Lupine contract

Matrix source: .claude/skills/tms-publish-release/scripts/gpu_validation.py
Image identity: architecture-specific worker/server refs pinned by digest
Worker: official ARM64 lupine-pytorch-worker
Server: official x86_64 lupine-server with GPU 0 attached
Source revision: ebf4c2784e5756891ed8c2439fec37ed1a4e6b51 for worker and server
Network: private per-cell bridge; RPC port not published to the workstation LAN
Proxy: host.docker.internal:host-gateway -> workstation Clash
Preinstalled: ARM Python, PyTorch, CUDA user-space libraries, CUDA/NVML shims
Added test dependencies: pinned binary NumPy, pytest, nvidia-ml-py wheels
Execution: real ARM64 Python, PyTorch, and TMS wheel under QEMU
GPU path: CUDA driver and NVML calls forwarded to the physical 4090D
Test signal: TMS_TEST_LUPINE=1
Qualification: ARM user-space GPU behavior through Lupine
Not qualified: ARM NVIDIA kernel driver or native ARM PCIe path
Disk-backup boundary: Lupine protects pinned host mirrors read-only, so kernel pread returns EFAULT
RSS boundary: Lupine first-transfer buffers invalidate the preload RSS delta assertion
Product-code workaround: forbidden; keep both behaviors covered by the direct x86_64 cells
Derived client image: forbidden
Server evidence: complete Lupine server output captured with docker logs before cleanup

5.2 Run the harness

set -euxo pipefail
ssh tom-workstation "set -euxo pipefail; HTTP_PROXY=http://127.0.0.1:7890 HTTPS_PROXY=http://127.0.0.1:7890 \
  /home/tom/.local/bin/uv run --script \
  '$TMS_REMOTE_ROOT/.claude/skills/tms-publish-release/scripts/gpu_validation.py' \
  --release-root '$TMS_REMOTE_ROOT' \
  --artifact-root '$TMS_REMOTE_ARTIFACTS' \
  --expected-version '$TMS_RELEASE_VERSION'"

6 Pull and recheck artifacts locally

set -euxo pipefail
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/local-recheck.log" -- \
  rsync -a "tom-workstation:$TMS_REMOTE_ARTIFACTS/" "$TMS_LOCAL_ARTIFACTS/"
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/local-recheck.log" -- \
  rsync -a "tom-workstation:$TMS_REMOTE_ROOT/dist/" "$TMS_LOCAL_ARTIFACTS/dist/"
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/local-recheck.log" -- \
  uv run --script "$TMS_RELEASE_CHECKS" artifacts \
  --dist-dir "$TMS_LOCAL_ARTIFACTS/dist" \
  --expected-version "$TMS_RELEASE_VERSION" \
  --repo-root .
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/local-recheck.log" -- \
  zsh -lc 'set -euxo pipefail; UV_CACHE_DIR="$TMS_LOCAL_ARTIFACTS/uv-cache" uv run --no-project --with twine python -m twine check "$TMS_LOCAL_ARTIFACTS"/dist/*'
uv run --script "$TMS_RELEASE_CHECKS" run --log-path "$TMS_LOCAL_ARTIFACTS/local-recheck.log" -- \
  uv run --script "$TMS_RELEASE_CHECKS" write-manifest \
  --dist-dir "$TMS_LOCAL_ARTIFACTS/dist" \
  --output "$TMS_LOCAL_ARTIFACTS/artifacts.sha256"
  • Do not upload directly from the remote build directory.
  • Keep all three distribution files and full logs at the permanent local artifact path.
  • Treat artifacts.sha256 as the immutable human-review boundary.
  • Never overwrite or regenerate the manifest after human review; start a new run instead.

7 Write the release evidence report

  • Write one Markdown report in the matching local agent-context project agent-drafts/ directory.
  • Use the exact version and run ID in the filename.
  • Link every raw artifact and log with its final absolute local path.
  • Do not copy raw logs into the report.
  • Set Human review: pending until the report has been inspected.
Source: full release SHA, branch, clean-tree evidence
Version: canonical version and collision-check results
Host: workstation, GPU, driver, kernel, Docker, binfmt
Artifacts: filename, size, SHA-256, metadata result, twine result, file link
Preflight evidence: release-preflight.log
Build evidence: x86_64 log, aarch64 log, sdist log, artifact-validator log
Local evidence: local-recheck.log and artifacts.sha256
GPU matrix row: architecture, CUDA major, image digest, PyTorch/CUDA/GPU identity
GPU matrix result: pytest summary, every skip reason, terminal RESULT, log link
Lupine boundary: TMS_TEST_LUPINE signal, exact skipped tests, qualification limit
Cleanup: validation containers, server, and network removal evidence
Safety: PyPI upload and release tag not performed; GitHub Release creation forbidden
Human review: pending
  • Link all five harness logs:
    • preflight.log.
    • x86_64-cuda12-gpu.log.
    • x86_64-cuda13-gpu.log.
    • aarch64-cuda12-gpu.log.
    • aarch64-cuda13-gpu.log.
  • Link release-preflight.log, local-recheck.log, and artifacts.sha256.
  • Transcribe the three manifest lines into the artifact table without changing their hashes.
  • Require every harness-invoked external command to have an EXEC line and a terminal RESULT line.
  • Require every GPU row to link the exact log containing image identity, pytest output, skip reasons, and cleanup.
  • Stop after writing the report.
  • Give the human the report link and wait for explicit publish approval.

8 Publish

  • Continue only after the Section 7 report has been reviewed and the human gives explicit confirmation.
  • Run one fail-closed command that appends every immediate pre-upload check and its complete output to publish-recheck.log:
set -euxo pipefail
UV_CACHE_DIR="$TMS_LOCAL_ARTIFACTS/uv-cache" uv run --script "$TMS_RELEASE_CHECKS" pre-upload \
  --dist-dir "$TMS_LOCAL_ARTIFACTS/dist" \
  --manifest "$TMS_LOCAL_ARTIFACTS/artifacts.sha256" \
  --expected-version "$TMS_RELEASE_VERSION" \
  --log-path "$TMS_LOCAL_ARTIFACTS/publish-recheck.log" \
  --repo-root . \
  --remote origin
  • The command fetches origin/master; requires a clean tree and HEAD == origin/master; verifies the approved manifest; reruns the complete artifact and Twine gates; and rejects existing PyPI or tag identities.
  • Require the verified manifest to equal the three hashes approved in the Section 7 report.
  • Upload only the files covered by that manifest.
  • Treat an existing PyPI version or remote v<VERSION> tag as a hard failure.
  • Treat network and authentication errors as hard failures.
  • Upload without --skip-existing; a collision is a hard failure:
set -euxo pipefail
UV_CACHE_DIR="$TMS_LOCAL_ARTIFACTS/uv-cache" uv run --no-project --with twine \
  python -m twine upload --non-interactive --repository pypi "$TMS_LOCAL_ARTIFACTS"/dist/*
  • Poll PyPI with bounded waits until all three files appear under the exact version.
  • Create and push an annotated tag only after PyPI confirms the version:
set -euxo pipefail
git tag -a "v$TMS_RELEASE_VERSION" -m "Release $TMS_RELEASE_VERSION" "$(git rev-parse HEAD)"
git push origin "v$TMS_RELEASE_VERSION"
  • Do not create a GitHub Release for beta, release-candidate, stable, or post releases.
  • Never reuse or move a published version tag.

9 Verify the published release from fresh containers

set -euxo pipefail
rsync -a "$TMS_LOCAL_ARTIFACTS/artifacts.sha256" \
  "tom-workstation:$TMS_REMOTE_ARTIFACTS/artifacts.sha256"
ssh tom-workstation "set -euxo pipefail
cd '$TMS_REMOTE_ROOT'
TMS_PROXY_URL=http://127.0.0.1:7890 \
  .claude/skills/tms-publish-release/scripts/verify_published_release.sh \
  '$TMS_RELEASE_VERSION' \
  '$TMS_REMOTE_ARTIFACTS/artifacts.sha256'" \
  2>&1 | tee "$TMS_LOCAL_ARTIFACTS/verify-published-release.log"
  • Run this chapter only after PyPI and the Git tag exist.
  • Copy the approved artifacts.sha256 to $TMS_REMOTE_ARTIFACTS before invoking the script.
  • Keep Chapter 9 implemented as auditable shell; do not move it into a Python orchestration command.
  • Require PyPI to contain exactly the two wheels and sdist recorded by the approved manifest, with matching SHA-256 digests.
  • Start one fresh --rm container for each CUDA major.
  • Before installation, require Python to report that torch_memory_saver is absent.
  • Install the exact published version from PyPI, never from the local dist/ directory.
  • Require the installed package to resolve from site-packages, PyTorch to report the matching CUDA major, and the GPU to be the 4090D.
  • Run the complete runtime pytest suite with the exact structured skip gate in both containers.
  • Require local verify-published-release.log to contain two passing pytest summaries and terminal RESULT: returncode=0.
  • Report any partial release state explicitly.
  • Never delete a published PyPI version to make a retry look clean.
  • Increment the prerelease number for a retry.

10 Reliability

SymptomCauseAction
Docker Hub pull resets or refusesDocker daemon is not using tms-clash-main, or the selected Clash node is unhealthyRepair the daemon proxy or refresh the remote Clash config; do not switch registries
ARM container reports exec format errorqemu-aarch64 binfmt is absentStop; request approval for the privileged binfmt bootstrap
Lupine client cannot reach the serverServer startup, Docker network, or matched CUDA pair is wrongInspect the cell log; keep the private network and use the exact client/server pair from the matrix
ARM PyTorch reports no GPUThe Lupine shim is not first in the client library path or the server lacks the GPU mountRequire /opt/lupine/lib in LD_LIBRARY_PATH, LUPINE_SERVER=<container>:14833, and --gpus device=0 only on the server
ARM and server CUDA tags differClient and server protocol/runtime behavior is not the validated pairStop and use exactly matched Lupine tags; never mix CUDA 12 and CUDA 13 endpoints
ARM validation starts downloading PyTorchThe harness is using a generic client or builder instead of the published workerStop and use the digest-pinned lupine-pytorch-worker; only NumPy, pytest, and nvidia-ml-py should be installed before the final TMS wheel
ARM NumPy/pytest install cannot reach 127.0.0.1:7890Loopback inside the private-network client is the client itselfAdd host.docker.internal:host-gateway and use http://host.docker.internal:7890 inside the ARM client
make build-sdist cannot import setuptoolsThe sdist ran against an unprepared host PythonUse the repository's containerized target with TMS_PYTHON_BUILD_IMAGE=python:3.11
make clean reports Permission denied under dist/An older build left root-owned bind-mount outputRemove only the dedicated rehearsal output through a root Docker container, then use the current scripts that normalize ownership
Wheel test imports /workspace/torch_memory_saverPytest ran against the source treeCopy only test/ to /validation and rerun against the installed wheel
CUDA 13 preload tests report libcudart.so.13 missingThe runtime image installs CUDART under Python site-packages/nvidia/cu13/lib without registering it in ldconfigDiscover the matching CUDART path before pytest and export it through LD_LIBRARY_PATH; do not skip preload tests
SKIP_GATE_RESULT=failA skip is missing, additional, duplicated, or has a changed reasonInspect SKIP_GATE_ACTUAL; update code or the reviewed matrix contract instead of silently accepting it
Cleanup raises after a passing cellDocker cleanup timed out or could not startInspect the complete cell log; the harness attempted every cleanup command and preserved any earlier validation error
Manifest verification failsAn artifact changed or the file set differs after human reviewStop and start a new build and review run; never regenerate the approved manifest
Post-release verification reports jq: command not foundThe workstation lacks the host-side JSON verifierInstall jq with sudo apt-get install -y jq; the script checks every host dependency before network access
dist/ has extra wheelsStale or partial build outputStop and start a new run directory; never repair or reuse a release tree
PyPI upload reports an existing filenameVersion or artifact was already publishedStop; never use --skip-existing or overwrite a release

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.