margin 0.9.7__tar.gz → 0.9.8__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.

Potentially problematic release.


This version of margin might be problematic. Click here for more details.

Files changed (85) hide show
  1. {margin-0.9.7/margin.egg-info → margin-0.9.8}/PKG-INFO +1 -1
  2. {margin-0.9.7 → margin-0.9.8}/margin/policy/validate.py +26 -0
  3. {margin-0.9.7 → margin-0.9.8}/margin/streaming.py +15 -0
  4. {margin-0.9.7 → margin-0.9.8/margin.egg-info}/PKG-INFO +1 -1
  5. {margin-0.9.7 → margin-0.9.8}/pyproject.toml +1 -1
  6. {margin-0.9.7 → margin-0.9.8}/tests/test_policy_validate.py +38 -0
  7. {margin-0.9.7 → margin-0.9.8}/LICENSE +0 -0
  8. {margin-0.9.7 → margin-0.9.8}/NOTICE +0 -0
  9. {margin-0.9.7 → margin-0.9.8}/README.md +0 -0
  10. {margin-0.9.7 → margin-0.9.8}/margin/__init__.py +0 -0
  11. {margin-0.9.7 → margin-0.9.8}/margin/__main__.py +0 -0
  12. {margin-0.9.7 → margin-0.9.8}/margin/algebra.py +0 -0
  13. {margin-0.9.7 → margin-0.9.8}/margin/anomaly.py +0 -0
  14. {margin-0.9.7 → margin-0.9.8}/margin/bridge.py +0 -0
  15. {margin-0.9.7 → margin-0.9.8}/margin/calibrate.py +0 -0
  16. {margin-0.9.7 → margin-0.9.8}/margin/causal.py +0 -0
  17. {margin-0.9.7 → margin-0.9.8}/margin/composite.py +0 -0
  18. {margin-0.9.7 → margin-0.9.8}/margin/confidence.py +0 -0
  19. {margin-0.9.7 → margin-0.9.8}/margin/config.py +0 -0
  20. {margin-0.9.7 → margin-0.9.8}/margin/contract.py +0 -0
  21. {margin-0.9.7 → margin-0.9.8}/margin/correlate.py +0 -0
  22. {margin-0.9.7 → margin-0.9.8}/margin/diff.py +0 -0
  23. {margin-0.9.7 → margin-0.9.8}/margin/drift.py +0 -0
  24. {margin-0.9.7 → margin-0.9.8}/margin/events.py +0 -0
  25. {margin-0.9.7 → margin-0.9.8}/margin/forecast.py +0 -0
  26. {margin-0.9.7 → margin-0.9.8}/margin/health.py +0 -0
  27. {margin-0.9.7 → margin-0.9.8}/margin/intent.py +0 -0
  28. {margin-0.9.7 → margin-0.9.8}/margin/ledger.py +0 -0
  29. {margin-0.9.7 → margin-0.9.8}/margin/loop.py +0 -0
  30. {margin-0.9.7 → margin-0.9.8}/margin/observation.py +0 -0
  31. {margin-0.9.7 → margin-0.9.8}/margin/persist.py +0 -0
  32. {margin-0.9.7 → margin-0.9.8}/margin/policy/__init__.py +0 -0
  33. {margin-0.9.7 → margin-0.9.8}/margin/policy/compose.py +0 -0
  34. {margin-0.9.7 → margin-0.9.8}/margin/policy/core.py +0 -0
  35. {margin-0.9.7 → margin-0.9.8}/margin/policy/temporal.py +0 -0
  36. {margin-0.9.7 → margin-0.9.8}/margin/policy/trace.py +0 -0
  37. {margin-0.9.7 → margin-0.9.8}/margin/policy/tuning.py +0 -0
  38. {margin-0.9.7 → margin-0.9.8}/margin/predicates.py +0 -0
  39. {margin-0.9.7 → margin-0.9.8}/margin/provenance.py +0 -0
  40. {margin-0.9.7 → margin-0.9.8}/margin/transitions.py +0 -0
  41. {margin-0.9.7 → margin-0.9.8}/margin/uncertain.py +0 -0
  42. {margin-0.9.7 → margin-0.9.8}/margin/validity.py +0 -0
  43. {margin-0.9.7 → margin-0.9.8}/margin.egg-info/SOURCES.txt +0 -0
  44. {margin-0.9.7 → margin-0.9.8}/margin.egg-info/dependency_links.txt +0 -0
  45. {margin-0.9.7 → margin-0.9.8}/margin.egg-info/top_level.txt +0 -0
  46. {margin-0.9.7 → margin-0.9.8}/setup.cfg +0 -0
  47. {margin-0.9.7 → margin-0.9.8}/tests/test_algebra.py +0 -0
  48. {margin-0.9.7 → margin-0.9.8}/tests/test_anomaly.py +0 -0
  49. {margin-0.9.7 → margin-0.9.8}/tests/test_bridge.py +0 -0
  50. {margin-0.9.7 → margin-0.9.8}/tests/test_calibrate.py +0 -0
  51. {margin-0.9.7 → margin-0.9.8}/tests/test_causal.py +0 -0
  52. {margin-0.9.7 → margin-0.9.8}/tests/test_composite.py +0 -0
  53. {margin-0.9.7 → margin-0.9.8}/tests/test_confidence.py +0 -0
  54. {margin-0.9.7 → margin-0.9.8}/tests/test_config.py +0 -0
  55. {margin-0.9.7 → margin-0.9.8}/tests/test_contract.py +0 -0
  56. {margin-0.9.7 → margin-0.9.8}/tests/test_correlate.py +0 -0
  57. {margin-0.9.7 → margin-0.9.8}/tests/test_diff.py +0 -0
  58. {margin-0.9.7 → margin-0.9.8}/tests/test_drift.py +0 -0
  59. {margin-0.9.7 → margin-0.9.8}/tests/test_events.py +0 -0
  60. {margin-0.9.7 → margin-0.9.8}/tests/test_forecast.py +0 -0
  61. {margin-0.9.7 → margin-0.9.8}/tests/test_health.py +0 -0
  62. {margin-0.9.7 → margin-0.9.8}/tests/test_healthcare.py +0 -0
  63. {margin-0.9.7 → margin-0.9.8}/tests/test_intent.py +0 -0
  64. {margin-0.9.7 → margin-0.9.8}/tests/test_ledger.py +0 -0
  65. {margin-0.9.7 → margin-0.9.8}/tests/test_loop.py +0 -0
  66. {margin-0.9.7 → margin-0.9.8}/tests/test_neuro.py +0 -0
  67. {margin-0.9.7 → margin-0.9.8}/tests/test_observation.py +0 -0
  68. {margin-0.9.7 → margin-0.9.8}/tests/test_persist.py +0 -0
  69. {margin-0.9.7 → margin-0.9.8}/tests/test_policy.py +0 -0
  70. {margin-0.9.7 → margin-0.9.8}/tests/test_policy_compose.py +0 -0
  71. {margin-0.9.7 → margin-0.9.8}/tests/test_policy_temporal.py +0 -0
  72. {margin-0.9.7 → margin-0.9.8}/tests/test_policy_trace.py +0 -0
  73. {margin-0.9.7 → margin-0.9.8}/tests/test_policy_tuning.py +0 -0
  74. {margin-0.9.7 → margin-0.9.8}/tests/test_predicates.py +0 -0
  75. {margin-0.9.7 → margin-0.9.8}/tests/test_printer3d.py +0 -0
  76. {margin-0.9.7 → margin-0.9.8}/tests/test_provenance.py +0 -0
  77. {margin-0.9.7 → margin-0.9.8}/tests/test_reverse_bridge.py +0 -0
  78. {margin-0.9.7 → margin-0.9.8}/tests/test_ros2.py +0 -0
  79. {margin-0.9.7 → margin-0.9.8}/tests/test_staleness.py +0 -0
  80. {margin-0.9.7 → margin-0.9.8}/tests/test_streaming.py +0 -0
  81. {margin-0.9.7 → margin-0.9.8}/tests/test_transformer.py +0 -0
  82. {margin-0.9.7 → margin-0.9.8}/tests/test_transitions.py +0 -0
  83. {margin-0.9.7 → margin-0.9.8}/tests/test_uncertain.py +0 -0
  84. {margin-0.9.7 → margin-0.9.8}/tests/test_validity.py +0 -0
  85. {margin-0.9.7 → margin-0.9.8}/tests/test_windowing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: margin
3
- Version: 0.9.7
3
+ Version: 0.9.8
4
4
  Summary: Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened.
5
5
  Author: Cope Labs LLC
6
6
  License: MIT
@@ -82,6 +82,10 @@ def validate(
82
82
  5. Missing health coverage (no rule handles ABLATED, DEGRADED, etc.)
83
83
  6. Contract coverage (if a contract is provided, check that the
84
84
  policy has rules for every component the contract mentions)
85
+ 7. Component coverage (if components list provided)
86
+ 8. alpha_from_sigma without a constraint floor
87
+ 9. min_confidence too high (Parser.parse() defaults to MODERATE, so
88
+ rules with min_confidence >= HIGH may silently never fire)
85
89
 
86
90
  Args:
87
91
  policy: the policy to validate
@@ -146,6 +150,9 @@ def validate(
146
150
  # 8. alpha_from_sigma without a constraint floor
147
151
  _check_alpha_from_sigma(policy, issues)
148
152
 
153
+ # 9. min_confidence gate too high for default parse behaviour
154
+ _check_min_confidence(policy, issues)
155
+
149
156
  return ValidationResult(issues=issues)
150
157
 
151
158
 
@@ -256,3 +263,22 @@ def _check_component_coverage(
256
263
  issues.append(ValidationIssue(
257
264
  "info", "policy",
258
265
  f"component '{comp}' has no dedicated rule (no wildcard rules either)"))
266
+
267
+
268
+ def _check_min_confidence(policy: Policy, issues: list[ValidationIssue]) -> None:
269
+ """
270
+ Warn when a rule's min_confidence gate is above MODERATE.
271
+
272
+ Parser.parse() assigns MODERATE confidence to every observation by
273
+ default (when no per-component confidences dict is passed). A rule
274
+ with min_confidence >= HIGH will therefore silently never fire unless
275
+ the caller explicitly passes HIGH or CERTAIN confidences on every step.
276
+ """
277
+ for rule in policy.rules:
278
+ if rule.min_confidence >= Confidence.HIGH:
279
+ issues.append(ValidationIssue(
280
+ "warning", rule.name,
281
+ f"min_confidence={rule.min_confidence.value} — Parser.parse() defaults "
282
+ "to MODERATE; this rule will never fire unless the caller explicitly "
283
+ "passes per-component confidences of HIGH or CERTAIN",
284
+ ))
@@ -392,6 +392,21 @@ class Monitor:
392
392
  anomaly_min_reference: int = 10,
393
393
  features: Optional[set] = None,
394
394
  ):
395
+ """
396
+ Args:
397
+ parser: Parser configured with baselines and thresholds
398
+ window: base window size for all trackers (overridden per-tracker)
399
+ drift_window: DriftTracker window (overrides ``window``)
400
+ anomaly_window: AnomalyTracker window (overrides ``window``)
401
+ correlation_window: CorrelationTracker window (overrides ``window``)
402
+ window_config: WindowConfig dataclass; overrides named window params
403
+ min_correlation: minimum |r| to include a pair in correlations
404
+ anomaly_min_reference: minimum steps before AnomalyTracker classifies
405
+ features: set of tracker names to enable — ``{"drift"``,
406
+ ``"anomaly"``, ``"correlation"}``; ``None`` (default)
407
+ enables all three; ``set()`` disables all.
408
+ ``"health"`` is always implied and need not be listed.
409
+ """
395
410
  self.parser = parser
396
411
  self.window = window
397
412
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: margin
3
- Version: 0.9.7
3
+ Version: 0.9.8
4
4
  Summary: Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened.
5
5
  Author: Cope Labs LLC
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "margin"
7
- version = "0.9.7"
7
+ version = "0.9.8"
8
8
  description = "Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -151,6 +151,44 @@ class TestComponentCoverage:
151
151
  assert len(comp_issues) == 0
152
152
 
153
153
 
154
+ class TestMinConfidenceCheck:
155
+ def test_high_confidence_gate_warns(self):
156
+ rule = PolicyRule(
157
+ "r", any_degraded(),
158
+ Action(target="*", op=Op.RESTORE, alpha=0.5),
159
+ min_confidence=Confidence.HIGH,
160
+ )
161
+ result = validate(Policy(name="p", rules=[rule]))
162
+ assert any("min_confidence" in i.message or "MODERATE" in i.message
163
+ for i in result.warnings)
164
+
165
+ def test_certain_confidence_gate_warns(self):
166
+ rule = PolicyRule(
167
+ "r", any_degraded(),
168
+ Action(target="*", op=Op.RESTORE, alpha=0.5),
169
+ min_confidence=Confidence.CERTAIN,
170
+ )
171
+ result = validate(Policy(name="p", rules=[rule]))
172
+ assert any("min_confidence" in i.message or "MODERATE" in i.message
173
+ for i in result.warnings)
174
+
175
+ def test_moderate_confidence_gate_no_warn(self):
176
+ rule = PolicyRule(
177
+ "r", any_degraded(),
178
+ Action(target="*", op=Op.RESTORE, alpha=0.5),
179
+ min_confidence=Confidence.MODERATE,
180
+ )
181
+ result = validate(Policy(name="p", rules=[rule]))
182
+ # No warning about min_confidence for MODERATE (default parse behaviour)
183
+ assert not any("MODERATE" in i.message and "min_confidence" in i.message
184
+ for i in result.warnings)
185
+
186
+ def test_low_confidence_gate_no_warn(self):
187
+ rule = _make_rule("r", any_degraded()) # default min_confidence=LOW
188
+ result = validate(Policy(name="p", rules=[rule]))
189
+ assert not any("min_confidence" in i.message for i in result.warnings)
190
+
191
+
154
192
  class TestValidationResult:
155
193
  def test_valid_when_no_errors(self):
156
194
  r = ValidationResult(issues=[])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes