tensorfs 0.3.26__tar.gz → 0.3.27__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 (126) hide show
  1. {tensorfs-0.3.26 → tensorfs-0.3.27}/Cargo.lock +2 -2
  2. {tensorfs-0.3.26 → tensorfs-0.3.27}/Cargo.toml +1 -1
  3. {tensorfs-0.3.26 → tensorfs-0.3.27}/PKG-INFO +1 -1
  4. tensorfs-0.3.27/crates/tensorfs-core/tests/instrument_profiles.rs +213 -0
  5. {tensorfs-0.3.26 → tensorfs-0.3.27}/pyproject.toml +1 -1
  6. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/Cargo.toml +0 -0
  7. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/build.rs +0 -0
  8. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/examples/h3-swiglu-layout.md +0 -0
  9. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/examples/optional-cache-backfill.md +0 -0
  10. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/examples/resident-conversion.md +0 -0
  11. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/examples/resident_conversion_profile.rs +0 -0
  12. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/b64.rs +0 -0
  13. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +0 -0
  14. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/conform.rs +0 -0
  15. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
  16. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/ingest.rs +0 -0
  17. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/main.rs +0 -0
  18. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/rd.rs +0 -0
  19. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/repo.rs +0 -0
  20. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
  21. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
  22. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/canon.rs +0 -0
  23. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/capability.rs +0 -0
  24. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/catalog.rs +0 -0
  25. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/cbor.rs +0 -0
  26. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/checkpoint.rs +0 -0
  27. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/corpus.rs +0 -0
  28. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/adoption.rs +0 -0
  29. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/graft_tests.rs +0 -0
  30. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/progress.rs +0 -0
  31. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/resume_tests.rs +0 -0
  32. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/retention.rs +0 -0
  33. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived/roots.rs +0 -0
  34. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/derived.rs +0 -0
  35. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/dtype.rs +0 -0
  36. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/durability.rs +0 -0
  37. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/err.rs +0 -0
  38. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/fetch.rs +0 -0
  39. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/fill.rs +0 -0
  40. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/fit.rs +0 -0
  41. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/gc.rs +0 -0
  42. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/header.rs +0 -0
  43. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/home.rs +0 -0
  44. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ids.rs +0 -0
  45. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
  46. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/convert.rs +0 -0
  47. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/fingerprint.rs +0 -0
  48. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
  49. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/journal.rs +0 -0
  50. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/mod.rs +0 -0
  51. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/preflight.rs +0 -0
  52. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/source.rs +0 -0
  53. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
  54. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/ingest/transaction.rs +0 -0
  55. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/jcs.rs +0 -0
  56. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/lib.rs +0 -0
  57. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/limits.rs +0 -0
  58. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/machine.rs +0 -0
  59. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/manifest.rs +0 -0
  60. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/meta.rs +0 -0
  61. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/project.rs +0 -0
  62. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/providers.rs +0 -0
  63. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/read.rs +0 -0
  64. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/receipt.rs +0 -0
  65. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/reclaim.rs +0 -0
  66. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/registry.rs +0 -0
  67. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/relation.rs +0 -0
  68. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/repo_cache.rs +0 -0
  69. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/repository.rs +0 -0
  70. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/sha256.rs +0 -0
  71. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/source_artifact.rs +0 -0
  72. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/spec.rs +0 -0
  73. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/staging.rs +0 -0
  74. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/storage.rs +0 -0
  75. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/store.rs +0 -0
  76. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/api.rs +0 -0
  77. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/http.rs +0 -0
  78. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/hub.rs +0 -0
  79. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/ledger.rs +0 -0
  80. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/mod.rs +0 -0
  81. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/policy.rs +0 -0
  82. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/prefix.rs +0 -0
  83. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/pull.rs +0 -0
  84. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/push.rs +0 -0
  85. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/ranged.rs +0 -0
  86. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/transport/tests.rs +0 -0
  87. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/src/vectors.rs +0 -0
  88. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fetch_url_progress.rs +0 -0
  89. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fit.rs +0 -0
  90. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
  91. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -0
  92. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -0
  93. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -0
  94. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
  95. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
  96. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
  97. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/h3_swiglu.rs +0 -0
  98. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/home.rs +0 -0
  99. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/import_tree.rs +0 -0
  100. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/liveness.rs +0 -0
  101. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/read_plan.rs +0 -0
  102. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/reclaim.rs +0 -0
  103. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/reclaim_run.rs +0 -0
  104. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/repo_cache.rs +0 -0
  105. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/repo_store.rs +0 -0
  106. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/resident_admission.rs +0 -0
  107. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/sha256_backends.rs +0 -0
  108. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/sharded_cas.rs +0 -0
  109. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/source_artifacts.rs +0 -0
  110. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/source_plan.rs +0 -0
  111. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/source_prefixes.rs +0 -0
  112. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/source_preflight.rs +0 -0
  113. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/staging.rs +0 -0
  114. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/store_boundaries.rs +0 -0
  115. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/tensor_schema.rs +0 -0
  116. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/version.rs +0 -0
  117. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-core/tests/write_through.rs +0 -0
  118. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-py/Cargo.toml +0 -0
  119. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-py/src/docs.rs +0 -0
  120. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-py/src/errors.rs +0 -0
  121. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-py/src/lib.rs +0 -0
  122. {tensorfs-0.3.26 → tensorfs-0.3.27}/crates/tensorfs-py/src/store.rs +0 -0
  123. {tensorfs-0.3.26 → tensorfs-0.3.27}/python/tensorfs/__init__.py +0 -0
  124. {tensorfs-0.3.26 → tensorfs-0.3.27}/python/tensorfs/_ext.pyi +0 -0
  125. {tensorfs-0.3.26 → tensorfs-0.3.27}/python/tensorfs/errors.py +0 -0
  126. {tensorfs-0.3.26 → tensorfs-0.3.27}/python/tensorfs/py.typed +0 -0
@@ -392,7 +392,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
392
392
 
393
393
  [[package]]
394
394
  name = "tensorfs-core"
395
- version = "0.3.26"
395
+ version = "0.3.27"
396
396
  dependencies = [
397
397
  "fs2",
398
398
  "minicbor",
@@ -404,7 +404,7 @@ dependencies = [
404
404
 
405
405
  [[package]]
406
406
  name = "tensorfs-py"
407
- version = "0.3.26"
407
+ version = "0.3.27"
408
408
  dependencies = [
409
409
  "pyo3",
410
410
  "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.26"
6
+ version = "0.3.27"
7
7
  edition = "2021"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensorfs
3
- Version: 0.3.26
3
+ Version: 0.3.27
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Rust
@@ -0,0 +1,213 @@
1
+ //! Real instrument metadata plans through the production native source path.
2
+ //! The only file data staged here is a header/index; sparse payload holes are never read.
3
+
4
+ use std::{fs, path::PathBuf};
5
+ use tensorfs_core::{
6
+ canon::{self, Value},
7
+ err::Code,
8
+ ids::ObjectRef,
9
+ ingest::{
10
+ fingerprint::{self, FingerprintRegistry},
11
+ preflight,
12
+ source::{self, BUILTIN_REGISTRY, BUILTIN_REGISTRY_BYTES},
13
+ },
14
+ limits,
15
+ providers::MemberHead,
16
+ };
17
+
18
+ struct Fixture {
19
+ name: String,
20
+ component: String,
21
+ profile: String,
22
+ carrier: String,
23
+ keys: usize,
24
+ order_digest: String,
25
+ heads: Vec<MemberHead>,
26
+ }
27
+
28
+ fn field<'a>(value: &'a Value, key: &str) -> &'a Value {
29
+ let Value::Obj(fields) = value else {
30
+ panic!("fixture object")
31
+ };
32
+ &fields.iter().find(|(name, _)| name == key).unwrap().1
33
+ }
34
+ fn text(value: &Value, key: &str) -> String {
35
+ let Value::Str(value) = field(value, key) else {
36
+ panic!("fixture string")
37
+ };
38
+ value.clone()
39
+ }
40
+ fn count(value: &Value, key: &str) -> u64 {
41
+ let Value::Int(value) = field(value, key) else {
42
+ panic!("fixture integer")
43
+ };
44
+ (*value).try_into().unwrap()
45
+ }
46
+ fn fixtures() -> Vec<Fixture> {
47
+ let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../vectors/instrument-headers");
48
+ let Value::Arr(rows) = canon::parse(
49
+ &fs::read(root.join("MANIFEST.json")).unwrap(),
50
+ limits::DOC_MAX_BYTES,
51
+ )
52
+ .unwrap() else {
53
+ panic!("fixture array")
54
+ };
55
+ rows.iter()
56
+ .map(|row| {
57
+ let Value::Arr(members) = field(row, "members") else {
58
+ panic!("members array")
59
+ };
60
+ let heads = members
61
+ .iter()
62
+ .map(|member| {
63
+ let head = fs::read(root.join(text(member, "header_file"))).unwrap();
64
+ assert_eq!(ObjectRef::of(&head).sha256, text(member, "header_sha256"));
65
+ assert_eq!(head.len() as u64, count(member, "header_bytes"));
66
+ MemberHead {
67
+ member: text(member, "member"),
68
+ length: count(member, "full_length"),
69
+ head,
70
+ }
71
+ })
72
+ .collect();
73
+ Fixture {
74
+ name: text(row, "name"),
75
+ component: text(row, "component"),
76
+ profile: text(row, "profile"),
77
+ carrier: text(row, "carrier"),
78
+ keys: count(row, "logical_keys") as usize,
79
+ order_digest: text(row, "construction_order_sha256"),
80
+ heads,
81
+ }
82
+ })
83
+ .collect()
84
+ }
85
+ fn temporary(name: &str) -> PathBuf {
86
+ std::env::temp_dir().join(format!(
87
+ "tfs-instrument-{name}-{}-{}",
88
+ std::process::id(),
89
+ tensorfs_core::meta::now_nanos_unique()
90
+ ))
91
+ }
92
+
93
+ #[test]
94
+ fn real_instrument_headers_match_native_profiles_without_payloads() {
95
+ let registry = FingerprintRegistry::parse(BUILTIN_REGISTRY_BYTES).unwrap();
96
+ for fixture in fixtures() {
97
+ let scratch = temporary(&fixture.name);
98
+ let decision = preflight::plan(
99
+ BUILTIN_REGISTRY,
100
+ BUILTIN_REGISTRY_BYTES,
101
+ &fixture.heads,
102
+ std::slice::from_ref(&fixture.profile),
103
+ &scratch,
104
+ )
105
+ .unwrap();
106
+ assert!(!scratch.exists());
107
+ assert_eq!(decision.plans.len(), 1);
108
+ let plan = &decision.plans[0];
109
+ assert_eq!(plan.constructs, fixture.keys);
110
+ assert_eq!(plan.converter, "diffusers.identity/1");
111
+ assert_eq!(plan.target, format!("{}=plain/1", fixture.component));
112
+ assert_eq!(plan.components.len(), 1);
113
+ assert_eq!(plan.components[0].component, fixture.component);
114
+ assert_eq!(
115
+ plan.components[0].member.as_deref(),
116
+ Some(fixture.carrier.as_str())
117
+ );
118
+ assert!(!plan.components[0].projected);
119
+
120
+ let staged = preflight::stage(&scratch, &fixture.heads).unwrap();
121
+ let native = source::plan_source(
122
+ BUILTIN_REGISTRY,
123
+ BUILTIN_REGISTRY_BYTES,
124
+ staged.carriers(),
125
+ Some(&fixture.profile),
126
+ None,
127
+ )
128
+ .unwrap();
129
+ assert_eq!(
130
+ native.session, plan.session,
131
+ "preflight and native plan are one operation"
132
+ );
133
+ assert!(native
134
+ .construction_order
135
+ .iter()
136
+ .all(|(component, _)| component == &fixture.component));
137
+ let order = Value::arr(
138
+ native
139
+ .construction_order
140
+ .iter()
141
+ .map(|(_, key)| Value::str(key.clone()))
142
+ .collect(),
143
+ );
144
+ assert_eq!(
145
+ ObjectRef::of(&canon::write(&order)).sha256,
146
+ fixture.order_digest
147
+ );
148
+ let carrier = staged
149
+ .carriers()
150
+ .iter()
151
+ .find(|input| input.member.as_deref() == Some(fixture.carrier.as_str()))
152
+ .unwrap();
153
+ let set = source::CarrierSet::of(staged.carriers());
154
+ let (header, _) = source::read_carrier(carrier, &set).unwrap();
155
+ let observed = fingerprint::fingerprint(&fixture.component, &header).unwrap();
156
+ let entry = registry
157
+ .entries
158
+ .iter()
159
+ .find(|entry| {
160
+ entry.component == fixture.component
161
+ && entry.keyset_digest == observed.keyset_digest
162
+ })
163
+ .unwrap();
164
+ assert_eq!(entry.tensor_schema_digest, observed.tensor_schema_digest);
165
+ assert_eq!(observed.logical_keys, fixture.keys);
166
+ drop(staged);
167
+ assert!(!scratch.exists());
168
+ }
169
+ }
170
+
171
+ #[test]
172
+ fn profiles_refuse_a_foreign_model_or_missing_member() {
173
+ let all = fixtures();
174
+ let qwen2 = all.iter().find(|fixture| fixture.name == "qwen2b").unwrap();
175
+ let qwen8 = all.iter().find(|fixture| fixture.name == "qwen8b").unwrap();
176
+ let error = preflight::plan(
177
+ BUILTIN_REGISTRY,
178
+ BUILTIN_REGISTRY_BYTES,
179
+ &qwen2.heads,
180
+ std::slice::from_ref(&qwen8.profile),
181
+ &temporary("wrong-model"),
182
+ )
183
+ .unwrap_err();
184
+ assert_eq!(error.code, Code::UNREGISTERED_FINGERPRINT);
185
+ let absent = "model-00001-of-00004.safetensors";
186
+ let heads: Vec<_> = qwen8
187
+ .heads
188
+ .iter()
189
+ .filter(|head| head.member != absent)
190
+ .cloned()
191
+ .collect();
192
+ let error = preflight::plan(
193
+ BUILTIN_REGISTRY,
194
+ BUILTIN_REGISTRY_BYTES,
195
+ &heads,
196
+ std::slice::from_ref(&qwen8.profile),
197
+ &temporary("missing-shard"),
198
+ )
199
+ .unwrap_err();
200
+ assert_eq!(error.code, Code::MISSING_FIELD);
201
+ assert!(error.detail.contains(absent));
202
+ let mut renamed = qwen2.heads.clone();
203
+ renamed[0].member = "other.safetensors".into();
204
+ let error = preflight::plan(
205
+ BUILTIN_REGISTRY,
206
+ BUILTIN_REGISTRY_BYTES,
207
+ &renamed,
208
+ std::slice::from_ref(&qwen2.profile),
209
+ &temporary("wrong-member"),
210
+ )
211
+ .unwrap_err();
212
+ assert_eq!(error.code, Code::UNREGISTERED_FINGERPRINT);
213
+ }
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "tensorfs"
7
- version = "0.3.26"
7
+ version = "0.3.27"
8
8
  description = "TensorFS — canonical tensor artifact substrate"
9
9
  requires-python = ">=3.12"
10
10
  classifiers = [