tensorfs 0.1.0__tar.gz → 0.1.2__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 (83) hide show
  1. {tensorfs-0.1.0 → tensorfs-0.1.2}/Cargo.lock +2 -2
  2. {tensorfs-0.1.0 → tensorfs-0.1.2}/Cargo.toml +1 -1
  3. {tensorfs-0.1.0 → tensorfs-0.1.2}/PKG-INFO +1 -1
  4. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +7 -25
  5. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/conform.rs +4 -1
  6. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/ingest.rs +6 -14
  7. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/layout.rs +110 -147
  8. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/main.rs +89 -56
  9. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/rd.rs +8 -8
  10. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/repo.rs +298 -29
  11. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/checkpoint.rs +32 -3
  12. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/corpus.rs +7 -19
  13. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/derived.rs +171 -15
  14. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/fetch.rs +159 -2
  15. tensorfs-0.1.0/crates/tensorfs-core/src/compat.rs → tensorfs-0.1.2/crates/tensorfs-core/src/fit.rs +703 -407
  16. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/grade.rs +14 -21
  17. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/header.rs +90 -3
  18. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/fingerprint.rs +27 -26
  19. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/source.rs +12 -16
  20. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/transaction.rs +5 -6
  21. tensorfs-0.1.2/crates/tensorfs-core/src/jcs.rs +527 -0
  22. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/lib.rs +4 -6
  23. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/machine.rs +89 -8
  24. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/read.rs +21 -2
  25. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/repository.rs +414 -271
  26. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/storage.rs +528 -80
  27. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/store.rs +6 -3
  28. tensorfs-0.1.2/crates/tensorfs-core/tests/fixtures/repo_apply/evidence.json +1 -0
  29. tensorfs-0.1.2/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +1 -0
  30. tensorfs-0.1.2/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +1 -0
  31. tensorfs-0.1.2/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +3 -0
  32. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/grade.rs +9 -86
  33. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/liveness.rs +0 -2
  34. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/repo_store.rs +51 -18
  35. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/source_plan.rs +1 -9
  36. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/topology_projection.rs +15 -20
  37. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-py/src/docs.rs +135 -10
  38. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-py/src/lib.rs +7 -1
  39. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-py/src/store.rs +44 -9
  40. {tensorfs-0.1.0 → tensorfs-0.1.2}/pyproject.toml +1 -1
  41. {tensorfs-0.1.0 → tensorfs-0.1.2}/python/tensorfs/__init__.py +34 -6
  42. tensorfs-0.1.0/crates/tensorfs-core/src/bin/tfs/fixtures.rs +0 -286
  43. tensorfs-0.1.0/crates/tensorfs-core/src/structure.rs +0 -282
  44. tensorfs-0.1.0/crates/tensorfs-core/src/verifier.rs +0 -256
  45. tensorfs-0.1.0/crates/tensorfs-core/tests/fixtures/repo_apply/evidence.json +0 -1
  46. tensorfs-0.1.0/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -1
  47. tensorfs-0.1.0/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -1
  48. tensorfs-0.1.0/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -3
  49. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/Cargo.toml +0 -0
  50. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/b64.rs +0 -0
  51. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
  52. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
  53. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
  54. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/canon.rs +0 -0
  55. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/capability.rs +0 -0
  56. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/catalog.rs +0 -0
  57. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/cbor.rs +0 -0
  58. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/dtype.rs +0 -0
  59. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/err.rs +0 -0
  60. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/fill.rs +0 -0
  61. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ids.rs +0 -0
  62. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
  63. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/convert.rs +0 -0
  64. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
  65. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/mod.rs +0 -0
  66. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
  67. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/limits.rs +0 -0
  68. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/manifest.rs +0 -0
  69. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/meta.rs +0 -0
  70. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/project.rs +0 -0
  71. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/receipt.rs +0 -0
  72. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/registry.rs +0 -0
  73. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/relation.rs +0 -0
  74. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/sha256.rs +0 -0
  75. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/spec.rs +0 -0
  76. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/src/vectors.rs +0 -0
  77. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
  78. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
  79. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
  80. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
  81. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-py/Cargo.toml +0 -0
  82. {tensorfs-0.1.0 → tensorfs-0.1.2}/crates/tensorfs-py/src/errors.rs +0 -0
  83. {tensorfs-0.1.0 → tensorfs-0.1.2}/python/tensorfs/errors.py +0 -0
@@ -249,7 +249,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
249
249
 
250
250
  [[package]]
251
251
  name = "tensorfs-core"
252
- version = "0.1.0"
252
+ version = "0.1.2"
253
253
  dependencies = [
254
254
  "fs2",
255
255
  "minicbor",
@@ -258,7 +258,7 @@ dependencies = [
258
258
 
259
259
  [[package]]
260
260
  name = "tensorfs-py"
261
- version = "0.1.0"
261
+ version = "0.1.2"
262
262
  dependencies = [
263
263
  "pyo3",
264
264
  "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.1.0"
6
+ version = "0.1.2"
7
7
  edition = "2021"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensorfs
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Rust
@@ -543,13 +543,18 @@ pub fn cmd_read(root: &Path, hex: &str, f: &Flags) -> ExitCode {
543
543
  ExitCode::SUCCESS
544
544
  }
545
545
 
546
- // ------------------------------------------------------------------ info / locate / admit
546
+ // ------------------------------------------------------------------ info / locate
547
547
 
548
548
  pub fn cmd_info(root: &Path, hex: &str) -> ExitCode {
549
549
  let (store, href) = opened!(root, hex);
550
550
  let header = ok!(ck::load_header(&store, &href));
551
551
  println!("header {} ({} B)", href.id(), href.length);
552
- println!("topology_digest {}", header.topology_digest());
552
+ let digests = ok!(ck::digests(&store, &header));
553
+ println!("topology_digest {}", digests.topology_digest);
554
+ println!("shape_digest {}", digests.shape_digest);
555
+ if let Some(config) = &digests.config_digest {
556
+ println!("config_digest {config}");
557
+ }
553
558
  for (name, c) in &header.configs {
554
559
  println!(
555
560
  "config {name:<14} sha256:{} {} B {}",
@@ -651,29 +656,6 @@ pub fn cmd_locate(
651
656
  ExitCode::SUCCESS
652
657
  }
653
658
 
654
- pub fn cmd_admit(root: &Path, hex: &str, f: &Flags) -> ExitCode {
655
- let (store, href) = opened!(root, hex);
656
- let header = ok!(ck::load_header(&store, &href));
657
- let closure = ok!(ck::load_closure(&store, &header));
658
- let pin: Vec<String> = match flag(f, "pin") {
659
- Some("empty") => Vec::new(),
660
- Some(alias) => registry::seeds()
661
- .iter()
662
- .filter(|s| s.alias == alias)
663
- .map(|s| s.spec.object_id())
664
- .collect(),
665
- None => registry::platform_digests(),
666
- };
667
- println!("local pin: {} aliased spec digests", pin.len());
668
- match header.admit_for_serving(&closure, &pin) {
669
- Ok(()) => {
670
- println!("ADMITTED for serving: every cited spec digest carries a local alias");
671
- ExitCode::SUCCESS
672
- }
673
- Err(e) => bail(e),
674
- }
675
- }
676
-
677
659
  // ------------------------------------------------------------------ caps / size
678
660
 
679
661
  /// The whole-document totals are red-armed in memory: the over-cap documents are far too
@@ -596,7 +596,10 @@ pub fn cmd_mine(rows: &std::path::Path, name: &str, f: &Flags) -> ExitCode {
596
596
  if let Err(e) = EncodingVectors::parse_fixture(&bytes) {
597
597
  return bail(e);
598
598
  }
599
- let d = crate::fixtures::dir().parent().unwrap().join("mined");
599
+ let d: std::path::PathBuf = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
600
+ .join("../../vectors/mined")
601
+ .components()
602
+ .collect();
600
603
  if let Err(e) = std::fs::create_dir_all(&d) {
601
604
  eprintln!("{}: {e}", d.display());
602
605
  return ExitCode::FAILURE;
@@ -36,6 +36,7 @@ use tensorfs_core::ingest::convert::{self, Class, Effect, Rekey, Source, Target}
36
36
  use tensorfs_core::ingest::fingerprint::{
37
37
  self, Banked, FingerprintRegistry, SourceProfile, SourceProfileComponent, SourceProfileVariant,
38
38
  };
39
+ use tensorfs_core::ingest::fingerprint::{Provenance, REAL};
39
40
  use tensorfs_core::ingest::source as source_core;
40
41
  use tensorfs_core::ingest::stamp::{self, Stamp};
41
42
  use tensorfs_core::ingest::transaction::{self as tx};
@@ -44,7 +45,6 @@ use tensorfs_core::limits;
44
45
  use tensorfs_core::manifest::{Draft, Entry};
45
46
  use tensorfs_core::registry;
46
47
  use tensorfs_core::store::{Progress, Store};
47
- use tensorfs_core::structure::{Provenance, REAL};
48
48
 
49
49
  use crate::watch::{self, Verdict, PROGRESS_PREFIX};
50
50
  use crate::{bail, flag, flag_num, flag_on, rss_kb, Flags};
@@ -364,8 +364,8 @@ pub fn cmd_inspect(f: &Flags) -> ExitCode {
364
364
  None => println!(" verdict (no registry loaded)"),
365
365
  Some(r) => match r.classify(&fp) {
366
366
  fingerprint::Verdict::Authorized(b) => println!(
367
- " verdict AUTHORIZED {}/{} via {} -> {}",
368
- b.task_family, b.structural_variant, b.dialect, b.converter
367
+ " verdict AUTHORIZED {} via {} -> {}",
368
+ b.component, b.dialect, b.converter
369
369
  ),
370
370
  fingerprint::Verdict::ComponentAmbiguous { banked_as } => println!(
371
371
  " verdict AMBIGUOUS — this key set is reviewed, but not as \
@@ -396,13 +396,7 @@ pub fn cmd_inspect(f: &Flags) -> ExitCode {
396
396
 
397
397
  /// Bank a reviewed registry entry. This is the REVIEW ACT, performed by a platform operator
398
398
  /// against bytes they have in hand — never by an uploader and never from a filename.
399
- pub fn cmd_bank(
400
- dialect: &str,
401
- family: &str,
402
- variant: &str,
403
- converter: &str,
404
- f: &Flags,
405
- ) -> ExitCode {
399
+ pub fn cmd_bank(dialect: &str, converter: &str, f: &Flags) -> ExitCode {
406
400
  let srcs = match sources(f) {
407
401
  Ok(s) => s,
408
402
  Err(c) => return c,
@@ -440,8 +434,6 @@ pub fn cmd_bank(
440
434
  reg.merge(Banked {
441
435
  keyset_digest: fp.keyset_digest.clone(),
442
436
  dialect: dialect.to_string(),
443
- task_family: family.to_string(),
444
- structural_variant: variant.to_string(),
445
437
  component: component.clone(),
446
438
  converter: converter.to_string(),
447
439
  topology_digest: fp.topology_digest.clone(),
@@ -1028,8 +1020,8 @@ pub fn cmd_plan(target: &str, f: &Flags) -> ExitCode {
1028
1020
  }
1029
1021
  for (i, b) in p.verdicts.iter().enumerate() {
1030
1022
  println!(
1031
- "verdict {} -> {}/{} via {} ({} keys)",
1032
- b.component, b.task_family, b.structural_variant, b.dialect, p.fps[i].logical_keys
1023
+ "verdict {} via {} -> {} ({} keys)",
1024
+ b.component, b.dialect, b.converter, p.fps[i].logical_keys
1033
1025
  );
1034
1026
  }
1035
1027
  print_plan(&p);
@@ -1,8 +1,8 @@
1
- //! The layout plane's CLI (tfs-009): `check_compatibility`, hub grading, the round-trip
2
- //! registration act, and the hermetic verifier's bounded document interface.
1
+ //! The fit and layout CLI: `tfs fit` (tfs-042, the one code <-> checkpoint answer), the
2
+ //! grade plane's walk and ranking (search only, D11), and the round-trip registration act.
3
3
  //!
4
- //! This file is a CONSUMER of the two decision modules. It prints grades because someone
5
- //! has to; it never decides one.
4
+ //! This file is a CONSUMER of the decision modules. It prints answers because someone has
5
+ //! to; it never decides one.
6
6
 
7
7
  use std::fs;
8
8
  use std::io::{BufRead, BufReader, Read, Write};
@@ -10,20 +10,19 @@ use std::path::Path;
10
10
  use std::process::ExitCode;
11
11
  use std::time::Instant;
12
12
 
13
+ use tensorfs_core::capability::CapabilityRecords;
13
14
  use tensorfs_core::checkpoint as ck;
14
- use tensorfs_core::compat::{
15
- self, Accepts, CodeTopology, CompatibilityReport, Lane, Requirement, Satisfaction,
16
- };
17
15
  use tensorfs_core::dtype::Dtype;
16
+ use tensorfs_core::fit::{
17
+ self, Accepts, CodeTopology, CompatibilityReport, Custody, Fit, Requirement,
18
+ };
18
19
  use tensorfs_core::grade::{self, ConversionRegistration, Grade, GradeDecision, Mapping, Registry};
19
20
  use tensorfs_core::header::Header;
20
21
  use tensorfs_core::ids::{ObjectRef, Plain};
21
- use tensorfs_core::ingest::fingerprint::MARKER_SUFFIXES;
22
22
  use tensorfs_core::limits;
23
23
  use tensorfs_core::registry;
24
24
  use tensorfs_core::spec::EncodingSpec;
25
25
  use tensorfs_core::store::Store;
26
- use tensorfs_core::verifier::{self, VerifyRequest};
27
26
 
28
27
  use crate::{bail, flag, flag_on, rss_kb, Flags};
29
28
 
@@ -36,10 +35,6 @@ macro_rules! ok {
36
35
  };
37
36
  }
38
37
 
39
- fn markers() -> Vec<String> {
40
- MARKER_SUFFIXES.iter().map(|s| s.to_string()).collect()
41
- }
42
-
43
38
  fn read(p: &Path) -> Result<Vec<u8>, ExitCode> {
44
39
  fs::read(p).map_err(|e| {
45
40
  eprintln!("REFUSED IO_FAILED: read {}: {e}", p.display());
@@ -83,6 +78,7 @@ pub fn cmd_topology(root: &Path, hex: &str, flags: &Flags) -> ExitCode {
83
78
  println!("contract {}", code.contract);
84
79
  println!("tensors {}", code.count());
85
80
  println!("topology {}", code.topology_digest());
81
+ println!("shape {}", code.shape_digest());
86
82
  ExitCode::SUCCESS
87
83
  }
88
84
 
@@ -103,6 +99,7 @@ pub fn project(h: &Header, contract_name: &str) -> CodeTopology {
103
99
  dtype: t.dtype,
104
100
  shape: t.shape.clone(),
105
101
  accepts: Accepts::OneOf(vec![t.encoding.clone()]),
102
+ pinned: false,
106
103
  },
107
104
  )
108
105
  })
@@ -110,9 +107,88 @@ pub fn project(h: &Header, contract_name: &str) -> CodeTopology {
110
107
  )
111
108
  })
112
109
  .collect(),
110
+ constructed_components: h.components.iter().map(|(c, _)| c.clone()).collect(),
113
111
  }
114
112
  }
115
113
 
114
+ /// `tfs fit <code-topology.json> <root> <header> [--custody local] [--device <class>
115
+ /// --observations <obs.json>] [--json]` — design §3, the only compatibility verdict.
116
+ ///
117
+ /// `<header>` is a header object id in `<root>` or a path to header bytes. Exit 0 on
118
+ /// `ok`; every refusal has its own exit code so a caller can branch without parsing, and
119
+ /// `--json` prints the total machine document (`machine::fit_json`).
120
+ pub fn cmd_fit(code_p: &Path, root: &Path, header_arg: &str, flags: &Flags) -> ExitCode {
121
+ let code = ok!(CodeTopology::parse(&rd!(code_p)));
122
+ let header = match tensorfs_core::ids::hex64("header", header_arg) {
123
+ Ok(_) => {
124
+ let store = ok!(Store::open(root));
125
+ let length = match fs::metadata(store.object_path(header_arg)) {
126
+ Ok(m) => m.len(),
127
+ Err(e) => {
128
+ eprintln!("REFUSED OBJECT_ABSENT: {header_arg}: {e}");
129
+ return ExitCode::FAILURE;
130
+ }
131
+ };
132
+ ok!(ck::load_header(
133
+ &store,
134
+ &ObjectRef {
135
+ sha256: header_arg.to_string(),
136
+ length,
137
+ }
138
+ ))
139
+ }
140
+ Err(_) => ok!(Header::parse(&rd!(Path::new(header_arg)))),
141
+ };
142
+ let custody = ok!(Custody::parse(
143
+ flag(flags, "custody").unwrap_or("canonical")
144
+ ));
145
+ let observations = match flag(flags, "observations") {
146
+ Some(p) => Some(ok!(CapabilityRecords::parse_observed(&rd!(Path::new(p))))),
147
+ None => None,
148
+ };
149
+ let device = flag(flags, "device");
150
+ if observations.is_some() && device.is_none() {
151
+ eprintln!("REFUSED MISSING_FIELD: --observations names records for a --device");
152
+ return ExitCode::FAILURE;
153
+ }
154
+ let t = Instant::now();
155
+ let verdict = ok!(fit::fit(
156
+ &code,
157
+ &header,
158
+ custody,
159
+ device,
160
+ observations.as_ref()
161
+ ));
162
+ let us = t.elapsed().as_secs_f64() * 1e6;
163
+ if flag_on(flags, "json") {
164
+ println!(
165
+ "{}",
166
+ String::from_utf8_lossy(&tensorfs_core::machine::fit_json(&verdict, custody))
167
+ );
168
+ return ExitCode::from(verdict.exit_code());
169
+ }
170
+ println!("fit {}", verdict.code());
171
+ println!("detail {}", verdict.text());
172
+ println!("custody {}", custody.name());
173
+ println!(
174
+ "shape code {} / checkpoint {} — {}",
175
+ &code.shape_digest()[7..19],
176
+ &header.shape_digest()[7..19],
177
+ if code.shape_digest() == header.shape_digest() {
178
+ "the fit index HITS"
179
+ } else {
180
+ "index miss; the answer is the walk above"
181
+ }
182
+ );
183
+ if let Fit::Ok { ignored, .. } = &verdict {
184
+ for key in ignored {
185
+ println!("ignored {key}");
186
+ }
187
+ }
188
+ println!("in {us:.0} us");
189
+ ExitCode::from(verdict.exit_code())
190
+ }
191
+
116
192
  /// Build a canonical header + code topology out of NEUTRAL measured rows.
117
193
  ///
118
194
  /// The rows carry component, key, logical dtype/shape and the measured role geometry, and
@@ -266,6 +342,7 @@ pub fn cmd_import(rows_p: &Path, flags: &Flags) -> ExitCode {
266
342
  dtype,
267
343
  shape,
268
344
  accepts: Accepts::OneOf(vec![sid]),
345
+ pinned: false,
269
346
  },
270
347
  ));
271
348
  }
@@ -302,7 +379,8 @@ pub fn cmd_import(rows_p: &Path, flags: &Flags) -> ExitCode {
302
379
  ok!(header.validate(&closure));
303
380
  let code = CodeTopology {
304
381
  contract: tensorfs_core::ids::object_id(provenance.as_bytes()),
305
- components: vec![(component, reqs)],
382
+ components: vec![(component.clone(), reqs)],
383
+ constructed_components: vec![component],
306
384
  };
307
385
  if let Some(p) = flag(flags, "out-header") {
308
386
  let _ = fs::write(p, ok!(header.canonical_bytes()));
@@ -465,22 +543,18 @@ pub fn cmd_check(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
465
543
  v
466
544
  }
467
545
  };
468
- let lane = ok!(Lane::parse(flag(flags, "lane").unwrap_or("canonical")));
469
- let depth = ok!(compat::Depth::parse(
546
+ let custody = ok!(Custody::parse(
547
+ flag(flags, "custody").unwrap_or("canonical")
548
+ ));
549
+ let depth = ok!(fit::Depth::parse(
470
550
  flag(flags, "depth").unwrap_or("first-mismatch")
471
551
  ));
472
552
  let t = Instant::now();
473
- let out = ok!(compat::check_compatibility(
474
- &code,
475
- &header,
476
- &closure,
477
- &pin,
478
- lane,
479
- &markers(),
480
- depth
553
+ let out = ok!(fit::check_compatibility(
554
+ &code, &header, &closure, &pin, custody, depth
481
555
  ));
482
556
  let us = t.elapsed().as_secs_f64() * 1e6;
483
- let report = ok!(CompatibilityReport::of(&code, &header, lane, &out));
557
+ let report = ok!(CompatibilityReport::of(&code, &header, custody, &out));
484
558
  emit(&report, flags);
485
559
 
486
560
  // The machine surface (proto-020). A caller that shells out to this command must not
@@ -497,7 +571,7 @@ pub fn cmd_check(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
497
571
  return ExitCode::SUCCESS;
498
572
  }
499
573
 
500
- println!("lane {}", lane.name());
574
+ println!("custody {}", custody.name());
501
575
  println!(
502
576
  "topology required {} / present {} — {}",
503
577
  &report.topology_required[7..19],
@@ -510,9 +584,9 @@ pub fn cmd_check(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
510
584
  );
511
585
  println!(
512
586
  "shape required {} / present {} — {}",
513
- &report.topology_shape_required[7..19],
514
- &report.topology_shape_present[7..19],
515
- if report.topology_shape_required == report.topology_shape_present {
587
+ &report.shape_required[7..19],
588
+ &report.shape_present[7..19],
589
+ if report.shape_required == report.shape_present {
516
590
  "same shapes, so any difference is dtype or encoding alone (a search bucket)"
517
591
  } else {
518
592
  "different shapes: a different model, not a different packaging"
@@ -556,7 +630,7 @@ pub fn cmd_check(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
556
630
  }
557
631
  if !out.unconsumed.is_empty() {
558
632
  println!(
559
- "unconsumed {} key(s) warned-ignored-confessed, first {:?}",
633
+ "unconsumed {} key(s) listed and ignored on local custody, first {:?}",
560
634
  out.unconsumed.len(),
561
635
  out.unconsumed[0]
562
636
  );
@@ -569,7 +643,7 @@ pub fn cmd_check(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
569
643
  ExitCode::SUCCESS
570
644
  }
571
645
 
572
- fn side(s: &compat::Side) -> String {
646
+ fn side(s: &fit::Side) -> String {
573
647
  let mut v = Vec::new();
574
648
  if let Some(d) = s.dtype {
575
649
  v.push(d.name().to_string());
@@ -736,8 +810,8 @@ pub fn cmd_grade(report_p: &Path, flags: &Flags) -> ExitCode {
736
810
  Ok(r) => r,
737
811
  Err(c) => return c,
738
812
  };
739
- // Grading over a report ALONE cannot prove a registration closes the whole gap — only
740
- // `verify-compat`, which holds both documents, can. `--prove-with` supplies them here.
813
+ // Grading over a report ALONE cannot prove a registration closes the whole gap; holding
814
+ // both documents can. `--code`/`--header` supply them here.
741
815
  let t = Instant::now();
742
816
  let g = match (flag(flags, "code"), flag(flags, "header")) {
743
817
  (Some(c), Some(h)) => {
@@ -762,8 +836,7 @@ pub fn cmd_grade(report_p: &Path, flags: &Flags) -> ExitCode {
762
836
  &header,
763
837
  &closure,
764
838
  &pin,
765
- report.lane,
766
- &markers(),
839
+ report.custody,
767
840
  &reg
768
841
  ))
769
842
  .1
@@ -787,8 +860,8 @@ pub fn cmd_grade(report_p: &Path, flags: &Flags) -> ExitCode {
787
860
  "grade {} — the {} of {} fact(s) at depth {}",
788
861
  g.name(),
789
862
  match report.depth {
790
- compat::Depth::Full => "WORST",
791
- compat::Depth::FirstMismatch => "first",
863
+ fit::Depth::Full => "WORST",
864
+ fit::Depth::FirstMismatch => "first",
792
865
  },
793
866
  report.mismatches.len(),
794
867
  report.depth.name()
@@ -954,113 +1027,3 @@ pub fn cmd_grade_stream(path: Option<&Path>, flags: &Flags) -> ExitCode {
954
1027
  Ok(tensorfs_core::machine::grade_json(&decision, &report))
955
1028
  })
956
1029
  }
957
-
958
- // ------------------------------------------------------------------ the hermetic verifier
959
-
960
- /// Build a request out of loose documents, so the seam can be driven by hand.
961
- pub fn cmd_request(code_p: &Path, header_p: &Path, flags: &Flags) -> ExitCode {
962
- let code_topology = rd!(code_p);
963
- let header_bytes = rd!(header_p);
964
- let header = ok!(Header::parse(&header_bytes));
965
- let mut closure = Vec::new();
966
- for p in flag(flags, "closure").unwrap_or("").split(',') {
967
- if !p.is_empty() {
968
- closure.push(rd!(Path::new(p)));
969
- }
970
- }
971
- let mut registrations = Vec::new();
972
- for p in flag(flags, "registry").unwrap_or("").split(',') {
973
- if !p.is_empty() {
974
- registrations.push(rd!(Path::new(p)));
975
- }
976
- }
977
- let pin: Vec<String> = match flag(flags, "pin") {
978
- Some(p) if !p.is_empty() => p.split(',').map(|s| s.to_string()).collect(),
979
- _ => header
980
- .encodings
981
- .iter()
982
- .map(EncodingSpec::object_id)
983
- .collect(),
984
- };
985
- let req = VerifyRequest {
986
- code_topology,
987
- header: header_bytes,
988
- closure,
989
- registrations,
990
- lane: ok!(Lane::parse(flag(flags, "lane").unwrap_or("canonical"))),
991
- pin,
992
- known_markers: markers(),
993
- };
994
- emit(&req, flags);
995
- println!("request {}", req.object_id());
996
- println!("bytes {}", req.canonical_bytes().len());
997
- ExitCode::SUCCESS
998
- }
999
-
1000
- /// The verifier process. One file in, one file out, written whole or not at all.
1001
- pub fn cmd_verify(req_p: &Path, out_p: &Path, flags: &Flags) -> ExitCode {
1002
- let bytes = rd!(req_p);
1003
- if bytes.len() > limits::DOC_MAX_BYTES {
1004
- eprintln!("REFUSED SIZE_CAP: request over the document cap");
1005
- return ExitCode::FAILURE;
1006
- }
1007
- let t = Instant::now();
1008
- let response = ok!(verifier::run(&bytes));
1009
- // A dev-only truncation point, so the CONSUMER's partial-output refusal can be armed
1010
- // against a real short file rather than described.
1011
- let response = match flag(flags, "truncate-at") {
1012
- Some(n) => response[..n.parse::<usize>().unwrap_or(0).min(response.len())].to_vec(),
1013
- None => response,
1014
- };
1015
- let tmp = out_p.with_extension("partial");
1016
- if let Err(e) = fs::write(&tmp, &response).and_then(|_| fs::rename(&tmp, out_p)) {
1017
- eprintln!("REFUSED IO_FAILED: write response: {e}");
1018
- return ExitCode::FAILURE;
1019
- }
1020
- println!(
1021
- "verified {} B response in {:.2} ms, peak RSS {:.1} MiB",
1022
- response.len(),
1023
- t.elapsed().as_secs_f64() * 1000.0,
1024
- rss_kb("VmHWM") as f64 / 1024.0
1025
- );
1026
- ExitCode::SUCCESS
1027
- }
1028
-
1029
- /// The verifier as a STREAM, over the same bounded document interface: one canonical
1030
- /// `VerifyRequest` per line in, one canonical `VerifyResponse` per line out, each response
1031
- /// still naming the sha256 of its own request. `verifier::run` is unchanged and still the
1032
- /// whole verifier as a pure function of bytes to bytes — this only stops paying a process
1033
- /// for each call to it, which is the end-to-end shape a catalog search wants: one code
1034
- /// topology against many checkpoints without a fork per pair.
1035
- ///
1036
- /// Every input still arrives inside its request, so the loop resolves no digest, opens no
1037
- /// store and reaches no network. Long-lived does not mean stateful.
1038
- pub fn cmd_verify_stream(path: Option<&Path>) -> ExitCode {
1039
- let (mut reader, flush_each) = match stream_in(path) {
1040
- Ok(v) => v,
1041
- Err(c) => return c,
1042
- };
1043
- each_line(&mut reader, flush_each, verifier::run)
1044
- }
1045
-
1046
- /// The hub's side: consume a response, or refuse. Nothing between those two.
1047
- pub fn cmd_consume(req_p: &Path, resp_p: &Path) -> ExitCode {
1048
- let req = rd!(req_p);
1049
- let resp = fs::read(resp_p).unwrap_or_default();
1050
- let (report, decision) = ok!(verifier::consume(&req, &resp));
1051
- println!("report {}", report.object_id());
1052
- println!("lane {}", report.lane.name());
1053
- match report.satisfaction() {
1054
- Satisfaction::Satisfied => println!("satisfaction Satisfied"),
1055
- Satisfaction::Mismatch(d) => println!(
1056
- "satisfaction Mismatch {} at {}/{} ({} fact(s) at depth {})",
1057
- d.code.as_str(),
1058
- d.component,
1059
- d.key,
1060
- report.mismatches.len(),
1061
- report.depth.name()
1062
- ),
1063
- }
1064
- println!("grade {}", decision.grade.name());
1065
- ExitCode::SUCCESS
1066
- }