docs(adr): split read and write runtimes out of core#29
Merged
Conversation
The 33 `unwrapForSubParser` audit-trail sites in PR #27 are a strong signal that the current module layout is wrong: `core` hosts the read runtime, not just the data model. `reader` is a thin orchestration shell around `core`; cross-module byte hand-offs force public escape-hatch APIs (`VortexHandle.slice`, `Registry.decodeAsSegment`) that no architectural wrapper can really cure. Proposes splitting `Encoding` into separate read and write interfaces and moving the corresponding runtime into `reader` / `writer`, leaving `core` as the model-only module it was originally intended to be. PR #27's escape hatches collapse as a side effect of co-locating the decoder runtime with the byte source. Includes: - Root-cause analysis of the current `core` layout (5 concrete smells) - Target module split with the `Array` hierarchy moving to `reader` (writer only touches `NullableData`, confirmed by audit) — only `NullableData` and `BoundedSegment` stay in `core` proper - Registry split into distinct `ReadRegistry` and `WriteRegistry` types passed alongside the entry points (not folded into options records) — read-only callers never pull the `writer` module onto their classpath - 6-phase migration plan with effort estimates (~9 person-days plus CI fallout) - Consequences (positive and negative) and risks-to-manage - Rejected alternatives (JPMS hide, move FlatSegmentDecoder alone, adopt Arrow codec SPI, status-quo + docs) Status: Proposed. No code changes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Records the trade-offs for unsealing DType + Layout (and adding a
compute SPI) as a separate decision from ADR 0001's module split.
Status: Deferred — awaiting a real downstream consumer use case, per
the existing TODO.md:215 guidance ("don't pre-open these without a
use case"). The ADR captures:
- Why sealed-by-default is correct today (exhaustive switches, free
equality, no premature abstraction, CLAUDE.md tone alignment)
- When that default flips (downstream consumer with custom logical
type, Rust ships variants Java cannot follow with sealed additions)
- Three shapes for a future un-deferral (open SPI mirroring Rust;
Extension-plugin elevation; defer to JDK pattern-matching evolution)
- Four decision criteria for un-deferring: named consumer, spec for
the variant, confirmation Extension does not fit, plan for the
switch-exhaustiveness implications
- Compute layer deferred entirely — no Java query / pruning layer yet
to plug compute into
Cross-links to ADR 0001 (module split) and compatibility.md (which
already records DType::Union as one variant Java does not yet decode).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
07f72b5 to
374ad04
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Proposes splitting
Encodinginto separate read/write interfaces and moving the corresponding runtime intoreader/writer, leavingcoreas the model-only module it was originally intended to be.PR #27's 33
unwrapForSubParseraudit-trail sites are a strong signal thatcoreis hosting the read runtime, not just the data model. Cross-module byte hand-offs force public escape-hatch APIs (VortexHandle.slice,Registry.decodeAsSegment) that no architectural wrapper can really cure.Why this ADR
VortexHandle.slicereturning a rawMemorySegmentis a symptom; the disease is the module layout.unwrapForSubParsersites collapse as a side effect of co-locating the decoder runtime with the byte source.What the ADR contains
corelayout (5 concrete smells).core→ model only;reader→ read runtime + decoders;writer→ write runtime + encoders).FlatSegmentDecoderalone, adopt Arrow codec SPI, status-quo + docs).Status
This PR adds only the ADR. No code changes. The ADR is marked
Status: Proposed.Test plan
Proposed, escalate toAccepted, or close asRejected.🤖 Generated with Claude Code