invarlock 0.3.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

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.
invarlock/__init__.py CHANGED
@@ -12,7 +12,7 @@ For torch-dependent functionality, see subpackages under `invarlock.*`:
12
12
  - `invarlock.eval`: Metrics, guard-overhead checks, and certification
13
13
  """
14
14
 
15
- __version__ = "0.3.0"
15
+ __version__ = "0.3.1"
16
16
 
17
17
  # Core exports - torch-independent
18
18
  from .config import CFG, Defaults, get_default_config
@@ -11,5 +11,10 @@ dataset:
11
11
  final_n: 120
12
12
  stride: 512
13
13
 
14
+ primary_metric:
15
+ acceptance_range:
16
+ min: 0.95
17
+ max: 1.15
18
+
14
19
  context:
15
20
  telemetry_profile: "ci_cpu"
@@ -326,8 +326,14 @@ def doctor_command(
326
326
  try:
327
327
  import torch
328
328
 
329
+ torch_version = getattr(torch, "__version__", None)
329
330
  if not json_out:
330
- console.print(f"[green]✅ PyTorch {torch.__version__}[/green]")
331
+ if torch_version:
332
+ console.print(f"[green]✅ PyTorch {torch_version}[/green]")
333
+ else:
334
+ console.print(
335
+ "[yellow]⚠️ PyTorch present but version unavailable[/yellow]"
336
+ )
331
337
 
332
338
  # Device information
333
339
  from ..device import get_device_info
@@ -81,6 +81,137 @@ GUARD_OVERHEAD_THRESHOLD = 0.01
81
81
  SPLIT_ALIASES: tuple[str, ...] = ("validation", "val", "dev", "eval", "test")
82
82
 
83
83
 
84
+ def _coerce_mapping(obj: object) -> dict[str, Any]:
85
+ """Best-effort conversion of config-like objects to plain dicts."""
86
+
87
+ if isinstance(obj, dict):
88
+ return obj
89
+ try:
90
+ raw = getattr(obj, "_data", None)
91
+ if isinstance(raw, dict):
92
+ return raw
93
+ except Exception:
94
+ pass
95
+ try:
96
+ dumped = obj.model_dump() # type: ignore[attr-defined]
97
+ if isinstance(dumped, dict):
98
+ return dumped
99
+ except Exception:
100
+ pass
101
+ try:
102
+ data = vars(obj)
103
+ if isinstance(data, dict):
104
+ return data
105
+ except Exception:
106
+ pass
107
+ return {}
108
+
109
+
110
+ def _resolve_pm_acceptance_range(
111
+ cfg: InvarLockConfig | dict[str, Any] | None,
112
+ ) -> dict[str, float]:
113
+ """Resolve primary-metric acceptance bounds from config/env with safe defaults."""
114
+
115
+ base_min = 0.95
116
+ base_max = 1.10
117
+
118
+ cfg_min = None
119
+ cfg_max = None
120
+ try:
121
+ cfg_map = _coerce_mapping(cfg) if cfg is not None else {}
122
+ pm_section = cfg_map.get("primary_metric") if isinstance(cfg_map, dict) else {}
123
+ pm_map = _coerce_mapping(pm_section)
124
+ acceptance = (
125
+ pm_map.get("acceptance_range") if isinstance(pm_map, dict) else None
126
+ )
127
+ if isinstance(acceptance, dict):
128
+ if acceptance.get("min") is not None:
129
+ try:
130
+ cfg_min = float(acceptance["min"])
131
+ except (TypeError, ValueError):
132
+ cfg_min = None
133
+ if acceptance.get("max") is not None:
134
+ try:
135
+ cfg_max = float(acceptance["max"])
136
+ except (TypeError, ValueError):
137
+ cfg_max = None
138
+ except Exception:
139
+ cfg_min = None
140
+ cfg_max = None
141
+
142
+ def _parse_env(name: str) -> float | None:
143
+ try:
144
+ raw = os.environ.get(name, "")
145
+ if raw is None or str(raw).strip() == "":
146
+ return None
147
+ return float(raw)
148
+ except Exception:
149
+ return None
150
+
151
+ env_min = _parse_env("INVARLOCK_PM_ACCEPTANCE_MIN")
152
+ env_max = _parse_env("INVARLOCK_PM_ACCEPTANCE_MAX")
153
+
154
+ has_explicit = any(v is not None for v in (cfg_min, cfg_max, env_min, env_max))
155
+ if not has_explicit:
156
+ return {}
157
+
158
+ min_val = (
159
+ env_min if env_min is not None else cfg_min if cfg_min is not None else base_min
160
+ )
161
+ max_val = (
162
+ env_max if env_max is not None else cfg_max if cfg_max is not None else base_max
163
+ )
164
+
165
+ try:
166
+ if min_val is not None and min_val <= 0:
167
+ min_val = base_min
168
+ except Exception:
169
+ min_val = base_min
170
+ try:
171
+ if max_val is not None and max_val <= 0:
172
+ max_val = base_max
173
+ except Exception:
174
+ max_val = base_max
175
+
176
+ try:
177
+ if max_val is not None and min_val is not None and max_val < min_val:
178
+ max_val = min_val
179
+ except Exception:
180
+ max_val = base_max
181
+
182
+ return {"min": float(min_val), "max": float(max_val)}
183
+
184
+
185
+ def _free_model_memory(model: object | None) -> None:
186
+ """Best-effort cleanup to release GPU memory for a model object."""
187
+ if model is None:
188
+ return
189
+ try:
190
+ import gc
191
+
192
+ del model
193
+ gc.collect()
194
+ if torch is not None and torch.cuda.is_available():
195
+ torch.cuda.empty_cache()
196
+ torch.cuda.synchronize()
197
+ except Exception:
198
+ # Cleanup should never raise; fallback is to proceed without cache purge
199
+ pass
200
+
201
+
202
+ def _should_measure_overhead(profile_normalized: str) -> tuple[bool, bool]:
203
+ """Return (measure_guard_overhead, skip_overhead) derived from env/profile."""
204
+
205
+ skip_overhead_env = (
206
+ os.environ.get("INVARLOCK_SKIP_OVERHEAD_CHECK", "").strip().lower()
207
+ )
208
+ skip_overhead = skip_overhead_env in {"1", "true", "yes"}
209
+ measure_guard_overhead = (
210
+ profile_normalized in {"ci", "release"} and not skip_overhead
211
+ )
212
+ return measure_guard_overhead, skip_overhead
213
+
214
+
84
215
  def _choose_dataset_split(
85
216
  *, requested: str | None, available: list[str] | None
86
217
  ) -> tuple[str, bool]:
@@ -1671,6 +1802,7 @@ def run_command(
1671
1802
  "edit": edit_meta,
1672
1803
  "guards": guard_metadata,
1673
1804
  }
1805
+ pm_acceptance_range = _resolve_pm_acceptance_range(cfg)
1674
1806
 
1675
1807
  console.print(f"🔌 Adapter: {adapter.name}")
1676
1808
 
@@ -1746,6 +1878,10 @@ def run_command(
1746
1878
  "plugins": plugin_provenance,
1747
1879
  "run_id": run_id,
1748
1880
  }
1881
+ run_context.setdefault("primary_metric", {})["acceptance_range"] = (
1882
+ pm_acceptance_range
1883
+ )
1884
+ run_context["pm_acceptance_range"] = pm_acceptance_range
1749
1885
  run_context["model_profile"] = {
1750
1886
  "family": model_profile.family,
1751
1887
  "default_loss": model_profile.default_loss,
@@ -2756,18 +2892,26 @@ def run_command(
2756
2892
 
2757
2893
  restore_fn = _restore2
2758
2894
  else:
2759
- # reload path
2895
+ # reload path - properly free GPU memory before setting to None
2896
+ _free_model_memory(model)
2760
2897
  model = None
2761
2898
  restore_fn = None
2762
2899
  except Exception:
2763
2900
  # On any failure, fall back to reload-per-attempt path
2901
+ _free_model_memory(model)
2764
2902
  model = None
2765
2903
  restore_fn = None
2766
2904
 
2767
2905
  # RETRY LOOP - All report processing inside loop
2768
2906
  attempt = 1
2769
2907
  profile_normalized = (profile or "").lower()
2770
- measure_guard_overhead = profile_normalized in {"ci", "release"}
2908
+ measure_guard_overhead, skip_overhead = _should_measure_overhead(
2909
+ profile_normalized
2910
+ )
2911
+ if skip_overhead and profile_normalized in {"ci", "release"}:
2912
+ console.print(
2913
+ "[yellow]⚠️ Overhead check skipped via INVARLOCK_SKIP_OVERHEAD_CHECK[/yellow]"
2914
+ )
2771
2915
 
2772
2916
  while True:
2773
2917
  # Reset RNG streams each attempt to guarantee determinism across retries
@@ -2933,6 +3077,8 @@ def run_command(
2933
3077
  if env_flags:
2934
3078
  meta_payload["env_flags"] = env_flags
2935
3079
  report["meta"].update(meta_payload)
3080
+ if pm_acceptance_range:
3081
+ report["meta"]["pm_acceptance_range"] = pm_acceptance_range
2936
3082
  report["meta"]["model_profile"] = {
2937
3083
  "family": model_profile.family,
2938
3084
  "default_loss": model_profile.default_loss,
@@ -13,6 +13,7 @@ from __future__ import annotations
13
13
  # mypy: ignore-errors
14
14
  import copy
15
15
  import hashlib
16
+ import inspect
16
17
  import json
17
18
  import math
18
19
  import os
@@ -1322,24 +1323,36 @@ def make_certificate(
1322
1323
  capacity_tokens = None
1323
1324
  capacity_examples = None
1324
1325
 
1325
- validation_flags = _compute_validation_flags(
1326
- ppl_analysis,
1327
- spectral,
1328
- rmt,
1329
- invariants,
1330
- auto.get("tier", "balanced"),
1331
- ppl_metrics,
1332
- auto.get("target_pm_ratio"),
1333
- guard_overhead_section,
1334
- report.get("metrics", {}).get("primary_metric")
1326
+ pm_acceptance_range = _resolve_pm_acceptance_range_from_report(report)
1327
+
1328
+ validation_kwargs = {
1329
+ "ppl": ppl_analysis,
1330
+ "spectral": spectral,
1331
+ "rmt": rmt,
1332
+ "invariants": invariants,
1333
+ "tier": auto.get("tier", "balanced"),
1334
+ "_ppl_metrics": ppl_metrics,
1335
+ "target_ratio": auto.get("target_pm_ratio"),
1336
+ "guard_overhead": guard_overhead_section,
1337
+ "primary_metric": report.get("metrics", {}).get("primary_metric")
1335
1338
  if isinstance(report.get("metrics"), dict)
1336
1339
  else None,
1337
- moe_section,
1338
- {
1340
+ "moe": moe_section,
1341
+ "dataset_capacity": {
1339
1342
  "tokens_available": capacity_tokens,
1340
1343
  "examples_available": capacity_examples,
1341
1344
  },
1342
- )
1345
+ }
1346
+ try:
1347
+ if (
1348
+ "pm_acceptance_range"
1349
+ in inspect.signature(_compute_validation_flags).parameters
1350
+ ):
1351
+ validation_kwargs["pm_acceptance_range"] = pm_acceptance_range
1352
+ except Exception: # pragma: no cover - defensive against patched functions
1353
+ validation_kwargs["pm_acceptance_range"] = pm_acceptance_range
1354
+
1355
+ validation_flags = _compute_validation_flags(**validation_kwargs)
1343
1356
  # Enforce validation key allow-list to prevent surface drift
1344
1357
  _allowed_validation = _load_validation_allowlist()
1345
1358
  validation_filtered = {
@@ -2537,6 +2550,103 @@ def _build_provenance_block(
2537
2550
  return provenance
2538
2551
 
2539
2552
 
2553
+ def _resolve_pm_acceptance_range_from_report(
2554
+ report: dict[str, Any] | None,
2555
+ ) -> dict[str, float]:
2556
+ """Resolve primary-metric acceptance bounds from report context/meta/env."""
2557
+
2558
+ base_min = 0.95
2559
+ base_max = 1.10
2560
+
2561
+ def _safe_float(val: Any) -> float | None:
2562
+ try:
2563
+ if val is None:
2564
+ return None
2565
+ return float(val)
2566
+ except Exception:
2567
+ return None
2568
+
2569
+ cfg_min = None
2570
+ cfg_max = None
2571
+ ctx = report.get("context") if isinstance(report, dict) else None
2572
+ if isinstance(ctx, dict):
2573
+ pm_ctx = (
2574
+ ctx.get("primary_metric")
2575
+ if isinstance(ctx.get("primary_metric"), dict)
2576
+ else {}
2577
+ )
2578
+ if isinstance(pm_ctx, dict):
2579
+ cfg_min = _safe_float(pm_ctx.get("acceptance_range", {}).get("min"))
2580
+ cfg_max = _safe_float(pm_ctx.get("acceptance_range", {}).get("max"))
2581
+ if cfg_min is None or cfg_max is None:
2582
+ alt = ctx.get("pm_acceptance_range")
2583
+ if isinstance(alt, dict):
2584
+ cfg_min = (
2585
+ cfg_min if cfg_min is not None else _safe_float(alt.get("min"))
2586
+ )
2587
+ cfg_max = (
2588
+ cfg_max if cfg_max is not None else _safe_float(alt.get("max"))
2589
+ )
2590
+
2591
+ if (cfg_min is None or cfg_max is None) and isinstance(report, dict):
2592
+ meta = report.get("meta")
2593
+ if isinstance(meta, dict):
2594
+ meta_range = meta.get("pm_acceptance_range")
2595
+ if isinstance(meta_range, dict):
2596
+ cfg_min = (
2597
+ cfg_min
2598
+ if cfg_min is not None
2599
+ else _safe_float(meta_range.get("min"))
2600
+ )
2601
+ cfg_max = (
2602
+ cfg_max
2603
+ if cfg_max is not None
2604
+ else _safe_float(meta_range.get("max"))
2605
+ )
2606
+
2607
+ def _parse_env(name: str) -> float | None:
2608
+ try:
2609
+ raw = os.environ.get(name, "")
2610
+ if raw is None or str(raw).strip() == "":
2611
+ return None
2612
+ return float(raw)
2613
+ except Exception:
2614
+ return None
2615
+
2616
+ env_min = _parse_env("INVARLOCK_PM_ACCEPTANCE_MIN")
2617
+ env_max = _parse_env("INVARLOCK_PM_ACCEPTANCE_MAX")
2618
+
2619
+ has_explicit = any(v is not None for v in (cfg_min, cfg_max, env_min, env_max))
2620
+ if not has_explicit:
2621
+ return {}
2622
+
2623
+ min_val = (
2624
+ env_min if env_min is not None else cfg_min if cfg_min is not None else base_min
2625
+ )
2626
+ max_val = (
2627
+ env_max if env_max is not None else cfg_max if cfg_max is not None else base_max
2628
+ )
2629
+
2630
+ try:
2631
+ if min_val is not None and min_val <= 0:
2632
+ min_val = base_min
2633
+ except Exception:
2634
+ min_val = base_min
2635
+ try:
2636
+ if max_val is not None and max_val <= 0:
2637
+ max_val = base_max
2638
+ except Exception:
2639
+ max_val = base_max
2640
+
2641
+ try:
2642
+ if max_val is not None and min_val is not None and max_val < min_val:
2643
+ max_val = min_val
2644
+ except Exception:
2645
+ max_val = base_max
2646
+
2647
+ return {"min": float(min_val), "max": float(max_val)}
2648
+
2649
+
2540
2650
  def _compute_validation_flags(
2541
2651
  ppl: dict[str, Any],
2542
2652
  spectral: dict[str, Any],
@@ -2549,6 +2659,7 @@ def _compute_validation_flags(
2549
2659
  primary_metric: dict[str, Any] | None = None,
2550
2660
  moe: dict[str, Any] | None = None,
2551
2661
  dataset_capacity: dict[str, Any] | None = None,
2662
+ pm_acceptance_range: dict[str, float] | None = None,
2552
2663
  ) -> dict[str, bool]:
2553
2664
  """Compute validation flags for the certificate including canonical gates."""
2554
2665
  tier = (tier or "balanced").lower()
@@ -2569,7 +2680,25 @@ def _compute_validation_flags(
2569
2680
  "aggressive": 1.20,
2570
2681
  "none": 1.10,
2571
2682
  }
2572
- ratio_limit = tier_thresholds.get(tier, 1.10)
2683
+ acceptance = pm_acceptance_range if isinstance(pm_acceptance_range, dict) else {}
2684
+ ratio_min_bound = None
2685
+ ratio_max_bound = None
2686
+ try:
2687
+ if acceptance.get("min") is not None:
2688
+ ratio_min_bound = float(acceptance.get("min"))
2689
+ except Exception:
2690
+ ratio_min_bound = None
2691
+ try:
2692
+ if acceptance.get("max") is not None:
2693
+ ratio_max_bound = float(acceptance.get("max"))
2694
+ except Exception:
2695
+ ratio_max_bound = None
2696
+
2697
+ ratio_limit = (
2698
+ ratio_max_bound
2699
+ if isinstance(ratio_max_bound, (int | float)) and math.isfinite(ratio_max_bound)
2700
+ else tier_thresholds.get(tier, 1.10)
2701
+ )
2573
2702
  if isinstance(target_ratio, int | float) and target_ratio > 0:
2574
2703
  ratio_limit = min(ratio_limit, float(target_ratio))
2575
2704
 
@@ -2636,9 +2765,18 @@ def _compute_validation_flags(
2636
2765
  tokens_ok_eff = tokens_ok or _tiny_relax
2637
2766
  # Apply hysteresis to ratio limit if needed
2638
2767
  ratio_limit_with_hyst = ratio_limit + max(0.0, hysteresis_ratio)
2768
+ lower_bound_ok = True
2769
+ if ratio_min_bound is not None and isinstance(ratio_vs_baseline, (int | float)):
2770
+ try:
2771
+ lower_bound_ok = math.isfinite(float(ratio_vs_baseline)) and (
2772
+ float(ratio_vs_baseline) >= float(ratio_min_bound)
2773
+ )
2774
+ except Exception:
2775
+ lower_bound_ok = True
2639
2776
  compression_acceptable = (
2640
2777
  isinstance(ratio_vs_baseline, int | float)
2641
2778
  and math.isfinite(ratio_vs_baseline)
2779
+ and lower_bound_ok
2642
2780
  and ratio_vs_baseline <= ratio_limit_with_hyst
2643
2781
  and tokens_ok_eff
2644
2782
  )
@@ -2655,7 +2793,9 @@ def _compute_validation_flags(
2655
2793
  and all(isinstance(x, int | float) and math.isfinite(x) for x in ratio_ci)
2656
2794
  ):
2657
2795
  compression_acceptable = (
2658
- compression_acceptable and ratio_ci[1] <= ratio_limit_with_hyst
2796
+ compression_acceptable
2797
+ and ratio_ci[1] <= ratio_limit_with_hyst
2798
+ and (ratio_min_bound is None or ratio_ci[0] >= ratio_min_bound)
2659
2799
  )
2660
2800
 
2661
2801
  # 3. RMT ε-rule compliance
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: invarlock
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Edit‑agnostic robustness certificates for weight edits (InvarLock framework)
5
5
  Author-email: InvarLock Team <oss@invarlock.dev>
6
6
  Maintainer-email: InvarLock Maintainers <support@invarlock.dev>
@@ -112,7 +112,7 @@ they don’t, roll back safely.
112
112
  Technical: edit‑agnostic guard pipeline (invariants → spectral → RMT →
113
113
  variance) producing a machine‑readable Safety Certificate.
114
114
 
115
- > **Status:** 0.3.0 (pre‑1.0). Until 1.0, **minor** releases may be
115
+ > **Status:** 0.3.1 (pre‑1.0). Until 1.0, **minor** releases may be
116
116
  > breaking. See CLI help and the CHANGELOG for updates.
117
117
 
118
118
  [![CI](https://img.shields.io/github/actions/workflow/status/invarlock/invarlock/ci.yml?branch=main&logo=github&label=CI)](https://github.com/invarlock/invarlock/actions/workflows/ci.yml)
@@ -1,4 +1,4 @@
1
- invarlock/__init__.py,sha256=Oan5J3YATdRnh-9M-k6dQh6JAExLsg5SrU2gfoau9dE,1268
1
+ invarlock/__init__.py,sha256=YQiNLCps9m3tcPWMQ2ikf9_v9aA8C-JGvJAAhHMBNSo,1268
2
2
  invarlock/__main__.py,sha256=ffhoKctw89j-henmQXThbHDIdlvK9fBfsy8LpjhOEXc,146
3
3
  invarlock/config.py,sha256=7BUOl7EW258YnsgRipjOx6lmWou5jNDzimREd35ewsQ,1725
4
4
  invarlock/model_profile.py,sha256=sFHpK-1Q-1DjiZTWMolQBG4Dw9feLJgk3GnaD3ixgd8,12809
@@ -7,7 +7,7 @@ invarlock/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuNfZc,37
7
7
  invarlock/security.py,sha256=xUjbHu-bHKUfFqDyN_21Hj00NBmAcGgnAg4JCjb0JOE,4861
8
8
  invarlock/sparsity_utils.py,sha256=30SC3osptca2GmzxezbfX31EE6sRUhmEz8u3jn4vB2c,8281
9
9
  invarlock/_data/runtime/tiers.yaml,sha256=A0NMcz5o-TXJp1gZq2Sd7uYAQSsMQcG0ZV1FuLxl5jA,1700
10
- invarlock/_data/runtime/profiles/ci_cpu.yaml,sha256=N_ur2CkyL_g9-jwTwATniMhdrv0SL64lnHCQvjq-WWQ,324
10
+ invarlock/_data/runtime/profiles/ci_cpu.yaml,sha256=FE5vxeemAFWW7oRxPvp_8hIcCO8qrJilvQpXuS3f6u0,389
11
11
  invarlock/_data/runtime/profiles/release.yaml,sha256=xF0Qb0OTm904U6L3wK674JMTcDPegYvpKgwUB9pfq_w,482
12
12
  invarlock/adapters/__init__.py,sha256=Bwj8aKjhFxCzvcdxTIl-nG7IXyIE4L3Nd_fsIghbZxA,3418
13
13
  invarlock/adapters/_capabilities.py,sha256=FmzUR5BHsxWe92Z9W1As-G5_5wG1PvqF2sUpjZ2_CdY,1483
@@ -39,12 +39,12 @@ invarlock/cli/provenance.py,sha256=2E_8MxpSVEcxe5UewTb5Hlz6x4jXFwGd1567F4nIbEc,1
39
39
  invarlock/cli/utils.py,sha256=R6IN21lGfko2lGUgspmkZyjA6Nl_dVRaP8F8nRtN5yw,1393
40
40
  invarlock/cli/commands/__init__.py,sha256=afpKpU8hJI41Ol46oXxVwQgPwFBy4OmLaa_v4AAOdts,712
41
41
  invarlock/cli/commands/certify.py,sha256=2dYMrZYX1fACOIHbHshPoM7leCizQDRTPZ3Gc8s7FNo,14903
42
- invarlock/cli/commands/doctor.py,sha256=EVMxjyA2gq-LctknrhgdmGwD_xyMNDxdwlEmsDBq5sE,56349
42
+ invarlock/cli/commands/doctor.py,sha256=D5QTYQLlOxM3ngtw2RkuV7QPU2vgKWuymuNIvtKRnCM,56593
43
43
  invarlock/cli/commands/explain_gates.py,sha256=vAiszKjHBrXQ1K4xyzBIgV_gszVS38Zg254STPK8mnA,6057
44
44
  invarlock/cli/commands/export_html.py,sha256=oUGtt6EpKhjlywdtz_0FqYqcmA219H4eSjPuSMDShgY,3095
45
45
  invarlock/cli/commands/plugins.py,sha256=9SVs-2YZENsp10uZrWWT_uZUSFztrIDZizO_9WGP4xA,53044
46
46
  invarlock/cli/commands/report.py,sha256=I-B11k6cLLNUIaNiKlsWrGgZ2cTQQJsarN3oNf9Dt84,12988
47
- invarlock/cli/commands/run.py,sha256=5T1zaRVRLaLRWTW2WDnj9gCaCXByFM8k7tb1xAayLUA,172745
47
+ invarlock/cli/commands/run.py,sha256=BbXdhD5Vt8t0tg5ZAG6XPujZ3Je4J8ZExFrqv783KRs,177448
48
48
  invarlock/cli/commands/verify.py,sha256=iSnqXB1369aQUdxSAWeexyLcByeU3uKaE-LRgPTNdpA,44336
49
49
  invarlock/core/__init__.py,sha256=4wb83Xv7NE5M1FgvaFUviiNtVSTVATiPH3gqavNmp2w,1490
50
50
  invarlock/core/abi.py,sha256=gmU1F7LDd2HTcF4kcznn8vgG4zj9UCHSqhBk9jyu05k,484
@@ -110,7 +110,7 @@ invarlock/plugins/hf_bnb_adapter.py,sha256=g0ysWEi8dQzLtJy8iCszfTsYCOACuZMFYnTLM
110
110
  invarlock/plugins/hf_gptq_adapter.py,sha256=ysugAcnjLqF5sqpijSNiim1xUpRmoIgBrG053X3S2hE,3743
111
111
  invarlock/plugins/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuNfZc,37
112
112
  invarlock/reporting/__init__.py,sha256=A0541EqxcdTpslNbZEWIO4q-LCqzCQcadev2IBKEBbM,232
113
- invarlock/reporting/certificate.py,sha256=3xlAryynUh31iGenN7us3L3VGYB8vW722uVYGQiXdrM,124085
113
+ invarlock/reporting/certificate.py,sha256=pM9ghpA8qSCMLVXBv7qNfHL9YOTsf3gz96ObiZZXhUA,128987
114
114
  invarlock/reporting/certificate_schema.py,sha256=RXWc5RAabY7Jj_0xFOv2Op6dtNRpImsWJyI0QORcHNg,8817
115
115
  invarlock/reporting/dataset_hashing.py,sha256=b9LM2rtOtD0-1gQq_oJ0yI6oLleempwKinQtLupajwI,8680
116
116
  invarlock/reporting/guards_analysis.py,sha256=L8WdIFi17LrqWwggc11b-wzzT0O9Huo0zUxi9CkC-F4,38266
@@ -125,9 +125,9 @@ invarlock/reporting/utils.py,sha256=1aLYgSUR4XvgmhDvU9YK9ICd7W5sjft1qdsZC9JJSRY,
125
125
  invarlock/reporting/validate.py,sha256=396Fe4SPII4zaD1adGtH2hsl5asQOCDqDL4W3YixEXU,22453
126
126
  invarlock/utils/__init__.py,sha256=DR2pBrgddLH2PW-6ninOE8CM7DNvlvgyYsCkckozbPU,4276
127
127
  invarlock/utils/digest.py,sha256=sfnqGFRiRf7l950MjSIrWO1XbUfXlcEfNLeWFbBUr8I,1290
128
- invarlock-0.3.0.dist-info/licenses/LICENSE,sha256=uFddaXYY02nEFdPpS7bam_bnm0st41BibzD0jHULPXw,10413
129
- invarlock-0.3.0.dist-info/METADATA,sha256=MtsIbRufSXZ3xxDzNbxjDrYH0oDhIb1xDQdlElAsdjw,21783
130
- invarlock-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
- invarlock-0.3.0.dist-info/entry_points.txt,sha256=i0e4ZzmJNMBGG-69lbgP-muEcn1je2TUIWwl9SJERm0,670
132
- invarlock-0.3.0.dist-info/top_level.txt,sha256=GXfftc_YDHHcQC2vQgYbZ5cTO82YuWY3HusHMT3DuKs,10
133
- invarlock-0.3.0.dist-info/RECORD,,
128
+ invarlock-0.3.1.dist-info/licenses/LICENSE,sha256=uFddaXYY02nEFdPpS7bam_bnm0st41BibzD0jHULPXw,10413
129
+ invarlock-0.3.1.dist-info/METADATA,sha256=_i8VwWAUvfiqMRSPc-QmUp6SZlhZ0LdWblXRcmCMoao,21783
130
+ invarlock-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
+ invarlock-0.3.1.dist-info/entry_points.txt,sha256=i0e4ZzmJNMBGG-69lbgP-muEcn1je2TUIWwl9SJERm0,670
132
+ invarlock-0.3.1.dist-info/top_level.txt,sha256=GXfftc_YDHHcQC2vQgYbZ5cTO82YuWY3HusHMT3DuKs,10
133
+ invarlock-0.3.1.dist-info/RECORD,,