margin 0.8.1__tar.gz → 0.8.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.

Potentially problematic release.


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

Files changed (85) hide show
  1. {margin-0.8.1/margin.egg-info → margin-0.8.2}/PKG-INFO +1 -1
  2. {margin-0.8.1 → margin-0.8.2}/margin/causal.py +25 -1
  3. {margin-0.8.1 → margin-0.8.2}/margin/correlate.py +1 -0
  4. {margin-0.8.1 → margin-0.8.2}/margin/ledger.py +8 -0
  5. {margin-0.8.1 → margin-0.8.2/margin.egg-info}/PKG-INFO +1 -1
  6. {margin-0.8.1 → margin-0.8.2}/pyproject.toml +1 -1
  7. {margin-0.8.1 → margin-0.8.2}/LICENSE +0 -0
  8. {margin-0.8.1 → margin-0.8.2}/NOTICE +0 -0
  9. {margin-0.8.1 → margin-0.8.2}/README.md +0 -0
  10. {margin-0.8.1 → margin-0.8.2}/margin/__init__.py +0 -0
  11. {margin-0.8.1 → margin-0.8.2}/margin/__main__.py +0 -0
  12. {margin-0.8.1 → margin-0.8.2}/margin/algebra.py +0 -0
  13. {margin-0.8.1 → margin-0.8.2}/margin/anomaly.py +0 -0
  14. {margin-0.8.1 → margin-0.8.2}/margin/bridge.py +0 -0
  15. {margin-0.8.1 → margin-0.8.2}/margin/calibrate.py +0 -0
  16. {margin-0.8.1 → margin-0.8.2}/margin/composite.py +0 -0
  17. {margin-0.8.1 → margin-0.8.2}/margin/confidence.py +0 -0
  18. {margin-0.8.1 → margin-0.8.2}/margin/config.py +0 -0
  19. {margin-0.8.1 → margin-0.8.2}/margin/contract.py +0 -0
  20. {margin-0.8.1 → margin-0.8.2}/margin/diff.py +0 -0
  21. {margin-0.8.1 → margin-0.8.2}/margin/drift.py +0 -0
  22. {margin-0.8.1 → margin-0.8.2}/margin/events.py +0 -0
  23. {margin-0.8.1 → margin-0.8.2}/margin/forecast.py +0 -0
  24. {margin-0.8.1 → margin-0.8.2}/margin/health.py +0 -0
  25. {margin-0.8.1 → margin-0.8.2}/margin/intent.py +0 -0
  26. {margin-0.8.1 → margin-0.8.2}/margin/loop.py +0 -0
  27. {margin-0.8.1 → margin-0.8.2}/margin/observation.py +0 -0
  28. {margin-0.8.1 → margin-0.8.2}/margin/persist.py +0 -0
  29. {margin-0.8.1 → margin-0.8.2}/margin/policy/__init__.py +0 -0
  30. {margin-0.8.1 → margin-0.8.2}/margin/policy/compose.py +0 -0
  31. {margin-0.8.1 → margin-0.8.2}/margin/policy/core.py +0 -0
  32. {margin-0.8.1 → margin-0.8.2}/margin/policy/temporal.py +0 -0
  33. {margin-0.8.1 → margin-0.8.2}/margin/policy/trace.py +0 -0
  34. {margin-0.8.1 → margin-0.8.2}/margin/policy/tuning.py +0 -0
  35. {margin-0.8.1 → margin-0.8.2}/margin/policy/validate.py +0 -0
  36. {margin-0.8.1 → margin-0.8.2}/margin/predicates.py +0 -0
  37. {margin-0.8.1 → margin-0.8.2}/margin/provenance.py +0 -0
  38. {margin-0.8.1 → margin-0.8.2}/margin/streaming.py +0 -0
  39. {margin-0.8.1 → margin-0.8.2}/margin/transitions.py +0 -0
  40. {margin-0.8.1 → margin-0.8.2}/margin/uncertain.py +0 -0
  41. {margin-0.8.1 → margin-0.8.2}/margin/validity.py +0 -0
  42. {margin-0.8.1 → margin-0.8.2}/margin.egg-info/SOURCES.txt +0 -0
  43. {margin-0.8.1 → margin-0.8.2}/margin.egg-info/dependency_links.txt +0 -0
  44. {margin-0.8.1 → margin-0.8.2}/margin.egg-info/top_level.txt +0 -0
  45. {margin-0.8.1 → margin-0.8.2}/setup.cfg +0 -0
  46. {margin-0.8.1 → margin-0.8.2}/tests/test_algebra.py +0 -0
  47. {margin-0.8.1 → margin-0.8.2}/tests/test_anomaly.py +0 -0
  48. {margin-0.8.1 → margin-0.8.2}/tests/test_bridge.py +0 -0
  49. {margin-0.8.1 → margin-0.8.2}/tests/test_calibrate.py +0 -0
  50. {margin-0.8.1 → margin-0.8.2}/tests/test_causal.py +0 -0
  51. {margin-0.8.1 → margin-0.8.2}/tests/test_composite.py +0 -0
  52. {margin-0.8.1 → margin-0.8.2}/tests/test_confidence.py +0 -0
  53. {margin-0.8.1 → margin-0.8.2}/tests/test_config.py +0 -0
  54. {margin-0.8.1 → margin-0.8.2}/tests/test_contract.py +0 -0
  55. {margin-0.8.1 → margin-0.8.2}/tests/test_correlate.py +0 -0
  56. {margin-0.8.1 → margin-0.8.2}/tests/test_diff.py +0 -0
  57. {margin-0.8.1 → margin-0.8.2}/tests/test_drift.py +0 -0
  58. {margin-0.8.1 → margin-0.8.2}/tests/test_events.py +0 -0
  59. {margin-0.8.1 → margin-0.8.2}/tests/test_forecast.py +0 -0
  60. {margin-0.8.1 → margin-0.8.2}/tests/test_health.py +0 -0
  61. {margin-0.8.1 → margin-0.8.2}/tests/test_healthcare.py +0 -0
  62. {margin-0.8.1 → margin-0.8.2}/tests/test_intent.py +0 -0
  63. {margin-0.8.1 → margin-0.8.2}/tests/test_ledger.py +0 -0
  64. {margin-0.8.1 → margin-0.8.2}/tests/test_loop.py +0 -0
  65. {margin-0.8.1 → margin-0.8.2}/tests/test_neuro.py +0 -0
  66. {margin-0.8.1 → margin-0.8.2}/tests/test_observation.py +0 -0
  67. {margin-0.8.1 → margin-0.8.2}/tests/test_persist.py +0 -0
  68. {margin-0.8.1 → margin-0.8.2}/tests/test_policy.py +0 -0
  69. {margin-0.8.1 → margin-0.8.2}/tests/test_policy_compose.py +0 -0
  70. {margin-0.8.1 → margin-0.8.2}/tests/test_policy_temporal.py +0 -0
  71. {margin-0.8.1 → margin-0.8.2}/tests/test_policy_trace.py +0 -0
  72. {margin-0.8.1 → margin-0.8.2}/tests/test_policy_tuning.py +0 -0
  73. {margin-0.8.1 → margin-0.8.2}/tests/test_policy_validate.py +0 -0
  74. {margin-0.8.1 → margin-0.8.2}/tests/test_predicates.py +0 -0
  75. {margin-0.8.1 → margin-0.8.2}/tests/test_printer3d.py +0 -0
  76. {margin-0.8.1 → margin-0.8.2}/tests/test_provenance.py +0 -0
  77. {margin-0.8.1 → margin-0.8.2}/tests/test_reverse_bridge.py +0 -0
  78. {margin-0.8.1 → margin-0.8.2}/tests/test_ros2.py +0 -0
  79. {margin-0.8.1 → margin-0.8.2}/tests/test_staleness.py +0 -0
  80. {margin-0.8.1 → margin-0.8.2}/tests/test_streaming.py +0 -0
  81. {margin-0.8.1 → margin-0.8.2}/tests/test_transformer.py +0 -0
  82. {margin-0.8.1 → margin-0.8.2}/tests/test_transitions.py +0 -0
  83. {margin-0.8.1 → margin-0.8.2}/tests/test_uncertain.py +0 -0
  84. {margin-0.8.1 → margin-0.8.2}/tests/test_validity.py +0 -0
  85. {margin-0.8.1 → margin-0.8.2}/tests/test_windowing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: margin
3
- Version: 0.8.1
3
+ Version: 0.8.2
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
@@ -45,6 +45,10 @@ class CausalLink:
45
45
  strength: 0.0-1.0, how strong the relationship is (1.0 = deterministic)
46
46
  condition: optional — this link only applies when source is in this health state
47
47
  evidence: free text — why we believe this link exists
48
+ origin: "asserted" (manually declared) or "discovered" (auto_causal_graph).
49
+ Asserted links are authoritative. Discovered links are correlational
50
+ heuristics — lag-based causal direction is plausible but not proven.
51
+ Never treat discovered links as ground truth in high-stakes domains.
48
52
  """
49
53
  source: str
50
54
  target: str
@@ -52,6 +56,15 @@ class CausalLink:
52
56
  strength: float = 1.0
53
57
  condition: Optional[Health] = None
54
58
  evidence: str = ""
59
+ origin: str = "asserted" # "asserted" | "discovered"
60
+
61
+ @property
62
+ def is_asserted(self) -> bool:
63
+ return self.origin == "asserted"
64
+
65
+ @property
66
+ def is_discovered(self) -> bool:
67
+ return self.origin == "discovered"
55
68
 
56
69
  def to_dict(self) -> dict:
57
70
  d = {
@@ -59,6 +72,7 @@ class CausalLink:
59
72
  "cause_type": self.cause_type.value,
60
73
  "strength": round(self.strength, 4),
61
74
  "evidence": self.evidence,
75
+ "origin": self.origin,
62
76
  }
63
77
  if self.condition:
64
78
  d["condition"] = self.condition.value
@@ -72,11 +86,13 @@ class CausalLink:
72
86
  strength=d.get("strength", 1.0),
73
87
  condition=Health(d["condition"]) if "condition" in d else None,
74
88
  evidence=d.get("evidence", ""),
89
+ origin=d.get("origin", "asserted"),
75
90
  )
76
91
 
77
92
  def __repr__(self) -> str:
78
93
  cond = f" when {self.condition.value}" if self.condition else ""
79
- return f"{self.source} --{self.cause_type.value}--> {self.target}{cond}"
94
+ tag = "[discovered]" if self.is_discovered else ""
95
+ return f"{self.source} --{self.cause_type.value}--> {self.target}{cond}{tag}"
80
96
 
81
97
 
82
98
  # -----------------------------------------------------------------------
@@ -124,6 +140,14 @@ class CausalGraph:
124
140
  """All links where `component` is the source (what it affects)."""
125
141
  return [l for l in self.links if l.source == component]
126
142
 
143
+ def asserted_links(self) -> list[CausalLink]:
144
+ """Links that were manually declared (authoritative)."""
145
+ return [l for l in self.links if l.is_asserted]
146
+
147
+ def discovered_links(self) -> list[CausalLink]:
148
+ """Links auto-discovered via correlation (heuristic, not proven)."""
149
+ return [l for l in self.links if l.is_discovered]
150
+
127
151
  def upstream(self, component: str, depth: int = 10) -> list[str]:
128
152
  """All components upstream of `component` (transitive causes)."""
129
153
  visited = set()
@@ -85,6 +85,7 @@ class Correlation:
85
85
  cause_type=cause_type,
86
86
  strength=self.strength,
87
87
  evidence=f"auto-correlated: r={self.coefficient:.3f}, lag={self.lag}, n={self.n_samples}",
88
+ origin="discovered", # lag-based causal direction is a heuristic, not proven
88
89
  )
89
90
 
90
91
  def to_dict(self) -> dict:
@@ -109,12 +109,20 @@ class Ledger:
109
109
  """
110
110
  Accumulates Records across a session.
111
111
  Provides aggregate stats and renders the intervention history.
112
+
113
+ max_records: optional bound on records kept. When set, old records
114
+ are dropped (oldest first) on each append. Use this for
115
+ long-running production loops to prevent unbounded growth.
116
+ None (default) = unbounded, suitable for batch/replay use.
112
117
  """
113
118
  label: str = ""
114
119
  records: list[Record] = field(default_factory=list)
120
+ max_records: Optional[int] = None
115
121
 
116
122
  def append(self, record: Record) -> None:
117
123
  self.records.append(record)
124
+ if self.max_records is not None and len(self.records) > self.max_records:
125
+ self.records.pop(0)
118
126
 
119
127
  def __len__(self) -> int:
120
128
  return len(self.records)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: margin
3
- Version: 0.8.1
3
+ Version: 0.8.2
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.8.1"
7
+ version = "0.8.2"
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"}
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