invarlock 0.2.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.
@@ -5,18 +5,73 @@ HuggingFace BitsAndBytes Adapter (plugin)
5
5
  Optional adapter for loading 4/8-bit quantized causal LMs via bitsandbytes
6
6
  through Transformers. Requires GPU for practical use.
7
7
  Install with the `gpu` extra on supported platforms.
8
+
9
+ This adapter handles both:
10
+ 1. Fresh quantization of FP16 models (load_in_8bit/load_in_4bit)
11
+ 2. Loading pre-quantized BNB checkpoints (auto-detected via quantization_config)
8
12
  """
9
13
 
10
14
  from __future__ import annotations
11
15
 
16
+ from pathlib import Path
12
17
  from typing import Any
13
18
 
19
+ from invarlock.adapters.capabilities import (
20
+ ModelCapabilities,
21
+ QuantizationMethod,
22
+ detect_quantization_from_config,
23
+ )
14
24
  from invarlock.adapters.hf_mixin import HFAdapterMixin
15
25
  from invarlock.core.api import ModelAdapter
16
26
  from invarlock.core.error_utils import wrap_errors
17
27
  from invarlock.core.exceptions import DependencyError, ModelLoadError
18
28
 
19
29
 
30
+ def _is_local_path(model_id: str) -> bool:
31
+ """Check if model_id is a local filesystem path."""
32
+ return Path(model_id).exists()
33
+
34
+
35
+ def _detect_pre_quantized_bnb(model_id: str) -> tuple[bool, int]:
36
+ """
37
+ Detect if a local checkpoint is pre-quantized with BNB.
38
+
39
+ Returns:
40
+ Tuple of (is_pre_quantized, bits) where bits is 8 or 4.
41
+ """
42
+ if not _is_local_path(model_id):
43
+ return False, 0
44
+
45
+ config_path = Path(model_id) / "config.json"
46
+ if not config_path.exists():
47
+ return False, 0
48
+
49
+ try:
50
+ import json
51
+
52
+ config_data = json.loads(config_path.read_text())
53
+ quant_cfg = config_data.get("quantization_config", {})
54
+
55
+ if not quant_cfg:
56
+ return False, 0
57
+
58
+ # Check for BNB quantization
59
+ quant_method = quant_cfg.get("quant_method", "").lower()
60
+ if quant_method == "bitsandbytes" or "load_in_8bit" in quant_cfg:
61
+ if quant_cfg.get("load_in_8bit"):
62
+ return True, 8
63
+ if quant_cfg.get("load_in_4bit"):
64
+ return True, 4
65
+ # Fallback to bits field
66
+ bits = quant_cfg.get("bits", 8)
67
+ return True, bits
68
+
69
+ except Exception:
70
+ pass
71
+
72
+ return False, 0
73
+
74
+
20
75
  class HF_BNB_Adapter(HFAdapterMixin, ModelAdapter):
21
76
  name = "hf_bnb"
22
77
 
@@ -29,32 +84,72 @@ class HF_BNB_Adapter(HFAdapterMixin, ModelAdapter):
29
84
  ):
30
85
  from transformers import AutoModelForCausalLM
31
86
 
32
- # Default to 8-bit if not specified
33
- load_in_8bit = bool(kwargs.pop("load_in_8bit", True))
34
- load_in_4bit = bool(kwargs.pop("load_in_4bit", False))
87
+ # Check if this is a pre-quantized checkpoint
88
+ is_pre_quantized, pre_quant_bits = _detect_pre_quantized_bnb(model_id)
35
89
 
36
- if load_in_4bit:
37
- load_in_8bit = False
90
+ if is_pre_quantized:
91
+ # Load pre-quantized checkpoint WITHOUT re-applying quantization
92
+ with wrap_errors(
93
+ ModelLoadError,
94
+ "E201",
95
+ "MODEL-LOAD-FAILED: bitsandbytes/transformers (pre-quantized)",
96
+ lambda e: {"model_id": model_id, "pre_quantized_bits": pre_quant_bits},
97
+ ):
98
+ model = AutoModelForCausalLM.from_pretrained(
99
+ model_id,
100
+ device_map="auto",
101
+ trust_remote_code=True,
102
+ # Do NOT pass load_in_8bit/load_in_4bit for pre-quantized
103
+ **{
104
+ k: v
105
+ for k, v in kwargs.items()
106
+ if k not in ("load_in_8bit", "load_in_4bit")
107
+ },
108
+ )
109
+ else:
110
+ # Fresh quantization of FP16 model
111
+ load_in_8bit = bool(kwargs.pop("load_in_8bit", True))
112
+ load_in_4bit = bool(kwargs.pop("load_in_4bit", False))
38
113
 
39
- with wrap_errors(
40
- ModelLoadError,
41
- "E201",
42
- "MODEL-LOAD-FAILED: bitsandbytes/transformers",
43
- lambda e: {"model_id": model_id},
44
- ):
45
- model = AutoModelForCausalLM.from_pretrained(
46
- model_id,
47
- device_map="auto",
48
- load_in_8bit=load_in_8bit,
49
- load_in_4bit=load_in_4bit,
50
- trust_remote_code=True,
51
- **kwargs,
52
- )
53
-
54
- # Let HF device map place on CUDA if available; ensure device object resolves
55
- _ = self._resolve_device(device)
114
+ if load_in_4bit:
115
+ load_in_8bit = False
116
+
117
+ with wrap_errors(
118
+ ModelLoadError,
119
+ "E201",
120
+ "MODEL-LOAD-FAILED: bitsandbytes/transformers",
121
+ lambda e: {"model_id": model_id},
122
+ ):
123
+ model = AutoModelForCausalLM.from_pretrained(
124
+ model_id,
125
+ device_map="auto",
126
+ load_in_8bit=load_in_8bit,
127
+ load_in_4bit=load_in_4bit,
128
+ trust_remote_code=True,
129
+ **kwargs,
130
+ )
131
+
132
+ # BNB models handle their own device placement via device_map="auto"
133
+ # Do NOT call .to() on BNB models - it will raise an error
134
+ _ = self._resolve_device(device) # Validate device string only
56
135
  return model
57
136
 
137
+ def get_capabilities(self, model: Any) -> ModelCapabilities:
138
+ """Return capabilities for a BNB-quantized model."""
139
+ config = getattr(model, "config", None)
140
+ if config is not None:
141
+ quant_cfg = detect_quantization_from_config(config)
142
+ if quant_cfg.method == QuantizationMethod.BNB_8BIT:
143
+ return ModelCapabilities.for_bnb_8bit(from_checkpoint=True)
144
+ elif quant_cfg.method == QuantizationMethod.BNB_4BIT:
145
+ return ModelCapabilities.for_bnb_4bit(
146
+ from_checkpoint=True,
147
+ double_quant=quant_cfg.double_quant,
148
+ )
149
+
150
+ # Default to 8-bit if we can't determine
151
+ return ModelCapabilities.for_bnb_8bit()
152
+
58
153
  def can_handle(self, model: Any) -> bool:
59
154
  cfg = getattr(model, "config", None)
60
155
  return hasattr(cfg, "n_layer") or hasattr(cfg, "num_hidden_layers")
@@ -4,12 +4,16 @@ HuggingFace GPTQ Adapter (plugin)
4
4
 
5
5
  Optional adapter for loading AutoGPTQ-quantized causal LMs from the Hub.
6
6
  Requires the `auto-gptq` extra on supported platforms (typically Linux/CUDA).
7
+
8
+ GPTQ models are pre-quantized and typically handle device placement internally
9
+ during loading. This adapter uses safe device movement to respect constraints.
7
10
  """
8
11
 
9
12
  from __future__ import annotations
10
13
 
11
14
  from typing import Any
12
15
 
16
+ from invarlock.adapters.capabilities import ModelCapabilities
13
17
  from invarlock.adapters.hf_mixin import HFAdapterMixin
14
18
  from invarlock.core.api import ModelAdapter
15
19
  from invarlock.core.error_utils import wrap_errors
@@ -47,7 +51,26 @@ class HF_GPTQ_Adapter(HFAdapterMixin, ModelAdapter):
47
51
  **{k: v for k, v in kwargs.items() if k not in {"device"}},
48
52
  )
49
53
 
50
- return model.to(self._resolve_device(device))
54
+ # GPTQ models are pre-quantized; use safe device movement
55
+ # which respects the model's device constraints
56
+ return self._safe_to_device(
57
+ model, device, capabilities=ModelCapabilities.for_gptq()
58
+ )
59
+
60
+ def get_capabilities(self, model: Any) -> ModelCapabilities:
61
+ """Return capabilities for a GPTQ-quantized model."""
62
+ config = getattr(model, "config", None)
63
+ bits = 4 # Default GPTQ bits
64
+ group_size = 128 # Default GPTQ group size
65
+ if config is not None:
66
+ quant_cfg = getattr(config, "quantization_config", None)
67
+ if isinstance(quant_cfg, dict):
68
+ bits = quant_cfg.get("bits", 4)
69
+ group_size = quant_cfg.get("group_size", 128)
70
+ elif quant_cfg is not None:
71
+ bits = getattr(quant_cfg, "bits", 4)
72
+ group_size = getattr(quant_cfg, "group_size", 128)
73
+ return ModelCapabilities.for_gptq(bits=bits, group_size=group_size)
51
74
 
52
75
  # ---- Introspection ----
53
76
  def can_handle(self, model: Any) -> bool:
@@ -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.2.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.2.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=0wBGSMHtJjmLpssdA6ikmkPj1eMH_3x2q8214sYOguI,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,17 +7,18 @@ 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
- invarlock/adapters/__init__.py,sha256=4-q5QEQojX3G57BoJiBWzcFv-Ec9_upWtdxqxNVcJhk,3071
12
+ invarlock/adapters/__init__.py,sha256=Bwj8aKjhFxCzvcdxTIl-nG7IXyIE4L3Nd_fsIghbZxA,3418
13
13
  invarlock/adapters/_capabilities.py,sha256=FmzUR5BHsxWe92Z9W1As-G5_5wG1PvqF2sUpjZ2_CdY,1483
14
- invarlock/adapters/auto.py,sha256=s_rx29AkFen6-1eXMith8o7RN9pSW1b_J21yynhUl8Y,3706
14
+ invarlock/adapters/auto.py,sha256=XWENU5hi66AtMPlQDRuINk1SGW1Kym8Tot-2jXGFGcQ,7643
15
15
  invarlock/adapters/base.py,sha256=szSh1bECeDSDGQSr5oIWhs5RlI587gE4gzdt5cnOJ1s,16100
16
16
  invarlock/adapters/base_types.py,sha256=3IuHt63_RjGZqoTOdkMpfGPiZTGqcvXXDq1KU-8QemQ,1612
17
+ invarlock/adapters/capabilities.py,sha256=oAK_zgCzAFmss8qAU2zgc8kcahtadGtbPTYR7StXiCo,15360
17
18
  invarlock/adapters/hf_bert.py,sha256=DkUXCile7ALlHVZvMkNLAl_YrhHpdmQmomzNyIAPBEo,35547
18
19
  invarlock/adapters/hf_gpt2.py,sha256=zuNapMDj4kdzlpGJY11tMOr9dh0V1C0qkOTRwi1xCnQ,14814
19
- invarlock/adapters/hf_llama.py,sha256=6hDQx62pg_T-7sbVj8xWgJa60030AC9g2TaGLbgG96Q,19069
20
- invarlock/adapters/hf_mixin.py,sha256=uqprV8XXyhZemWZBnqpyVgDibsS5vTwAYXv6iUPo-HU,14248
20
+ invarlock/adapters/hf_llama.py,sha256=TbE9wII1GAQG7gbtiZCZ4S92rKoWRM7VH5vCnqEHc-4,19102
21
+ invarlock/adapters/hf_mixin.py,sha256=rhm0MbjzoHtEAl54tmW3T7tf1C_VxTtcPSdQ7mQ0CIU,18279
21
22
  invarlock/adapters/hf_onnx.py,sha256=kEqgQEEdGUeaXDF0EgaMHOQQMhc1xIvur0bQvdky-AY,4446
22
23
  invarlock/adapters/hf_t5.py,sha256=2SpDKPyERrrkTWXcDJDo0J5NNjFLePuC965e1zy2tus,4738
23
24
  invarlock/adapters/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuNfZc,37
@@ -38,12 +39,12 @@ invarlock/cli/provenance.py,sha256=2E_8MxpSVEcxe5UewTb5Hlz6x4jXFwGd1567F4nIbEc,1
38
39
  invarlock/cli/utils.py,sha256=R6IN21lGfko2lGUgspmkZyjA6Nl_dVRaP8F8nRtN5yw,1393
39
40
  invarlock/cli/commands/__init__.py,sha256=afpKpU8hJI41Ol46oXxVwQgPwFBy4OmLaa_v4AAOdts,712
40
41
  invarlock/cli/commands/certify.py,sha256=2dYMrZYX1fACOIHbHshPoM7leCizQDRTPZ3Gc8s7FNo,14903
41
- invarlock/cli/commands/doctor.py,sha256=EVMxjyA2gq-LctknrhgdmGwD_xyMNDxdwlEmsDBq5sE,56349
42
+ invarlock/cli/commands/doctor.py,sha256=D5QTYQLlOxM3ngtw2RkuV7QPU2vgKWuymuNIvtKRnCM,56593
42
43
  invarlock/cli/commands/explain_gates.py,sha256=vAiszKjHBrXQ1K4xyzBIgV_gszVS38Zg254STPK8mnA,6057
43
44
  invarlock/cli/commands/export_html.py,sha256=oUGtt6EpKhjlywdtz_0FqYqcmA219H4eSjPuSMDShgY,3095
44
45
  invarlock/cli/commands/plugins.py,sha256=9SVs-2YZENsp10uZrWWT_uZUSFztrIDZizO_9WGP4xA,53044
45
46
  invarlock/cli/commands/report.py,sha256=I-B11k6cLLNUIaNiKlsWrGgZ2cTQQJsarN3oNf9Dt84,12988
46
- invarlock/cli/commands/run.py,sha256=5T1zaRVRLaLRWTW2WDnj9gCaCXByFM8k7tb1xAayLUA,172745
47
+ invarlock/cli/commands/run.py,sha256=BbXdhD5Vt8t0tg5ZAG6XPujZ3Je4J8ZExFrqv783KRs,177448
47
48
  invarlock/cli/commands/verify.py,sha256=iSnqXB1369aQUdxSAWeexyLcByeU3uKaE-LRgPTNdpA,44336
48
49
  invarlock/core/__init__.py,sha256=4wb83Xv7NE5M1FgvaFUviiNtVSTVATiPH3gqavNmp2w,1490
49
50
  invarlock/core/abi.py,sha256=gmU1F7LDd2HTcF4kcznn8vgG4zj9UCHSqhBk9jyu05k,484
@@ -55,7 +56,7 @@ invarlock/core/contracts.py,sha256=9j55WVwMrEsUqxWlzAdMsHtkzgfkSftdizhcLiJBauw,2
55
56
  invarlock/core/error_utils.py,sha256=T23-p5ONQ-SeVuMR4Ts0cWyupsSa-0DAgsejRTfxeCg,1782
56
57
  invarlock/core/events.py,sha256=8XBAi-9A7ys7QJQwqlz8PVlfxF0TM_TvLqjcPtDwZm4,9428
57
58
  invarlock/core/exceptions.py,sha256=b4OszJ0Fd0Ezy8s99AzprS7lAkqdZYGXaSj9fYaln4E,2077
58
- invarlock/core/registry.py,sha256=2bpz37u2Tf78N4h78cvTJ0iWrb5VG90CCg3CMzwyUbc,17879
59
+ invarlock/core/registry.py,sha256=vgKmhekteJS2oRu8g3tBHm48z_Eda5oPKq2ajQnDDc4,18884
59
60
  invarlock/core/retry.py,sha256=KTVkrTnWs60jwATOZDHinERH56GnOGjsKR0lmohagEo,4503
60
61
  invarlock/core/runner.py,sha256=IWp6cL21IzP_7k26AqcCFHg772f3XHO_PK2PB_-DS0s,81448
61
62
  invarlock/core/types.py,sha256=nVLMP4yqlxwhE1moQU7FWVeGJqTuud-cvTZiutdBGKk,3585
@@ -89,7 +90,7 @@ invarlock/guards/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuNfZc,37
89
90
  invarlock/guards/rmt.py,sha256=f_fZEKZyp_xJcmc7wAMNSrzs702JCztfq3zcK4CSJgk,78710
90
91
  invarlock/guards/spectral.py,sha256=tOHBoAm23xkPKUYLdr41ZQYHc806pxrhVXwsmoDLiKE,51132
91
92
  invarlock/guards/tier_config.py,sha256=_WJIQ4qvIOc8EI1ygBhpBqbZPt072RT6H6Oh9-LqNWY,10706
92
- invarlock/guards/variance.py,sha256=jB2UTB7fveudF7tRhkrbAXoO774_BWb59Cq2MMCvJ8s,131832
93
+ invarlock/guards/variance.py,sha256=LziyAF5QewT-dtCbRJGb7IklVTIp1IfwTqZhE3yJtv4,133080
93
94
  invarlock/guards_ref/__init__.py,sha256=jLnyFqdqQaheG1qQMlU4Gx7R118rkkQHPqFVF3_1ih0,366
94
95
  invarlock/guards_ref/rmt_ref.py,sha256=md-aSzLCxPL3OXmrA5NtI9wK7cVSyd2xw8WtSodcGQY,1246
95
96
  invarlock/guards_ref/spectral_ref.py,sha256=FdwFfrs5hxEEUIfBV3CvAJvTX78gAM00mKLEXyZ0zJo,4386
@@ -104,12 +105,12 @@ invarlock/observability/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuN
104
105
  invarlock/observability/utils.py,sha256=1AC3ZEzbrDzTOvSIFxAtWlITy1BHEPZ032HKKzqK_10,16492
105
106
  invarlock/plugins/__init__.py,sha256=aZqkpuTT0K3y0SX4702k3YpHnM3kng9fz0qO3XE43hY,260
106
107
  invarlock/plugins/hello_guard.py,sha256=-peYJaZd52bbdw6y8cBxEd3CbtFWualDs8nX60CeXhI,896
107
- invarlock/plugins/hf_awq_adapter.py,sha256=oKo9oP5WelHC5kymKhpqv1ORdMuXfp9TgxXUNbeegx0,2772
108
- invarlock/plugins/hf_bnb_adapter.py,sha256=kH_jDTqIjk5uzdRI19GeOvDQif1KxQHuv3Ac8ZDbo8A,2548
109
- invarlock/plugins/hf_gptq_adapter.py,sha256=A9AY0SkDifZL4dAJlCtqwUieVOgKp-1sl4gghvVjNTI,2582
108
+ invarlock/plugins/hf_awq_adapter.py,sha256=UGwzcqJyuqrYHWZ4F-vn-9LNfEDyolOgVDBi0jN35xc,3770
109
+ invarlock/plugins/hf_bnb_adapter.py,sha256=g0ysWEi8dQzLtJy8iCszfTsYCOACuZMFYnTLMAEVxs0,6011
110
+ invarlock/plugins/hf_gptq_adapter.py,sha256=ysugAcnjLqF5sqpijSNiim1xUpRmoIgBrG053X3S2hE,3743
110
111
  invarlock/plugins/py.typed,sha256=LCPmZeE_vANVVJDNvuq9A07i7jg9Nxrq6f10UeuNfZc,37
111
112
  invarlock/reporting/__init__.py,sha256=A0541EqxcdTpslNbZEWIO4q-LCqzCQcadev2IBKEBbM,232
112
- invarlock/reporting/certificate.py,sha256=3xlAryynUh31iGenN7us3L3VGYB8vW722uVYGQiXdrM,124085
113
+ invarlock/reporting/certificate.py,sha256=pM9ghpA8qSCMLVXBv7qNfHL9YOTsf3gz96ObiZZXhUA,128987
113
114
  invarlock/reporting/certificate_schema.py,sha256=RXWc5RAabY7Jj_0xFOv2Op6dtNRpImsWJyI0QORcHNg,8817
114
115
  invarlock/reporting/dataset_hashing.py,sha256=b9LM2rtOtD0-1gQq_oJ0yI6oLleempwKinQtLupajwI,8680
115
116
  invarlock/reporting/guards_analysis.py,sha256=L8WdIFi17LrqWwggc11b-wzzT0O9Huo0zUxi9CkC-F4,38266
@@ -124,9 +125,9 @@ invarlock/reporting/utils.py,sha256=1aLYgSUR4XvgmhDvU9YK9ICd7W5sjft1qdsZC9JJSRY,
124
125
  invarlock/reporting/validate.py,sha256=396Fe4SPII4zaD1adGtH2hsl5asQOCDqDL4W3YixEXU,22453
125
126
  invarlock/utils/__init__.py,sha256=DR2pBrgddLH2PW-6ninOE8CM7DNvlvgyYsCkckozbPU,4276
126
127
  invarlock/utils/digest.py,sha256=sfnqGFRiRf7l950MjSIrWO1XbUfXlcEfNLeWFbBUr8I,1290
127
- invarlock-0.2.0.dist-info/licenses/LICENSE,sha256=uFddaXYY02nEFdPpS7bam_bnm0st41BibzD0jHULPXw,10413
128
- invarlock-0.2.0.dist-info/METADATA,sha256=C0bQOmPMu9IwbiHk6tyHn2sPhO3Fld-bKfc8NCgS5KU,21783
129
- invarlock-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
130
- invarlock-0.2.0.dist-info/entry_points.txt,sha256=i0e4ZzmJNMBGG-69lbgP-muEcn1je2TUIWwl9SJERm0,670
131
- invarlock-0.2.0.dist-info/top_level.txt,sha256=GXfftc_YDHHcQC2vQgYbZ5cTO82YuWY3HusHMT3DuKs,10
132
- invarlock-0.2.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,,