Skip to content

Commit 55be97e

Browse files
committed
ci: skip release when no Solidity source changed
Only create a release when src/**/*.sol files differ from the last Soldeer-published version. README, CI, docs, and test-only changes no longer trigger a version bump. Remove @semantic-release/commit-analyzer so it cannot independently trigger releases for conventional commits that only touch non-source files. Claude via analyze-bump.sh is now the sole release gatekeeper. Also: CLAUDE.md is now a symlink to AGENTS.md, copilot-instructions updated for current naming.
1 parent 7625e02 commit 55be97e

File tree

5 files changed

+80
-76
lines changed

5 files changed

+80
-76
lines changed

.github/copilot-instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
`uint-quantization-lib` is a pure-function Solidity library for shift-based `uint256` compression.
66
The core implementation is `UintQuantizationLib` in `src/UintQuantizationLib.sol`, built around
7-
`Quant` (a `uint16` value type that packs `shift` and `targetBits`).
7+
`Quant` (a `uint16` value type that packs `discardedBitWidth` and `encodedBitWidth`).
88

99
## Repository-specific guidance
1010

1111
- Keep library functions `internal pure` unless there is a strong reason not to.
12-
- `Quant` layout is fixed: bits 0-7 = `shift`, bits 8-15 = `targetBits`.
12+
- `Quant` layout is fixed: bits 0-7 = `discardedBitWidth`, bits 8-15 = `encodedBitWidth`.
1313
- Keep custom errors file-level with bare names (`BadConfig`, `Overflow`, `NotAligned`).
1414
- Keep fuzz constraints consistent with existing tests (`bound()` instead of `vm.assume`).
1515
- For resolution-sensitive flows, prefer `encode(value, true)`; for floor truncation use `encode`.

.releaserc.json

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
11
{
22
"branches": ["main"],
33
"plugins": [
4-
[
5-
"@semantic-release/commit-analyzer",
6-
{
7-
"preset": "conventionalcommits",
8-
"releaseRules": [
9-
{ "breaking": true, "release": "major" },
10-
{ "type": "feat", "release": "minor" },
11-
{ "type": "fix", "release": "patch" },
12-
{ "type": "perf", "release": "patch" },
13-
{ "type": "refactor", "release": "patch" }
14-
]
15-
}
16-
],
174
[
185
"@semantic-release/exec",
196
{

AGENTS.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
`uint-quantization-lib` is a pure-function Solidity library for shift-based `uint256` lossy compression. The core mechanism is floor quantization via right-shifting. A `Quant` value type packs `(discardedBitWidth, encodedBitWidth)` into a single `uint16`, making the compression scheme explicit and reusable. The recommended pattern is `immutable` + `create(discardedBitWidth, encodedBitWidth)`.
8+
9+
## Commands
10+
11+
```bash
12+
forge build # compile
13+
forge test # all tests (includes 65536 fuzz runs)
14+
forge test --match-path test/UintQuantizationLib.t.sol # library tests only
15+
forge test --match-test test_encodePrecise_notAligned_reverts # single test
16+
forge test --match-test testFuzz_ # fuzz tests only
17+
forge test --match-path test/showcase/ShowcaseGas.t.sol --gas-report -vv # gas benchmarks
18+
forge fmt # format Solidity files
19+
```
20+
21+
## Architecture
22+
23+
### Core library: `src/UintQuantizationLib.sol`
24+
25+
- UDT `Quant` wraps `uint16`: bits 0-7 = discardedBitWidth, bits 8-15 = encodedBitWidth.
26+
- All library functions are `internal pure`.
27+
- Errors (`BadConfig`, `Overflow`, `NotAligned`) are file-level, not inside the library block.
28+
- `using UintQuantizationLib for Quant global` at file bottom propagates method-call syntax to all importers automatically (no local `using` needed).
29+
- `VERSION` constant is bumped automatically by semantic-release; do not edit it manually.
30+
31+
### Showcase: `src/showcase/ShowcaseSolidityFixtures.sol`
32+
33+
Production-style contracts for gas benchmarks only. Raw vs quantized pairs: `RawETHStakingShowcase` / `QuantizedETHStakingShowcase` (real-life staking) and `RawExtremePackingShowcase` / `QuantizedExtremePackingShowcase` (12 slots into 1).
34+
35+
### Tests: `test/`
36+
37+
- `UintQuantizationLib.t.sol`: `QuantHarness` exposes library via method-call syntax for external calls. `UintQuantizationLibSmokeTest` has concrete regression tests and fuzz tests. Fuzz parameters use `uint8` for discardedBitWidth/encodedBitWidth; use `bound()` over `vm.assume` for value-in-range constraints.
38+
- `showcase/ShowcaseGas.t.sol`: Asserts quantized paths save >= 32% (real-life) and >= 80% (extreme) gas vs raw on zero-to-nonzero writes.
39+
40+
### Configuration
41+
42+
- `foundry.toml`: optimizer runs = 0x10000, fuzz runs = 0x10000, deps via Soldeer (`libs = ["dependencies"]`).
43+
- `remappings.txt`: maps `forge-std/` from `dependencies/`.
44+
45+
## Conventions
46+
47+
- Solidity `^0.8.25`, 4-space indentation, NatSpec on public-facing behavior.
48+
- Errors are file-level with bare names (not namespaced inside the library).
49+
- Create schemes with `UintQuantizationLib.create(...)`; never use `Quant.wrap(...)` directly.
50+
- Showcase pairs follow `Raw...` / `Quantized...` naming.
51+
- Test names: `test_` prefix for concrete, `testFuzz_` for fuzz. Descriptive: `test_encode_overflow_reverts`.
52+
- Fuzz tests: `uint8` params for scheme dimensions, `bound()` not `vm.assume` for bounding values.
53+
- Conventional Commits: `feat:`, `fix:`, `ci:`, `docs:`, `chore:`, `refactor:`, `perf:`.
54+
- If gas numbers change, include before/after output from the showcase gas report.
55+
56+
## Release pipeline
57+
58+
Fully automated on push to main (`.github/workflows/release.yml`):
59+
1. `scripts/analyze-bump.sh` checks if any `src/**/*.sol` files changed since the last Soldeer publish (`soldeer-published` tag). If no Solidity source changed, no release is created.
60+
2. If source changed, Claude (Opus, max effort) analyzes the diff and determines the semver bump (major/minor/patch). Falls back to "patch" if Claude is unavailable.
61+
3. `@semantic-release/exec` bumps the `VERSION` constant in `UintQuantizationLib.sol`.
62+
4. GitHub release created, CHANGELOG.md + source committed with `[skip ci]`.
63+
5. `forge soldeer push` publishes to the Soldeer registry, then tags `soldeer-published`.

CLAUDE.md

Lines changed: 0 additions & 53 deletions
This file was deleted.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

scripts/analyze-bump.sh

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@ set -euo pipefail
33

44
# Called by @semantic-release/exec as analyzeCommitsCmd.
55
# Asks Claude to determine the semantic version bump from the diff.
6+
# Skips release entirely when no Solidity source files under src/ changed.
67
# Falls back to "patch" if the token is missing or the call fails.
78

8-
if [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
9-
echo "patch"
10-
exit 0
11-
fi
12-
139
# Comparison base: last successful Soldeer publish, then last release tag, then repo root.
1410
# This ensures the bump reflects what users actually have, not intermediate failed publishes.
1511
if git rev-parse soldeer-published >/dev/null 2>&1; then
@@ -20,16 +16,26 @@ else
2016
BASE=$(git rev-list --max-parents=0 HEAD)
2117
fi
2218

19+
# No release when library source is unchanged (README, CI, docs, tests are chore).
20+
SOL_DIFF=$(git diff "$BASE"..HEAD -- 'src/*.sol' 'src/**/*.sol' 2>/dev/null || echo "")
21+
if [ -z "$SOL_DIFF" ]; then
22+
exit 0
23+
fi
24+
25+
if [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
26+
echo "patch"
27+
exit 0
28+
fi
29+
2330
COMMIT_LOG=$(git log "$BASE"..HEAD --pretty=format:"- %s" 2>/dev/null || echo "- initial release")
2431
DIFF_STAT=$(git diff "$BASE"..HEAD --stat 2>/dev/null | tail -30 || echo "no diff")
25-
SOL_DIFF=$(git diff "$BASE"..HEAD -- '*.sol' 2>/dev/null | head -200 || echo "no diff")
2632

2733
PROMPT="You are a semantic versioning expert for a Solidity library (uint-quantization-lib).
2834
2935
Rules:
3036
- major: breaking changes to the consumer-facing API (renamed functions, changed signatures, renamed/removed errors, changed type definitions)
3137
- minor: new features (new functions, new error types, new capabilities)
32-
- patch: bug fixes, docs, CI/CD, tests, internal refactoring, performance improvements
38+
- patch: bug fixes, internal refactoring, performance improvements
3339
3440
Respond with exactly one word: major, minor, or patch.
3541
@@ -40,7 +46,7 @@ Changed files:
4046
${DIFF_STAT}
4147
4248
Solidity diff (truncated):
43-
${SOL_DIFF}"
49+
$(echo "$SOL_DIFF" | head -200)"
4450

4551
RESPONSE=$(echo "$PROMPT" | claude --print --model opus --effort max 2>/dev/null) || { echo "patch"; exit 0; }
4652

0 commit comments

Comments
 (0)