From 237eff968305570bc8fa3f3bec47b1ddb5095272 Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 20 Aug 2026 10:49:22 +0000 Subject: [PATCH 1/2] Strip release-process narration from docs The release process is owned by rainix's rainix-tag-release reusable and restating it per-repo drifts: rainlanguage/rainix#338 made tag-release push-free, so the 'commits the snapshot back to main' narration here was already stale. Docs-only; repo-local invariants kept, mechanics point to rainix. Ruling: rainlanguage/claude-audit-skills#91 Philosophy: rainlanguage/rainix#298 Co-Authored-By: Claude Opus 4.8 --- .github/workflows/package-release.yaml | 7 +------ CLAUDE.md | 10 +++------- README.md | 6 ++---- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/.github/workflows/package-release.yaml b/.github/workflows/package-release.yaml index ee1b505..4718aa4 100644 --- a/.github/workflows/package-release.yaml +++ b/.github/workflows/package-release.yaml @@ -1,10 +1,5 @@ name: Package Release -# Deploy repo: a manual `sol-v*` tag is the sole release trigger. The tag names -# the version; rainix-tag-release verifies prod exists at the regenerated pins, -# publishes rain-factory-deploy to Soldeer, and commits the frozen snapshot back -# to main. The on-chain deploy is separate and manual (rainix-manual-sol-artifacts -# dispatch), run before tagging. Nothing publishes on merge, so [package].version -# and the frozen src/generated// snapshot it names only ever move together. +# Deploy repo: released by a manual `sol-v*` tag via rainix-tag-release. on: push: tags: diff --git a/CLAUDE.md b/CLAUDE.md index 4c277ed..35f436b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -110,13 +110,9 @@ This is a **deploy repo**, not a library repo, so nothing publishes on merge: - `[package].version` in `foundry.toml` is the **last released** version (it names the current `src/generated//` snapshot), not a next-version slot. A normal PR does not bump it; only a release moves it. -- A human pushes a `sol-v` tag, which runs `rainix-tag-release`: it - writes the version from the tag into `foundry.toml`, regenerates the snapshot - (`forge script ./script/BuildPointers.sol && forge fmt`), verifies the live - chains match the fresh pins with `forge test`, publishes `rain-factory-deploy` - to Soldeer, and commits the new snapshot back to `main`. -- The on-chain deploy happens **before** tagging, via the manual dispatch above; - `rainix-tag-release` never broadcasts, it only attests. +- A manual `sol-v` tag is the sole release trigger. The on-chain deploy + happens **before** tagging, via the manual dispatch above; tagging never + broadcasts. The release mechanics are `rainix-tag-release`'s. - Existing `src/generated//` snapshots are frozen: a release adds a new tag directory, it never edits or deletes an existing one. CI enforces this. diff --git a/README.md b/README.md index 9e5cdbc..25f1380 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,8 @@ This is a deploy repo: releases are **manual `sol-v*` tags**, not merges. The on-chain deploy is a separate, human-dispatched step, run **before** tagging: the `Manual sol artifacts` workflow runs `script/Deploy.sol` for the -`clone-factory` suite. Tagging then runs `rainix-tag-release`, which regenerates -the snapshot for the tagged version, verifies the live chains match those fresh -pins, publishes `rain-factory-deploy` to Soldeer, and commits the frozen -snapshot back to `main`. It never broadcasts a deploy itself. +`clone-factory` suite. Tagging then runs `rainix-tag-release`, which never +broadcasts a deploy itself; its mechanics live in rainix. Nothing publishes on merge, so `[package].version` and the frozen `src/generated//` snapshot it names only ever move together. From c887651d785f4e67a190cd4d9d42b8c5b048114f Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 20 Aug 2026 12:08:06 +0000 Subject: [PATCH 2/2] Trim CLAUDE.md under the 4096-byte agent-context cap Most of the file was discoverable content the cap gate targets (build/test command listings, CI job breakdown, file-by-file architecture, dep list). Kept only the non-discoverable invariants: interfaces-live-in-rain.factory, pragma pins, deterministic-address hazards, frozen/append-only snapshots, the last-released [package].version, and the manual-deploy-before-tag shape. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 173 +++++++++++++----------------------------------------- 1 file changed, 42 insertions(+), 131 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 35f436b..7c196cb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,133 +1,44 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with -code in this repository. - -## Project Overview - -rain.factory.deploy is the **deployment** half of `rain.factory`: the concrete -`CloneFactory` contract plus its deployed address + codehash pins. The core -contract `CloneFactory` clones any contract implementing `ICloneableV2` (an -interface it imports from the `rain-factory` Soldeer package) and atomically -initializes it. - -License: LicenseRef-DCL-1.0 (DecentraLicense). All source files must include -SPDX headers. - -## Build & Test Commands - -This project uses **Nix + Foundry (Forge)**. Everything runs in the rainix -`sol-shell`, the same shell CI uses: - -```bash -nix develop .#sol-shell -``` - -Soldeer dependencies are not committed (`dependencies/` is gitignored), so -install them before the first build: - -```bash -nix develop .#sol-shell -c forge soldeer install -``` - -Each command below has a matching CI job: - -```bash -# Build -nix develop .#sol-shell -c forge build - -# Run all tests. The five LibCloneFactoryDeployProdTest fork tests read the -# live chains and need ARBITRUM_RPC_URL, BASE_RPC_URL, BASE_SEPOLIA_RPC_URL, -# FLARE_RPC_URL and POLYGON_RPC_URL; without them only those five fail. -nix develop .#sol-shell -c forge test - -# Run a specific test, or a specific file -nix develop .#sol-shell -c forge test --match-test testCloneDeterministic -nix develop .#sol-shell -c forge test --match-path test/src/concrete/CloneFactoryCloneDeterministic.t.sol - -# Formatting (CI runs `forge fmt --check`) -nix develop .#sol-shell -c forge fmt - -# Static analysis -nix develop .#sol-shell -c slither . - -# License/legal checks (REUSE compliance) -nix develop .#sol-shell -c reuse lint - -# Regenerate the deploy pins for the current [package].version -nix develop .#sol-shell -c bash -c 'forge script ./script/BuildPointers.sol && forge fmt' -``` - -## Architecture - -The `ICloneable*` interfaces are NOT in this repo. They live in -[`rain.factory`](https://github.com/rainlanguage/rain.factory) and arrive here -as the `rain-factory` Soldeer dependency, so they are read under -`dependencies/rain-factory-/src/interface/`. - -- `src/concrete/CloneFactory.sol` — The single concrete implementation of - `ICloneableFactoryV3`. Uses OpenZeppelin `Clones.cloneDeterministic()`; there - is no plain `clone()`. -- `src/lib/LibCloneFactoryDeploy.sol` — Deterministic deployment address and - codehash constants (generated; aliases the current tag's - `src/generated//` snapshot). -- `src/generated//CloneFactory.pointers.sol` — Frozen per-release - deploy-pin snapshots: creation code, runtime code, bytecode hash, deployed - address. -- `script/BuildPointers.sol` — Regenerates the snapshot for the current - `[package].version` and the `LibCloneFactoryDeploy` alias. -- `script/Deploy.sol` — The Zoltu deploy script. - -## Solidity Conventions - -- Solidity version: concrete contracts, scripts and tests pin `=0.8.25` (exact); - library and generated files float `^0.8.25` so downstream soldeer consumers on - a different `0.8.x` can still compile them -- EVM target: Cancun -- Optimizer: enabled, 100,000 runs -- No CBOR metadata (`cbor_metadata = false`, `bytecode_hash = "none"`) -- Dependencies are managed with Soldeer (`[dependencies]` in `foundry.toml` + - `soldeer.lock`, vendored under `dependencies/`): forge-std, - @openzeppelin-contracts, rain-extrospection, rain-deploy, rain-sol-codegen, - rain-factory - -## Deployment - -Deployed via the deterministic Zoltu deployer (from `rain.deploy`), so the -address is a pure function of the bytecode. The canonical address and codehash -are committed in `LibCloneFactoryDeploy.sol`. `script/Deploy.sol` deploys the -`clone-factory` suite to the five networks `LibRainDeploy.supportedNetworks()` -returns: Arbitrum One, Base, Base Sepolia, Flare and Polygon. - -A deploy is a human-dispatched run of the `Manual sol artifacts` workflow -(`workflow_dispatch` → `rainix-manual-sol-artifacts`), never a merge and never -part of the release workflow. - -## Releases and versioning - -This is a **deploy repo**, not a library repo, so nothing publishes on merge: - -- `[package].version` in `foundry.toml` is the **last released** version (it - names the current `src/generated//` snapshot), not a next-version slot. A - normal PR does not bump it; only a release moves it. -- A manual `sol-v` tag is the sole release trigger. The on-chain deploy - happens **before** tagging, via the manual dispatch above; tagging never - broadcasts. The release mechanics are `rainix-tag-release`'s. -- Existing `src/generated//` snapshots are frozen: a release adds a new tag - directory, it never edits or deletes an existing one. CI enforces this. - -## CI - -`.github/workflows/rainix-sol.yaml` calls the rainix `rainix-sol` reusable on -every push, which runs three parallel jobs: - -- `test` — `forge test -vvv`. The `LibCloneFactoryDeployProdTest` fork tests - need the `RPC_URL_*_FORK` secrets. -- `static` — `slither .`, `forge fmt --check`, `rainix-sol-single-contract` (one - contract per `.sol` file), plus the org-wide gates: no ignored tests, no git - submodules, no `@custom:` NatSpec, and append-only `src/generated//` - snapshots. -- `legal` — `reuse lint`. - -The other two workflows never run on push: `package-release.yaml` fires only on -a `sol-v*` tag, and `manual-sol-artifacts.yaml` only on `workflow_dispatch`. +Only what a capable agent would get _wrong_ from this repo alone. Layout, dev +shells, build/test commands, dependency lists, and which command CI runs are all +discoverable and deliberately absent (rainlanguage/rainix#298). + +## What this repo is + +rain.factory.deploy is the **deploy half** of `rain.factory`: the concrete +`CloneFactory` (clones any `ICloneableV2` via OpenZeppelin +`Clones.cloneDeterministic()` — there is no plain `clone()`) plus its deployed +address + codehash pins. The `ICloneable*` **interfaces are NOT here** — they +live in `rain.factory` and arrive as the `rain-factory` Soldeer dependency +(`dependencies/rain-factory-/src/interface/`). + +## Conventions an agent would get wrong + +- Pragma: concrete contracts, scripts and tests pin `=0.8.25` (exact); library + and generated files float `^0.8.25` so downstream soldeer consumers on another + `0.8.x` still compile them. +- Optimizer 100,000 runs; no CBOR metadata (`cbor_metadata = false`, + `bytecode_hash = "none"`). The deployed address is a pure function of the + bytecode (deterministic Zoltu deployer), so any of these changing moves the + pins. +- All source files need SPDX headers (LicenseRef-DCL-1.0). + +## Deploy-pin invariants (the hazards) + +- `src/generated//` snapshots are **frozen**: a release ADDS a new tag dir, + never edits or deletes an existing one. CI enforces append-only. +- `[package].version` is the **last released** version — it names the current + `src/generated//` snapshot. A normal PR does not bump it; only a release + moves it, in lockstep with the snapshot. +- `LibCloneFactoryDeploy.sol` aliases the current tag's snapshot; + `script/BuildPointers.sol` regenerates both. Generated files — do not + hand-edit. + +## Release / deploy shape + +- The on-chain deploy is a human-dispatched `Manual sol artifacts` run + (`workflow_dispatch`), done **before** tagging — never on merge, never part of + the release workflow, and it is what actually broadcasts. +- A manual `sol-v` tag is the sole release trigger. The release + mechanics live in rainix's `rainix-tag-release` reusable, not here.