SKaiNET carries two storage abstractions:
TensorData (skainet-lang-core/.../tensor/data/) — the live one. Every Tensor holds one; backends dispatch by downcasting to concrete classes/markers (is Q4_KTensorData -> .packedData); all common-code storage is heap arrays.
TensorStorage (.../tensor/storage/, 20 files) — a designed descriptor layer with the right concepts (BufferHandle.{Owned,Borrowed,Aliased,FileBacked,DeviceResident}, Placement/MemoryDomain, TensorEncoding, MemoryPlanner, StorageSpec) whose own KDoc says "new loaders, planners, and backends should target TensorStorage directly" — but which no Tensor ever holds. StorageSpec has zero consumers; the planner is never consulted at any allocation; Aliased is never produced; FileBacked and DeviceResident throw in every consumer; LogicalDType.fromDType has no inverse, so the layer structurally cannot back Tensor<T> today.
The result is a set of related, recurring costs:
An SKEEP-003 draft (PR to follow) lays out the analysis and two candidate end-states — (a) TensorStorage becomes the single byte-owner and TensorData a typed view protocol over it; (b) TensorData stays primary and absorbs BufferHandle/Placement, retiring the parallel descriptor — deliberately without a recommendation: the trade-off (dispatch rewrite + dtype coherence vs minimal churn + status quo dispatch) is a maintainer decision. Both directions share two prerequisites (two-way LogicalDType ↔ DType bridge; decide StorageSpec's fate) and one hard constraint: the packed-encoding system (7 GGML block formats, ternary, TurboQuant, kernel dispatch, StableHLO skainet.tensor_encodings export) must survive bit-identically.
Mechanical bugs found during the same audit are filed separately (TensorStorageFactory contract violations, GGUF encoding mapping dropping five formats, transfer-API gaps, rank-broken copyToFloatArray default, memory-diagnostics paper-cuts) — they are fixable under either end-state.
SKaiNET carries two storage abstractions:
TensorData(skainet-lang-core/.../tensor/data/) — the live one. EveryTensorholds one; backends dispatch by downcasting to concrete classes/markers (is Q4_KTensorData -> .packedData); all common-code storage is heap arrays.TensorStorage(.../tensor/storage/, 20 files) — a designed descriptor layer with the right concepts (BufferHandle.{Owned,Borrowed,Aliased,FileBacked,DeviceResident},Placement/MemoryDomain,TensorEncoding,MemoryPlanner,StorageSpec) whose own KDoc says "new loaders, planners, and backends should targetTensorStoragedirectly" — but which noTensorever holds.StorageSpechas zero consumers; the planner is never consulted at any allocation;Aliasedis never produced;FileBackedandDeviceResidentthrow in every consumer;LogicalDType.fromDTypehas no inverse, so the layer structurally cannot backTensor<T>today.The result is a set of related, recurring costs:
Placement.Residencymodels but nothing uses)SlicedTensorViewindex remap vsBufferHandle.Aliasedbyte range)DTypeKClass generic,LogicalDTypeenum,TensorEncoding), with packed tensors erasing their logical dtype entirely (Q4_KTensorData : TensorData<DType, Byte>— a logically-FP32 weight is not typed as such; ops find it by class check)createRandomAccessSourcereturns null on Android: full-file heap load OOMs on a 138 MiB GGUF (working ~40-line fix included) #922, SKEEP-002) keeps landing at the edges because the middle isn't wiredAn SKEEP-003 draft (PR to follow) lays out the analysis and two candidate end-states — (a)
TensorStoragebecomes the single byte-owner andTensorDataa typed view protocol over it; (b)TensorDatastays primary and absorbsBufferHandle/Placement, retiring the parallel descriptor — deliberately without a recommendation: the trade-off (dispatch rewrite + dtype coherence vs minimal churn + status quo dispatch) is a maintainer decision. Both directions share two prerequisites (two-wayLogicalDType ↔ DTypebridge; decideStorageSpec's fate) and one hard constraint: the packed-encoding system (7 GGML block formats, ternary, TurboQuant, kernel dispatch, StableHLOskainet.tensor_encodingsexport) must survive bit-identically.Mechanical bugs found during the same audit are filed separately (TensorStorageFactory contract violations, GGUF encoding mapping dropping five formats, transfer-API gaps, rank-broken
copyToFloatArraydefault, memory-diagnostics paper-cuts) — they are fixable under either end-state.