tensorfs 0.3.70__tar.gz → 0.3.71__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. {tensorfs-0.3.70 → tensorfs-0.3.71}/Cargo.lock +2 -2
  2. {tensorfs-0.3.70 → tensorfs-0.3.71}/Cargo.toml +1 -1
  3. {tensorfs-0.3.70 → tensorfs-0.3.71}/PKG-INFO +1 -1
  4. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/ingest.rs +15 -7
  5. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/companion_tests.rs +44 -0
  6. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived.rs +48 -0
  7. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/fill.rs +95 -0
  8. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/convert.rs +148 -5
  9. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/fingerprint.rs +5 -2
  10. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/journal.rs +10 -0
  11. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/mod.rs +2 -0
  12. tensorfs-0.3.71/crates/tensorfs-core/src/ingest/narrow.rs +178 -0
  13. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/preflight.rs +3 -3
  14. tensorfs-0.3.71/crates/tensorfs-core/src/ingest/routes/sdxl.routes.json +1 -0
  15. tensorfs-0.3.71/crates/tensorfs-core/src/ingest/routes/sdxl.spec.json +51 -0
  16. tensorfs-0.3.71/crates/tensorfs-core/src/ingest/routes.rs +382 -0
  17. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/source.rs +184 -16
  18. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/transaction.rs +76 -21
  19. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/providers.rs +93 -4
  20. tensorfs-0.3.71/crates/tensorfs-core/tests/as_is.rs +334 -0
  21. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/civitai_sdxl_profile.rs +18 -2
  22. tensorfs-0.3.71/crates/tensorfs-core/tests/routed_single_file.rs +297 -0
  23. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/source_plan.rs +35 -14
  24. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/src/ingest.rs +27 -0
  25. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/src/lib.rs +2 -0
  26. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/src/store.rs +13 -7
  27. {tensorfs-0.3.70 → tensorfs-0.3.71}/pyproject.toml +1 -1
  28. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/__init__.py +4 -0
  29. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/_ext.pyi +8 -0
  30. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/Cargo.toml +0 -0
  31. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/build.rs +0 -0
  32. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/examples/h3-swiglu-layout.md +0 -0
  33. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/examples/optional-cache-backfill.md +0 -0
  34. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/examples/resident-conversion.md +0 -0
  35. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/examples/resident_conversion_profile.rs +0 -0
  36. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/asset_update.rs +0 -0
  37. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/b64.rs +0 -0
  38. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +0 -0
  39. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/conform.rs +0 -0
  40. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
  41. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/main.rs +0 -0
  42. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/rd.rs +0 -0
  43. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/repo.rs +0 -0
  44. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
  45. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
  46. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/cache_roots.rs +0 -0
  47. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/canon.rs +0 -0
  48. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/capability.rs +0 -0
  49. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/catalog/lock.rs +0 -0
  50. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/catalog.rs +0 -0
  51. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/cbor.rs +0 -0
  52. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/checkpoint.rs +0 -0
  53. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/checkpoint_root.rs +0 -0
  54. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/corpus.rs +0 -0
  55. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/adoption.rs +0 -0
  56. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/estimate.rs +0 -0
  57. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/graft_tests.rs +0 -0
  58. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/group_commit_tests.rs +0 -0
  59. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/part_rows_tests.rs +0 -0
  60. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/progress.rs +0 -0
  61. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/resume_tests.rs +0 -0
  62. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/retention.rs +0 -0
  63. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/derived/roots.rs +0 -0
  64. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/descriptors.rs +0 -0
  65. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/disk.rs +0 -0
  66. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/dtype.rs +0 -0
  67. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/durability.rs +0 -0
  68. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/err.rs +0 -0
  69. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/fetch.rs +0 -0
  70. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/fit.rs +0 -0
  71. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/gc.rs +0 -0
  72. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/header.rs +0 -0
  73. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/home.rs +0 -0
  74. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ids.rs +0 -0
  75. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
  76. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/custody.rs +0 -0
  77. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
  78. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/h3_lora.rs +0 -0
  79. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
  80. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/jcs.rs +0 -0
  81. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/lib.rs +0 -0
  82. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/limits.rs +0 -0
  83. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/machine.rs +0 -0
  84. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/manifest.rs +0 -0
  85. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/meta.rs +0 -0
  86. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/project.rs +0 -0
  87. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/read.rs +0 -0
  88. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/receipt.rs +0 -0
  89. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/reclaim.rs +0 -0
  90. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/registry.rs +0 -0
  91. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/relation.rs +0 -0
  92. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/repo_cache/identity.rs +0 -0
  93. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/repo_cache.rs +0 -0
  94. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/repository.rs +0 -0
  95. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/sha256.rs +0 -0
  96. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/source_artifact.rs +0 -0
  97. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/spec.rs +0 -0
  98. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/staging.rs +0 -0
  99. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/stats.rs +0 -0
  100. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/storage.rs +0 -0
  101. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/store.rs +0 -0
  102. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/api.rs +0 -0
  103. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/http.rs +0 -0
  104. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/http_reuse_tests.rs +0 -0
  105. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/hub.rs +0 -0
  106. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/ledger.rs +0 -0
  107. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/memory.rs +0 -0
  108. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/mod.rs +0 -0
  109. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/pace.rs +0 -0
  110. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/policy.rs +0 -0
  111. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/prefix.rs +0 -0
  112. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/pull.rs +0 -0
  113. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/push.rs +0 -0
  114. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/ranged.rs +0 -0
  115. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/speculate.rs +0 -0
  116. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/transport/tests.rs +0 -0
  117. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/unsynced.rs +0 -0
  118. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/src/vectors.rs +0 -0
  119. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/additive_fields.rs +0 -0
  120. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/anima_hf_profile.rs +0 -0
  121. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/checkpoint_roots.rs +0 -0
  122. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fd_budget.rs +0 -0
  123. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fd_headroom.rs +0 -0
  124. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fetch_url_progress.rs +0 -0
  125. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fit.rs +0 -0
  126. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
  127. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -0
  128. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -0
  129. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -0
  130. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
  131. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
  132. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
  133. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/foreign_json.rs +0 -0
  134. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/h3_lora.rs +0 -0
  135. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/h3_swiglu.rs +0 -0
  136. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/home.rs +0 -0
  137. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/import_tree.rs +0 -0
  138. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/instrument_profiles.rs +0 -0
  139. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/liveness.rs +0 -0
  140. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/qwen_image21_profile.rs +0 -0
  141. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/read_plan.rs +0 -0
  142. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/reclaim.rs +0 -0
  143. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/reclaim_run.rs +0 -0
  144. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/repo_cache.rs +0 -0
  145. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/repo_store.rs +0 -0
  146. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/resident_admission.rs +0 -0
  147. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/sha256_backends.rs +0 -0
  148. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/sharded_cas.rs +0 -0
  149. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/source_artifacts.rs +0 -0
  150. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/source_download.rs +0 -0
  151. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/source_prefixes.rs +0 -0
  152. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/source_preflight.rs +0 -0
  153. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/staging.rs +0 -0
  154. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/store_boundaries.rs +0 -0
  155. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/tensor_schema.rs +0 -0
  156. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/transfer_memory.rs +0 -0
  157. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/trust_index.rs +0 -0
  158. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/version.rs +0 -0
  159. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-core/tests/write_through.rs +0 -0
  160. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/Cargo.toml +0 -0
  161. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/src/docs.rs +0 -0
  162. {tensorfs-0.3.70 → tensorfs-0.3.71}/crates/tensorfs-py/src/errors.rs +0 -0
  163. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/_derived_channel.py +0 -0
  164. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/_source_channel.py +0 -0
  165. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/_tensors.py +0 -0
  166. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/derived.py +0 -0
  167. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/errors.py +0 -0
  168. {tensorfs-0.3.70 → tensorfs-0.3.71}/python/tensorfs/py.typed +0 -0
@@ -439,7 +439,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
439
439
 
440
440
  [[package]]
441
441
  name = "tensorfs-core"
442
- version = "0.3.70"
442
+ version = "0.3.71"
443
443
  dependencies = [
444
444
  "fs2",
445
445
  "libc",
@@ -454,7 +454,7 @@ dependencies = [
454
454
 
455
455
  [[package]]
456
456
  name = "tensorfs-py"
457
- version = "0.3.70"
457
+ version = "0.3.71"
458
458
  dependencies = [
459
459
  "pyo3",
460
460
  "tensorfs-core",
@@ -3,5 +3,5 @@ resolver = "2"
3
3
  members = ["crates/tensorfs-core", "crates/tensorfs-py"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.3.70"
6
+ version = "0.3.71"
7
7
  edition = "2021"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensorfs
3
- Version: 0.3.70
3
+ Version: 0.3.71
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Rust
@@ -445,7 +445,7 @@ pub fn cmd_bank(dialect: &str, converter: &str, f: &Flags) -> ExitCode {
445
445
  let mut reviewed = Vec::new();
446
446
  for (component, path) in &srcs {
447
447
  let (full, raw) = ok!(source_core::read_carrier_at(path));
448
- let h = if conv.name == "single_file.identity/1" {
448
+ let h = if conv.dialect == "safetensors.single_file" {
449
449
  ok!(convert::single_file_component(component, &full))
450
450
  } else {
451
451
  full
@@ -584,11 +584,11 @@ pub fn cmd_bank(dialect: &str, converter: &str, f: &Flags) -> ExitCode {
584
584
  .collect::<Vec<_>>()
585
585
  .join(",");
586
586
  let variant = flag(f, "spec-variant").and_then(|value| value.parse().ok());
587
- let mut prepared = match source_core::prepare_with_registry(
587
+ let mut prepared = match source_core::prepare(
588
588
  &target,
589
589
  &unnamed(&srcs),
590
590
  &CarrierSet::default(),
591
- &reg,
591
+ Some(&reg),
592
592
  variant,
593
593
  ) {
594
594
  Ok(prepared) => prepared,
@@ -849,17 +849,22 @@ fn prepare_closed_source_plan(
849
849
  if closed.registry != BUILTIN_REGISTRY {
850
850
  flags.push(("registry".to_string(), closed.registry.clone()));
851
851
  }
852
+ let as_is = closed.converter == convert::IDENTITY;
853
+ if as_is {
854
+ flags.push(("source-profile".to_string(), source_core::AS_IS.to_string()));
855
+ }
852
856
  for (component, source) in &closed.sources {
853
857
  flags.push((
854
858
  "source".to_string(),
855
859
  format!("{component}={}", source.path.to_string_lossy()),
856
860
  ));
857
861
  }
858
- let mut prepared = source_core::prepare_with_registry(
862
+ // The plan was re-derived above, so its converter is the planner's: as-is has no registry.
863
+ let mut prepared = source_core::prepare(
859
864
  &closed.target,
860
865
  &closed.sources,
861
866
  &closed.set,
862
- &registry,
867
+ (!as_is).then_some(&registry),
863
868
  None,
864
869
  )
865
870
  .map_err(bail)?;
@@ -989,15 +994,17 @@ pub(crate) fn construction_order(f: &Flags) -> Result<Vec<(String, String)>, Exi
989
994
 
990
995
  /// Headers in, plan out. The one function `plan`, `run` and the worker all go through, so
991
996
  /// a preview and a run cannot disagree about what was going to happen.
997
+ /// `--source-profile as-is/1` stores the sources as they are, unclassified.
992
998
  fn prepare(f: &Flags, target: &str) -> Result<Prepared, ExitCode> {
993
999
  let sources = sources(f)?;
994
1000
  let registry = load_registry(f)?;
995
1001
  let variant = flag(f, "spec-variant").and_then(|value| value.parse().ok());
996
- source_core::prepare_with_registry(
1002
+ let as_is = flag(f, "source-profile") == Some(source_core::AS_IS);
1003
+ source_core::prepare(
997
1004
  target,
998
1005
  &unnamed(&sources),
999
1006
  &CarrierSet::default(),
1000
- &registry,
1007
+ (!as_is).then_some(&registry),
1001
1008
  variant,
1002
1009
  )
1003
1010
  .map_err(bail)
@@ -1206,6 +1213,7 @@ pub fn cmd_run(root: &Path, target: &str, f: &Flags) -> ExitCode {
1206
1213
  | "tenant"
1207
1214
  | "isolation-tier"
1208
1215
  | "checkpoint-bytes"
1216
+ | "source-profile"
1209
1217
  ) {
1210
1218
  argv.push(format!("--{k}"));
1211
1219
  argv.push(v.clone());
@@ -196,6 +196,50 @@ fn ordinary_companions_survive_derivation_without_copying_tensor_backing_files()
196
196
  std::fs::remove_dir_all(store.root()).unwrap();
197
197
  }
198
198
 
199
+ #[test]
200
+ fn a_verified_store_object_is_a_companion_by_reference_and_never_a_new_byte() {
201
+ let (store, meta, id) = fixture();
202
+ let vocab = vec![0x7b; 256 << 10]; // over the inline bound: references have none
203
+ let object = store
204
+ .put_stream(
205
+ &mut vocab.as_slice(),
206
+ Some(&ObjectRef::of(&vocab)),
207
+ &Fault::default(),
208
+ )
209
+ .unwrap()
210
+ .obj;
211
+ let mut d = super::tests::created_declaration();
212
+ d.objects = vec![("tokenizer/vocab.json".into(), object.clone())];
213
+ let encoded = d.canonical_work_bytes().unwrap();
214
+ assert_eq!(
215
+ Declaration::parse_text(std::str::from_utf8(&encoded).unwrap()).unwrap(),
216
+ d
217
+ );
218
+ let writer = begin(&store, &meta, &id, 1, d.clone(), None).unwrap();
219
+ write_weight(&store, &meta, &id);
220
+ let receipt = commit(&store, &meta, &id, 1).unwrap();
221
+ release(&meta, writer);
222
+ assert!(!receipt.added_objects.contains(&object));
223
+ let header = checkpoint::load_header(&store, &receipt.header).unwrap();
224
+ let (name, asset) = &header.assets[0];
225
+ assert_eq!(
226
+ (name.as_str(), &asset.segments),
227
+ ("tokenizer/vocab.json", &vec![object])
228
+ );
229
+ let mut read = Vec::new();
230
+ checkpoint::read_asset(&store, name, asset, &mut read).unwrap();
231
+ assert_eq!(read, vocab);
232
+
233
+ // An object this Store does not hold is refused at commit, never published.
234
+ let next = format!("sha256:{}", "c3".repeat(32));
235
+ d.objects = vec![("tokenizer/vocab.json".into(), ObjectRef::of(b"absent"))];
236
+ let writer = begin(&store, &meta, &next, 1, d, None).unwrap();
237
+ write_weight(&store, &meta, &next);
238
+ assert!(commit(&store, &meta, &next, 1).is_err());
239
+ release(&meta, writer);
240
+ std::fs::remove_dir_all(store.root()).unwrap();
241
+ }
242
+
199
243
  #[test]
200
244
  fn companion_paths_size_count_and_quotas_are_native_refusals() {
201
245
  for path in [
@@ -181,6 +181,9 @@ pub struct Declaration {
181
181
  pub configs: Vec<ConfigDeclaration>,
182
182
  /// Bounded immutable ordinary companion files, locked into the work intent.
183
183
  pub files: Vec<(String, Vec<u8>)>,
184
+ /// Companion files that are already verified Store objects (a pinned tokenizer), named
185
+ /// by reference: no bytes in the intent, none new in the output.
186
+ pub objects: Vec<(String, ObjectRef)>,
184
187
  pub order: Vec<(String, String)>,
185
188
  pub max_new_bytes: u64,
186
189
  }
@@ -248,6 +251,19 @@ impl Declaration {
248
251
  }
249
252
 
250
253
  validate_files(&mut self.files)?;
254
+ self.objects.sort_by(|a, b| a.0.cmp(&b.0));
255
+ let mut paths: Vec<String> = self
256
+ .files
257
+ .iter()
258
+ .map(|(path, _)| path.clone())
259
+ .chain(std::iter::once("model.cozytensors".to_string()))
260
+ .collect();
261
+ for (path, object) in &self.objects {
262
+ crate::manifest::check_path(path)?;
263
+ crate::ids::hex64("companion object", &object.sha256)?;
264
+ paths.push(path.clone());
265
+ }
266
+ validate_companion_paths(&mut paths)?;
251
267
 
252
268
  for source in &self.sources {
253
269
  name("source alias", &source.alias)?;
@@ -563,6 +579,15 @@ impl Declaration {
563
579
  ));
564
580
  }
565
581
  }
582
+ let mut objects = Vec::new();
583
+ if let Some(value) = f.opt("objects") {
584
+ for (path, value) in as_obj("DerivedDeclaration", "objects", value)? {
585
+ objects.push((
586
+ path.clone(),
587
+ ObjectRef::from_value("companion object", value)?,
588
+ ));
589
+ }
590
+ }
566
591
  let work_fingerprint = f
567
592
  .opt("work_fingerprint")
568
593
  .map(|value| {
@@ -710,6 +735,7 @@ impl Declaration {
710
735
  components,
711
736
  configs,
712
737
  files,
738
+ objects,
713
739
  order,
714
740
  max_new_bytes,
715
741
  })
@@ -873,6 +899,17 @@ impl Declaration {
873
899
  ),
874
900
  ));
875
901
  }
902
+ if !self.objects.is_empty() {
903
+ fields.push((
904
+ "objects",
905
+ Value::map(
906
+ self.objects
907
+ .iter()
908
+ .map(|(path, object)| (path.clone(), object.to_value()))
909
+ .collect(),
910
+ ),
911
+ ));
912
+ }
876
913
  if let Some(fingerprint) = &self.work_fingerprint {
877
914
  fields.push(("work_fingerprint", Value::str(fingerprint.clone())));
878
915
  }
@@ -947,6 +984,7 @@ fn companion_files(
947
984
  .files
948
985
  .iter()
949
986
  .map(|(path, _)| path.as_str())
987
+ .chain(declaration.objects.iter().map(|(path, _)| path.as_str()))
950
988
  .collect();
951
989
  for source in sources {
952
990
  let mut backing: HashSet<_> = source
@@ -989,6 +1027,12 @@ fn companion_files(
989
1027
  .iter()
990
1028
  .map(|(path, data)| (path.clone(), Entry::File(ObjectRef::of(data)))),
991
1029
  );
1030
+ files.extend(
1031
+ declaration
1032
+ .objects
1033
+ .iter()
1034
+ .map(|(path, object)| (path.clone(), Entry::File(object.clone()))),
1035
+ );
992
1036
  let mut paths: Vec<_> = files
993
1037
  .keys()
994
1038
  .cloned()
@@ -2197,6 +2241,7 @@ fn inspect_retained_source(
2197
2241
  let alias = "source".to_string();
2198
2242
  let mut declaration = Declaration {
2199
2243
  files: Vec::new(),
2244
+ objects: Vec::new(),
2200
2245
  work_fingerprint: None,
2201
2246
  sources: vec![Source {
2202
2247
  alias: alias.clone(),
@@ -3932,6 +3977,7 @@ mod tests {
3932
3977
  .object_id();
3933
3978
  Declaration {
3934
3979
  files: Vec::new(),
3980
+ objects: Vec::new(),
3935
3981
  work_fingerprint: Some(format!("sha256:{}", "44".repeat(32))),
3936
3982
  sources: Vec::new(),
3937
3983
  components: vec![ComponentDeclaration {
@@ -3961,6 +4007,7 @@ mod tests {
3961
4007
  fn inherited_declaration(manifest: ObjectRef) -> Declaration {
3962
4008
  Declaration {
3963
4009
  files: Vec::new(),
4010
+ objects: Vec::new(),
3964
4011
  work_fingerprint: Some(format!("sha256:{}", "44".repeat(32))),
3965
4012
  sources: vec![Source {
3966
4013
  alias: "source".into(),
@@ -4574,6 +4621,7 @@ mod tests {
4574
4621
  1,
4575
4622
  Declaration {
4576
4623
  files: Vec::new(),
4624
+ objects: Vec::new(),
4577
4625
  work_fingerprint: Some(format!("sha256:{}", "44".repeat(32))),
4578
4626
  sources: vec![Source {
4579
4627
  alias: "source".into(),
@@ -109,6 +109,13 @@ pub enum Xform {
109
109
  /// Bytes in one share unit — derived from the source run, never assumed.
110
110
  unit_bytes: u64,
111
111
  },
112
+ /// A row-major `[rows, cols]` matrix becomes `[cols, rows]`. Every element moves on its
113
+ /// own, so this is gather-class by construction: it is applied buffered, never as runs.
114
+ Transpose {
115
+ rows: u64,
116
+ cols: u64,
117
+ elem_bytes: u64,
118
+ },
112
119
  }
113
120
 
114
121
  impl Xform {
@@ -122,6 +129,11 @@ impl Xform {
122
129
  unit_bytes,
123
130
  ..
124
131
  } => groups * (shares[0] + shares[1] + shares[2]) * unit_bytes,
132
+ Xform::Transpose {
133
+ rows,
134
+ cols,
135
+ elem_bytes,
136
+ } => rows * cols * elem_bytes,
125
137
  }
126
138
  }
127
139
 
@@ -135,6 +147,36 @@ impl Xform {
135
147
  take,
136
148
  unit_bytes,
137
149
  } => groups * shares[*take as usize] * unit_bytes,
150
+ Xform::Transpose { .. } => self.in_bytes(),
151
+ }
152
+ }
153
+
154
+ /// Whether the transform streams its source runs straight out of the carrier. A
155
+ /// transpose reads its bounded source once and reorders it in memory instead.
156
+ pub fn streams(&self) -> bool {
157
+ !matches!(self, Xform::Transpose { .. })
158
+ }
159
+
160
+ /// `(bytes, runs, class)` of the decomposition, without materializing element runs.
161
+ pub fn census(&self) -> (u64, usize, Class) {
162
+ match self {
163
+ Xform::Transpose {
164
+ rows,
165
+ cols,
166
+ elem_bytes,
167
+ } => (
168
+ rows * cols * elem_bytes,
169
+ (rows * cols) as usize,
170
+ if *elem_bytes >= GATHER_FLOOR_BYTES {
171
+ Class::LongRun
172
+ } else {
173
+ Class::Gather
174
+ },
175
+ ),
176
+ _ => {
177
+ let d = self.runs();
178
+ (d.bytes, d.runs.len(), d.class)
179
+ }
138
180
  }
139
181
  }
140
182
 
@@ -175,6 +217,21 @@ impl Xform {
175
217
  .collect(),
176
218
  )
177
219
  }
220
+ Xform::Transpose {
221
+ rows,
222
+ cols,
223
+ elem_bytes,
224
+ } => Decomposition::of(
225
+ (0..*cols)
226
+ .flat_map(|j| {
227
+ (0..*rows).map(move |i| Run {
228
+ src_off: (i * cols + j) * elem_bytes,
229
+ dest_off: (j * rows + i) * elem_bytes,
230
+ len: *elem_bytes,
231
+ })
232
+ })
233
+ .collect(),
234
+ ),
178
235
  }
179
236
  }
180
237
 
@@ -206,6 +263,24 @@ impl Xform {
206
263
  ),
207
264
  );
208
265
  }
266
+ if let Xform::Transpose {
267
+ rows,
268
+ cols,
269
+ elem_bytes,
270
+ } = *self
271
+ {
272
+ let (rows, cols, e) = (rows as usize, cols as usize, elem_bytes as usize);
273
+ for (i, row) in src.chunks_exact(cols * e).enumerate() {
274
+ for (j, value) in row.chunks_exact(e).enumerate() {
275
+ dest[(j * rows + i) * e..][..e].copy_from_slice(value);
276
+ }
277
+ }
278
+ return Ok(Decomposition {
279
+ runs: Vec::new(),
280
+ class: Class::Gather,
281
+ bytes: self.out_bytes(),
282
+ });
283
+ }
209
284
  let d = self.runs();
210
285
  for r in &d.runs {
211
286
  let (s, o, n) = (r.src_off as usize, r.dest_off as usize, r.len as usize);
@@ -229,6 +304,26 @@ impl Xform {
229
304
  /// indexing and the three members must reassemble the source bit-for-bit.
230
305
  pub fn reassembles(&self, src: &[u8]) -> Result<bool> {
231
306
  match self {
307
+ Xform::Transpose {
308
+ rows,
309
+ cols,
310
+ elem_bytes,
311
+ } => {
312
+ let mut once = Vec::new();
313
+ self.apply(src, &mut once)?;
314
+ let mut back = Vec::new();
315
+ Xform::Transpose {
316
+ rows: *cols,
317
+ cols: *rows,
318
+ elem_bytes: *elem_bytes,
319
+ }
320
+ .apply(&once, &mut back)?;
321
+ Ok(back == src
322
+ && self.runs().runs.iter().all(|r| {
323
+ once[r.dest_off as usize..][..r.len as usize]
324
+ == src[r.src_off as usize..][..r.len as usize]
325
+ }))
326
+ }
232
327
  Xform::SwapHalves { .. } => {
233
328
  let mut swapped = Vec::new();
234
329
  self.apply(src, &mut swapped)?;
@@ -51,9 +51,25 @@ pub struct Converter {
51
51
  /// Quarry-derived geometry that has NOT yet met the real bytes it describes (tfs-010).
52
52
  /// Stated in the type so a receipt cannot quietly claim more than the evidence supports.
53
53
  pub validated_on_real_bytes: bool,
54
+ /// `(state, dialect of the stored keys)` for the output's `normalization` config:
55
+ /// `raw` keys need a consumer that reads that dialect, `normalized` ones are canonical.
56
+ /// `None` records nothing (reviewed outputs that predate the record).
57
+ pub normalization: Option<(&'static str, &'static str)>,
58
+ /// The one declared value change a converter may make: floating sources narrow to this
59
+ /// dtype, IEEE round-to-nearest-even, and a finite value it cannot hold refuses
60
+ /// NUMBER_RANGE. `None` moves bytes only.
61
+ pub lane: Option<Dtype>,
62
+ /// The pinned repository (`hf://org/repo@<commit>`, a Diffusers pipeline) whose index,
63
+ /// configs, scheduler and tokenizers the output needs when its source carries none.
64
+ pub reference: Option<&'static str>,
54
65
  }
55
66
 
56
- pub const CONVERTERS: [Converter; 5] = [
67
+ /// The header config an output's [`Converter::normalization`] is recorded under.
68
+ pub const NORMALIZATION: &str = "normalization";
69
+ /// The converter for a source no reviewed profile recognizes: its keys, stored as they are.
70
+ pub const IDENTITY: &str = "identity/1";
71
+
72
+ pub const CONVERTERS: [Converter; 7] = [
57
73
  Converter {
58
74
  name: "diffusers.identity/1",
59
75
  dialect: "safetensors.diffusers",
@@ -62,6 +78,9 @@ pub const CONVERTERS: [Converter; 5] = [
62
78
  becomes one logical tensor; `.weight_scale` siblings fold into their base as \
63
79
  encoding ROLES; marker tensors are dropped. Bytes stream through untouched.",
64
80
  validated_on_real_bytes: true,
81
+ normalization: None,
82
+ lane: None,
83
+ reference: None,
65
84
  },
66
85
  Converter {
67
86
  name: "single_file.identity/1",
@@ -70,6 +89,9 @@ pub const CONVERTERS: [Converter; 5] = [
70
89
  doc: "One file carrying several components, split on the reviewed component prefix \
71
90
  map. Same byte path as the diffusers converter — packaging is not identity.",
72
91
  validated_on_real_bytes: true,
92
+ normalization: None,
93
+ lane: None,
94
+ reference: None,
73
95
  },
74
96
  Converter {
75
97
  name: "cozytensors.inherit/1",
@@ -78,6 +100,9 @@ pub const CONVERTERS: [Converter; 5] = [
78
100
  doc: "An already-canonical source. Every untouched tensor carries by OBJECT \
79
101
  REFERENCE; nothing is re-hashed and nothing is re-uploaded.",
80
102
  validated_on_real_bytes: true,
103
+ normalization: None,
104
+ lane: None,
105
+ reference: None,
81
106
  },
82
107
  Converter {
83
108
  name: "h3.lora/1",
@@ -85,6 +110,9 @@ pub const CONVERTERS: [Converter; 5] = [
85
110
  class: Class::Permutation,
86
111
  doc: "Native H3 LoRA A/B and Kohya down/up factors: split head-interleaved QKV B rows, swap SwiGLU B halves, preserve A and alpha without arithmetic.",
87
112
  validated_on_real_bytes: false,
113
+ normalization: None,
114
+ lane: None,
115
+ reference: None,
88
116
  },
89
117
  Converter {
90
118
  name: "h3.native/2",
@@ -106,9 +134,59 @@ pub const CONVERTERS: [Converter; 5] = [
106
134
  // pinned official converter requires. The complete trained Ref2VA block0
107
135
  // fc1 (308281344 B) converted to e7cf97ae...3b19; fc2 stayed byte-identical.
108
136
  validated_on_real_bytes: true,
137
+ normalization: None,
138
+ lane: None,
139
+ reference: None,
140
+ },
141
+ Converter {
142
+ name: IDENTITY,
143
+ dialect: "safetensors",
144
+ class: Class::Identity,
145
+ doc: "An unrecognized source, stored as it is: every key becomes one plain tensor \
146
+ under its own name and dtype. Nothing is folded, dropped or renamed, so a \
147
+ consumer that needs another spelling normalizes it.",
148
+ validated_on_real_bytes: true,
149
+ normalization: Some(("raw", "safetensors")),
150
+ lane: None,
151
+ reference: None,
152
+ },
153
+ Converter {
154
+ name: super::routes::SDXL,
155
+ dialect: "safetensors.single_file",
156
+ class: Class::Permutation,
157
+ doc: "An SDXL single-file checkpoint becomes the Diffusers constructor's checkpoint: \
158
+ the generated route table rekeys every tensor into constructor order, splits \
159
+ OpenCLIP's fused in_proj into q|k|v runs, transposes its text_projection, \
160
+ squeezes 1x1-conv attention to linear and drops CLIP position IDs and \
161
+ logit_scale. bf16/f32 sources narrow to f16. Pipeline index, configs and \
162
+ tokenizers come from the pinned SDXL base reference.",
163
+ // The generated table equals packages-v2 sdxl normalization.json route for route, the
164
+ // mapping the sdxl normalize job served real Civitai checkpoints with.
165
+ validated_on_real_bytes: true,
166
+ normalization: Some(("normalized", "diffusers")),
167
+ lane: Some(Dtype::F16),
168
+ reference: Some(
169
+ "hf://stabilityai/stable-diffusion-xl-base-1.0@462165984030d82259a11f4367a4eed129e94a7b",
170
+ ),
109
171
  },
110
172
  ];
111
173
 
174
+ /// The `normalization` config the output of `converter` carries, if it records one.
175
+ pub fn normalization_config(converter: &str) -> Option<(String, Vec<u8>)> {
176
+ let converter_row = CONVERTERS.iter().find(|c| c.name == converter)?;
177
+ let (state, dialect) = converter_row.normalization?;
178
+ let mut fields = vec![
179
+ ("converter", crate::canon::Value::str(converter)),
180
+ ("dialect", crate::canon::Value::str(dialect)),
181
+ ("state", crate::canon::Value::str(state)),
182
+ ];
183
+ if let Some(reference) = converter_row.reference {
184
+ fields.push(("reference", crate::canon::Value::str(reference)));
185
+ }
186
+ let record = crate::canon::Value::obj(fields);
187
+ Some((NORMALIZATION.to_string(), crate::canon::write(&record)))
188
+ }
189
+
112
190
  pub fn converter(name: &str) -> Result<&'static Converter> {
113
191
  match CONVERTERS.iter().find(|c| c.name == name) {
114
192
  Some(c) => Ok(c),
@@ -359,11 +437,11 @@ impl Plan {
359
437
  for o in &self.ops {
360
438
  for r in &o.roles {
361
439
  if let Bytes::Permute { xform, .. } = &r.bytes {
362
- let d = xform.runs();
440
+ let (moved, count, class) = xform.census();
363
441
  ops += 1;
364
- bytes += d.bytes;
365
- runs += d.runs.len();
366
- gather |= d.class == crate::fill::Class::Gather;
442
+ bytes += moved;
443
+ runs += count;
444
+ gather |= class == crate::fill::Class::Gather;
367
445
  }
368
446
  }
369
447
  }
@@ -968,6 +1046,12 @@ fn plan_carrier(
968
1046
  }
969
1047
  return super::h3_lora::plan(component, file, h, cands.plain, p);
970
1048
  }
1049
+ if conv.name == IDENTITY {
1050
+ return plan_as_is(component, file, h, allowed, cands.plain, p);
1051
+ }
1052
+ if let Some(table) = super::routes::table(conv.name) {
1053
+ return super::routes::plan(conv, table, component, file, h, allowed, cands.plain, p);
1054
+ }
971
1055
  let alias = Allowed(allowed);
972
1056
  p.header_bytes += h.header_bytes;
973
1057
  let plain_map = role_map("plain/1")?;
@@ -1232,6 +1316,46 @@ fn plan_carrier(
1232
1316
  Ok(())
1233
1317
  }
1234
1318
 
1319
+ /// Every key, its own plain tensor: no role folds, no marker drops, no rename.
1320
+ fn plan_as_is(
1321
+ component: &str,
1322
+ file: usize,
1323
+ h: &SourceHeader,
1324
+ allowed: &[&str],
1325
+ plain: &EncodingSpec,
1326
+ p: &mut Plan,
1327
+ ) -> Result<()> {
1328
+ if allowed != ["plain/1"] {
1329
+ return refuse(
1330
+ Code::UNKNOWN_ENCODING,
1331
+ format!("{IDENTITY} stores an unrecognized source in plain/1 only"),
1332
+ );
1333
+ }
1334
+ p.header_bytes += h.header_bytes;
1335
+ let (data, id) = (role_map("plain/1")?.data, plain.object_id());
1336
+ for t in &h.tensors {
1337
+ p.ops.push(Op {
1338
+ component: component.to_string(),
1339
+ out_key: t.key.clone(),
1340
+ encoding: "plain/1".into(),
1341
+ encoding_id: id.clone(),
1342
+ logical_dtype: t.dtype,
1343
+ logical_shape: t.shape.clone(),
1344
+ roles: vec![RolePlan {
1345
+ role: data.into(),
1346
+ dtype: t.dtype,
1347
+ shape: t.shape.clone(),
1348
+ bytes: Bytes::Stream {
1349
+ file,
1350
+ key: t.key.clone(),
1351
+ },
1352
+ }],
1353
+ effect: Effect::Recontain,
1354
+ });
1355
+ }
1356
+ Ok(())
1357
+ }
1358
+
1235
1359
  /// The original H3 MLP consumes [gate; value], while Diffusers SwiGLU consumes
1236
1360
  /// [value; gate]. The sibling fc2 projection proves the gate width, for main and
1237
1361
  /// token-refiner blocks alike. Only source runs move; no tensor value changes.
@@ -1776,6 +1900,25 @@ pub fn golden_cases(c: &Converter) -> Vec<(&'static str, Xform)> {
1776
1900
  },
1777
1901
  ),
1778
1902
  ],
1903
+ name if name == super::routes::SDXL => vec![
1904
+ (
1905
+ "OpenCLIP in_proj_bias, row block 2 of 3 (1280 x f16)",
1906
+ Xform::QkvSplit {
1907
+ groups: 1,
1908
+ shares: [2, 1, 0],
1909
+ take: 1,
1910
+ unit_bytes: 1280 * 2,
1911
+ },
1912
+ ),
1913
+ (
1914
+ "OpenCLIP text_projection 3 x 5 x f32 transpose",
1915
+ Xform::Transpose {
1916
+ rows: 3,
1917
+ cols: 5,
1918
+ elem_bytes: 4,
1919
+ },
1920
+ ),
1921
+ ],
1779
1922
  "h3.native/2" => vec![
1780
1923
  (
1781
1924
  "h3-swiglu gate/value rows",
@@ -1,4 +1,6 @@
1
- //! Classification: what IS this carrier, and does a reviewed registry entry authorize it?
1
+ //! Classification: what IS this carrier, and which reviewed converter and profile fit it?
2
+ //! The registry is a HINT: a source it does not recognize is stored as it is
3
+ //! (`source::AS_IS`), never refused for being unknown.
2
4
  //!
3
5
  //! Three separations this file exists to keep:
4
6
  //!
@@ -417,7 +419,8 @@ impl FingerprintRegistry {
417
419
  Code::UNREGISTERED_FINGERPRINT,
418
420
  format!(
419
421
  "{what}: key set {} ({} logical keys) matches no reviewed registry entry. \
420
- A filename never authorizes; bank the fingerprint under review first.",
422
+ A filename never authorizes: bank the fingerprint under review, or plan \
423
+ the source as-is.",
421
424
  fp.keyset_digest, fp.logical_keys
422
425
  ),
423
426
  ),
@@ -237,6 +237,16 @@ pub fn plan_digest(plan: &Plan, headers: &[(PathBuf, &SourceHeader)]) -> String
237
237
  field(&mut hash, b"swap-halves");
238
238
  field(&mut hash, &half_bytes.to_le_bytes());
239
239
  }
240
+ Xform::Transpose {
241
+ rows,
242
+ cols,
243
+ elem_bytes,
244
+ } => {
245
+ field(&mut hash, b"transpose");
246
+ for n in [rows, cols, elem_bytes] {
247
+ field(&mut hash, &n.to_le_bytes());
248
+ }
249
+ }
240
250
  }
241
251
  }
242
252
  }