commit 0af4194c23a2b7162bea8fe8d45c955bb1f24763
parent 4aa40f21d60e64452f05a03ca94e8528e71a5927
Author: Erik Loualiche <[email protected]>
Date: Sat, 7 Feb 2026 13:45:54 -0600
Update CLAUDE.md with comprehensive release process guidelines
- FFI artifact build and release workflow
- Artifacts.toml format specification
- Registry update procedures (Versions.toml, Deps.toml, Compat.toml)
- Version range rules and common pitfalls
- Updated architecture diagram with Artifacts.toml
- Updated API functions with native FFI methods
- Added Enum type to protocol spec and type conversion table
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Diffstat:
| M | CLAUDE.md | | | 124 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
1 file changed, 105 insertions(+), 19 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
@@ -18,6 +18,11 @@ NickelEval/
│ └── src/lib.rs
├── deps/
│ └── build.jl # Build script for FFI
+├── Artifacts.toml # Pre-built FFI library URLs/hashes
+├── .github/workflows/
+│ ├── CI.yml # Julia tests
+│ ├── Documentation.yml
+│ └── build-ffi.yml # Cross-platform FFI builds
└── test/
└── test_subprocess.jl
```
@@ -34,9 +39,10 @@ JSON.jl 1.0 provides:
### 2. Types from Nickel FFI, Not JSON
The Rust FFI returns a binary protocol with native type information:
-- Type tags: 0=Null, 1=Bool, 2=Int64, 3=Float64, 4=String, 5=Array, 6=Record
+- Type tags: 0=Null, 1=Bool, 2=Int64, 3=Float64, 4=String, 5=Array, 6=Record, 7=Enum
- Direct memory encoding without JSON serialization overhead
- Preserves integer vs float distinction
+- Enum variants preserved as `NickelEnum(tag, arg)`
### 3. Avoid `unwrap()` in Rust
@@ -104,7 +110,50 @@ git push origin vX.Y.Z
3. Commit these changes
4. Wait for CI to pass
5. Tag the release
-6. Update loulouJL registry with correct tree SHA
+6. If FFI changed, build and upload new artifacts (see FFI Artifact Release below)
+7. Update loulouJL registry with correct tree SHA
+
+### FFI Artifact Release
+
+When the Rust FFI code changes, new pre-built binaries must be released:
+
+1. **Trigger the build workflow:**
+ ```bash
+ gh workflow run build-ffi.yml --ref main
+ ```
+
+2. **Download built artifacts** from the workflow run (4 platforms: aarch64-darwin, x86_64-darwin, x86_64-linux, x86_64-windows)
+
+3. **Create GitHub Release** and upload the `.tar.gz` files
+
+4. **Calculate tree hashes** for each artifact:
+ ```bash
+ # For each tarball:
+ tar -xzf libnickel_jl-PLATFORM.tar.gz
+ julia -e 'using Pkg; println(Pkg.GitTools.tree_hash("."))'
+ ```
+
+5. **Update Artifacts.toml** with new SHA256 checksums and tree hashes
+
+### Artifacts.toml Format
+
+Use the `[[artifact_name]]` array format with platform properties:
+
+```toml
+[[libnickel_jl]]
+arch = "aarch64"
+git-tree-sha1 = "TREE_HASH_HERE"
+os = "macos"
+lazy = true
+
+ [[libnickel_jl.download]]
+ url = "https://github.com/LouLouLibs/NickelEval/releases/download/vX.Y.Z/libnickel_jl-aarch64-apple-darwin.tar.gz"
+ sha256 = "SHA256_HASH_HERE"
+```
+
+Platform values:
+- `os`: "macos", "linux", "windows"
+- `arch`: "aarch64", "x86_64"
### Documentation Requirements
@@ -114,10 +163,36 @@ Any new exported function must be added to `docs/src/lib/public.md` in the appro
Location: `/Users/loulou/Dropbox/projects_code/julia_packages/loulouJL/N/NickelEval/`
-After tagging, update `Versions.toml` with:
-```bash
-git rev-parse vX.Y.Z^{tree} # Get tree SHA
-```
+**Files to update:**
+
+1. **Versions.toml** - Add new version entry:
+ ```toml
+ ["X.Y.Z"]
+ git-tree-sha1 = "TREE_SHA_HERE"
+ ```
+ Get tree SHA: `git rev-parse vX.Y.Z^{tree}`
+
+2. **Deps.toml** - If dependencies changed, add new version range:
+ ```toml
+ ["X.Y-0"]
+ Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
+ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
+ LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
+ ```
+ **Important:** Version ranges must not overlap. Use `"X.Y-Z.W"` for ranges.
+
+3. **Compat.toml** - If compat bounds changed:
+ ```toml
+ ["X.Y-0"]
+ JSON = ["0.21", "1"]
+ ```
+ Use arrays for multiple compatible versions: `["0.21", "1"]`
+
+**Registry format rules:**
+- Section headers must be quoted: `["0.5"]` not `[0.5]`
+- Version ranges: `"0.4-0.5"` (from 0.4 to 0.5), `"0.5-0"` (from 0.5 to end of 0.x)
+- No spaces in ranges
+- Ranges must not overlap for the same dependency
## Binary Protocol Specification
@@ -132,15 +207,23 @@ The FFI uses a binary protocol for native type encoding:
| 4 (String) | Tag + 4 bytes length + UTF-8 bytes |
| 5 (Array) | Tag + 4 bytes count + elements |
| 6 (Record) | Tag + 4 bytes field count + (key_len, key, value)* |
+| 7 (Enum) | Tag + 4 bytes tag_len + tag_bytes + 1 byte has_arg + [arg_value] |
## API Functions
-### Evaluation
+### Evaluation (Subprocess - requires Nickel CLI)
- `nickel_eval(code)` - Evaluate to `JSON.Object`
- `nickel_eval(code, T)` - Evaluate and convert to type `T`
- `nickel_eval_file(path)` - Evaluate a `.ncl` file
-- `nickel_eval_ffi(code)` - FFI-based evaluation (faster)
+
+### Evaluation (Native FFI - no CLI needed)
+
+- `nickel_eval_ffi(code)` - FFI evaluation via JSON (supports typed parsing)
+- `nickel_eval_ffi(code, T)` - FFI evaluation with type conversion
+- `nickel_eval_native(code)` - FFI with binary protocol (preserves types)
+- `nickel_eval_file_native(path)` - Evaluate file with import support
+- `check_ffi_available()` - Check if FFI library is loaded
### Export
@@ -151,15 +234,16 @@ The FFI uses a binary protocol for native type encoding:
## Type Conversion
-| Nickel Type | Julia Type |
-|-------------|------------|
-| Null | `nothing` |
-| Bool | `Bool` |
-| Number (integer) | `Int64` |
-| Number (float) | `Float64` |
-| String | `String` |
-| Array | `Vector` or `JSON.Array` |
-| Record | `JSON.Object`, `Dict`, `NamedTuple`, or struct |
+| Nickel Type | Julia Type (FFI native) | Julia Type (JSON) |
+|-------------|-------------------------|-------------------|
+| Null | `nothing` | `nothing` |
+| Bool | `Bool` | `Bool` |
+| Number (integer) | `Int64` | `Int64` |
+| Number (float) | `Float64` | `Float64` |
+| String | `String` | `String` |
+| Array | `Vector{Any}` | `JSON.Array` |
+| Record | `Dict{String,Any}` | `JSON.Object` |
+| Enum | `NickelEnum(tag, arg)` | N/A (JSON export) |
## Nickel Language Reference
@@ -191,9 +275,11 @@ let double = fun x => x * 2 in double 21
## Dependencies
### Julia
-- JSON.jl >= 1.0
+- JSON.jl >= 0.21 or >= 1.0
+- Artifacts (stdlib)
+- LazyArtifacts (stdlib)
-### Rust
+### Rust (for building FFI locally)
- nickel-lang-core = "0.9"
- malachite = "0.4"
- serde_json = "1.0"