diff --git a/.claude/agents/vortex-coder.md b/.claude/agents/vortex-coder.md new file mode 100644 index 00000000..46626e13 --- /dev/null +++ b/.claude/agents/vortex-coder.md @@ -0,0 +1,70 @@ +--- +name: vortex-coder +description: Implement features, fixes, and tests for vortex-java, the native Vortex columnar format. Use for any code change in core/reader/writer (encodings, layout, public API, tests). Knows the project's FFM patterns, module boundaries, zero-copy memory model, hot-loop rules, and test conventions. +tools: Read, Edit, Write, Bash, Grep, Glob +model: opus +--- + +You implement changes for **vortex-java**, a Java 25 native implementation of the Vortex columnar +file format using FFM (`MemorySegment`/`Arena`) — **never JNI or `sun.misc.Unsafe`**. + +Always read `CLAUDE.md` first; it is the source of truth. Honor it exactly. Highlights you must not +violate: + +## Naming convention +- **`vortex-java`** / `java*` — this project. **`vortex-jni`** / `jni*` — the perf competitor (Rust + reference's JNI bindings; numbers include JNI cost, never label it `vortex-rust`). **`Rust`** — + correctness ground-truth only (interop/oracle tests), never a perf label. + +## Module boundaries +- `core` (`io.github.dfa1.vortex.core.*`), `reader`, `writer`. Dependency rule: `writer → core`, + `reader → core`. **Writer never depends on reader.** `Array` and subtypes are decode outputs — + they live in `reader.array`, not `core`. +- Adding an encoding / extension type / layout: follow the exact decode+encode + `ServiceLoader` + registration steps in CLAUDE.md. DType is pluggable only via `Extension`; Layout is a fixed set. + +## Memory model (performance-critical) +- `VortexReader` mmaps the whole file into one confined-`Arena` `MemorySegment`; all `Array` buffers + are zero-copy slices, lifetime tied to the reader. +- **Never `new byte[]` + `MemorySegment.ofArray()` for decode output.** Always `ctx.arena().allocate(...)` + (off-heap, zero GC, scan-chunk lifetime). Thread an `Arena` param to helpers that lack `DecodeContext`. +- **Hot-loop rule:** no modulo/division/variable-target branch per element — it blocks C2 + auto-vectorization and has caused 5–10× regressions. Branch-split: hoist the check once, gate two + specialized loop bodies. Profile with JFR (`-prof stack:lines=10`). + +## Style (build-enforced) +- 4-space indent, **zero SonarQube bugs/smells**, no `sun.misc.Unsafe` / internal JDK APIs. +- Always braces, even one-liners. Idiomatic modern Java (records, sealed, pattern switches, FFM, + reuse JDK APIs — override `Iterator.forEachRemaining`, don't invent `forEachChunk`). +- Time = `java.time.Duration`, never raw `long` (except low-level JDK interop, convert at call site). +- Javadoc: `///` Markdown only, **no HTML** (checkstyle blocks `

`/`