mikeboone Claude Fable 5.1 commited on
Commit
bdd2c81
Β·
1 Parent(s): e429fd8

fix(formula): a formula constant by algebra is caught before generation, and the gate drops it without a recompute (R4)

Browse files

Frontline replay (run 5ec4b833c11b, test-mcp 1c5f261): the LLM authored
POLICY_UNDERWRITING.RATE_ON_LINE = WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55),
which is 0.55 on every row by algebra. The Wave 1 identity guard recognises
shapes (X, X*1, 1*X, X/1, X+0) and could not see this one; the column loaded
flat, and the post-load gate recomputed it from the same formula, re-profiled,
and posted a send-blocking repair_failed on top of measure_constant β€” two
findings and a capped grade for one dropped tile.

Blueprint time β€” formula.constant_value(), beside alias_target(): decide by
EVALUATION, not symbolic algebra. Probe the formula on twelve seeded random
input vectors (0.2x..5x of each identifier's scale, signed identifiers on both
sides of zero) and call it constant only when every output agrees within
1e-9; a literal has no inputs and is its own constant; anything that does not
parse or evaluate is None (validate() reports those). The blueprint passes its
siblings' scales and signs (_formula_constant), so a clamp or a rounding step
is judged where the data will be, not at 1.0. formula_problems() reports a
constant beside the identity report, so the LLM repair round sees it; the
repair loop's pending filter picks it up next to the alias check, and
_repair_one_formula demotes it with a message that names the formula and says
it is CONSTANT. A nonzero constant is the one thing the author told us β€” the
magnitude β€” so it is sampled in a Β±25% band around that value (a donor's
scale would have put a 0.55 rate at 15..85); a constant zero (X - X, X * 0)
takes the donor path or is dropped, like any other broken formula.

Gate β€” a `constant` defect takes the mirrors_other_column route: never a
recompute, so repair_failed cannot be raised for it; a derived constant is
dropped by _should_omit with one measure_constant finding whose detail names
the formula, a base constant is kept on the board and named.

Tests: constant_value cases for X/(X/c), X-X, X*0, X/X, a literal, signed
probing, scale-aware rounding, and the shapes that must stay variable;
blueprint demotion/drop paths for each; gate: a constant derived column
yields exactly one measure_constant finding, no UPDATE, no repair_failed,
and a base constant is kept.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

demoprep_app/dataset/formula.py CHANGED
@@ -30,6 +30,7 @@ from __future__ import annotations
30
  import ast
31
  import math
32
  import operator
 
33
  from typing import Any, Callable, Iterable, Mapping, MutableSequence
34
 
35
 
@@ -582,6 +583,72 @@ def alias_target(formula: str) -> str:
582
  return node.id if isinstance(node, ast.Name) else ""
583
 
584
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
585
  def _literal(node: ast.AST) -> float | None:
586
  """The value of a bare numeric literal node, else None."""
587
  if (isinstance(node, ast.Constant) and isinstance(node.value, (int, float))
 
30
  import ast
31
  import math
32
  import operator
33
+ import random
34
  from typing import Any, Callable, Iterable, Mapping, MutableSequence
35
 
36
 
 
583
  return node.id if isinstance(node, ast.Name) else ""
584
 
585
 
586
+ def constant_value(
587
+ formula: str,
588
+ *,
589
+ scales: Mapping[str, float] | None = None,
590
+ signed: Iterable[str] = (),
591
+ samples: int = 12,
592
+ ) -> float | None:
593
+ """The one value this formula produces for EVERY input, or None if it varies.
594
+
595
+ Decided by EVALUATION, not algebra. alias_target() recognises the
596
+ identities an LLM writes by their shape (`X * 1`, `X + 0`); it cannot
597
+ recognise Frontline's RATE_ON_LINE = WRITTEN_PREMIUM / (WRITTEN_PREMIUM /
598
+ 0.55) (2026-10-20, run 5ec4b833c11b), which is 0.55 on every row by
599
+ algebra, and there is no end to the shapes that are. So instead: evaluate
600
+ the formula on several random input vectors and ask whether the output
601
+ moved. A formula whose output is the same for every vector cannot produce
602
+ a measure β€” it is a flat tile β€” and belongs with the identity guard:
603
+ caught BEFORE generation, where the repair loop demotes or drops it, not
604
+ after the load, where the gate recomputed it from the same formula and
605
+ posted repair_failed on top of measure_constant.
606
+
607
+ A literal (`0.55`) has no inputs and is its own constant. Anything that
608
+ does not parse or cannot be evaluated returns None: validate() reports
609
+ those, and a constant verdict must never be reached by accident.
610
+
611
+ scales: {identifier: typical magnitude}, so a clamp or a rounding step is
612
+ probed at the measure's own scale β€” `MIN(MAX(A / B, 0), 1)` sits on
613
+ its cap for a 0.75 rate only now and then, and `ROUND(X / 1e6, 1)` is
614
+ a real computation for a seven-figure X and all zeros for a two-figure
615
+ one. An identifier with no scale is probed around 1.0.
616
+ signed: identifiers that may be negative. They are probed on both sides of
617
+ zero, so `MIN(VARIANCE, 0)` β€” the downside of a signed variance β€” is
618
+ not called constant for never having seen a negative input.
619
+ samples: how many vectors. A true constant is constant on all of them, so
620
+ every extra vector only makes a FALSE "constant" verdict less likely;
621
+ a capped ratio can sit on its cap for a few draws in a row, so twelve.
622
+ """
623
+ try:
624
+ node = parse(formula)
625
+ except FormulaEvaluationError:
626
+ return None
627
+ names = sorted(identifiers(formula))
628
+ magnitudes = {str(name): abs(float(value)) or 1.0 for name, value in (scales or {}).items()}
629
+ negatives = {str(name) for name in signed}
630
+ # Seeded by the formula text, so a re-parse of the same blueprint reaches
631
+ # the same verdict. Each input spreads over 0.2x..5x of its scale.
632
+ rng = random.Random(f"constant_value:{formula}")
633
+ seen: float | None = None
634
+ for i in range(samples if names else 1):
635
+ values: dict[str, float] = {}
636
+ for name in names:
637
+ draw = magnitudes.get(name, 1.0) * math.exp(rng.uniform(math.log(0.2), math.log(5.0)))
638
+ values[name] = -draw if (name in negatives and i % 2) else draw
639
+ try:
640
+ value = float(_eval_node(node, values, measure="", formula=formula, warnings=[]))
641
+ except (FormulaEvaluationError, ArithmeticError, ValueError):
642
+ return None
643
+ if math.isnan(value) or math.isinf(value):
644
+ return None
645
+ if seen is None:
646
+ seen = value
647
+ elif not math.isclose(value, seen, rel_tol=1e-9, abs_tol=1e-9):
648
+ return None
649
+ return seen
650
+
651
+
652
  def _literal(node: ast.AST) -> float | None:
653
  """The value of a bare numeric literal node, else None."""
654
  if (isinstance(node, ast.Constant) and isinstance(node.value, (int, float))
demoprep_app/integrations/snowflake/quality_gate.py CHANGED
@@ -555,13 +555,30 @@ def _column_defects(
555
  })
556
  continue
557
  if s["min"] is not None and s["max"] is not None and s["min"] == s["max"] and row_count > 1:
558
- defects.append({
559
- "table": table_name, "column": col, "defect": "constant",
560
- "detail": f"every row is {s['min']}",
561
- "suggestion": (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
562
  f"give {col} real variation (params.sigma, or a formula whose inputs vary) β€” "
563
  "a constant measure is a flat tile with no story"
564
- ),
 
 
 
565
  })
566
  if is_flag_column(col) and s.get("non_binary"):
567
  defects.append({
@@ -753,14 +770,19 @@ def _repair_statements(
753
  ))
754
  return statements
755
 
756
- if defect["defect"] == "mirrors_other_column":
757
- # Never "repair" a mirror by recomputing it: the column IS its formula
758
- # over these inputs, so the recompute reproduces the copy, the re-profile
759
- # still mirrors, and the run posts repair_failed on top of the mirror
760
- # (Humpty Dump, 2026-10-13: three builds in 70 minutes on one measure).
761
- # A mirror is a blueprint defect; _OMIT_WORTHY drops the column.
 
 
 
 
 
762
  return []
763
- # all_zero / constant: only a formula can fix these.
764
  return recompute()
765
 
766
 
@@ -772,8 +794,9 @@ _REPAIR_ORDER = {"part_exceeds_whole": 0, "flag_not_binary": 1,
772
 
773
 
774
  def _repair_rank(defect: dict) -> int:
775
- # Default 3: a pure recompute (all_zero / constant / mirror) runs LAST, so
776
- # it reads inputs that have already been bounded or binarised.
 
777
  return _REPAIR_ORDER.get(defect["defect"], 3)
778
 
779
 
 
555
  })
556
  continue
557
  if s["min"] is not None and s["max"] is not None and s["min"] == s["max"] and row_count > 1:
558
+ constant_formula = formulas.get(f"{table_name}.{col}", "")
559
+ if constant_formula:
560
+ # A derived constant is its formula's doing β€” Frontline's
561
+ # RATE_ON_LINE = WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55) is
562
+ # 0.55 on every row by algebra (2026-10-20). Name the formula:
563
+ # the fix is in the blueprint, and _should_omit drops the column.
564
+ detail = (
565
+ f"every row is {s['min']} β€” the formula '{constant_formula}' produced the "
566
+ "same value for every row"
567
+ )
568
+ suggestion = (
569
+ f"{col} = '{constant_formula}' is constant, so it is a flat tile, not a "
570
+ f"measure: give {col} a formula whose output changes with its inputs in the "
571
+ f"blueprint, or drop {col}"
572
+ )
573
+ else:
574
+ detail = f"every row is {s['min']}"
575
+ suggestion = (
576
  f"give {col} real variation (params.sigma, or a formula whose inputs vary) β€” "
577
  "a constant measure is a flat tile with no story"
578
+ )
579
+ defects.append({
580
+ "table": table_name, "column": col, "defect": "constant",
581
+ "detail": detail, "suggestion": suggestion,
582
  })
583
  if is_flag_column(col) and s.get("non_binary"):
584
  defects.append({
 
770
  ))
771
  return statements
772
 
773
+ if defect["defect"] in ("mirrors_other_column", "constant"):
774
+ # Never "repair" a mirror or a constant by recomputing it: the column
775
+ # IS its formula over these inputs, so the recompute reproduces the
776
+ # copy, the re-profile still shows the defect, and the run posts
777
+ # repair_failed on top of it β€” two findings and a capped grade for one
778
+ # dropped tile (Humpty Dump, 2026-10-13: three builds in 70 minutes on
779
+ # one mirror; Frontline, 2026-10-20: repair_failed on top of
780
+ # measure_constant for RATE_ON_LINE = X / (X / 0.55)). Both are
781
+ # blueprint defects: a mirror and a derived constant are dropped by
782
+ # _should_omit, a base constant (no formula, nothing to recompute
783
+ # anyway) is kept on the board and named.
784
  return []
785
+ # all_zero: only a formula can fix it.
786
  return recompute()
787
 
788
 
 
794
 
795
 
796
  def _repair_rank(defect: dict) -> int:
797
+ # Default 3: a pure recompute (all_zero) runs LAST, so it reads inputs that
798
+ # have already been bounded or binarised. A mirror or a constant has no
799
+ # repair at all (see _repair_statements) and only takes this rank.
800
  return _REPAIR_ORDER.get(defect["defect"], 3)
801
 
802
 
demoprep_app/scenario/blueprint.py CHANGED
@@ -31,6 +31,7 @@ from demoprep_app.dataset.formula import (
31
  difference_pairs as formula_difference_pairs,
32
  identifiers as formula_identifiers,
33
  alias_target as formula_alias_target,
 
34
  is_signed as formula_is_signed,
35
  parse as parse_formula,
36
  ratio_pairs as formula_ratio_pairs,
@@ -949,11 +950,24 @@ class DemoBlueprint:
949
  issues: list[str] = []
950
  for fact in self.facts:
951
  allowed = {m.name for m in fact.measures}
 
952
  for m in fact.measures:
953
  if m.kind != "derived" or not m.formula:
954
  continue
955
- for problem in validate_formula(m.formula, allowed - {m.name}, measure=m.name):
 
956
  issues.append(f"{problem} (fact {fact.name})")
 
 
 
 
 
 
 
 
 
 
 
957
  return issues
958
 
959
  def repair_formulas(self) -> list[str]:
@@ -981,11 +995,17 @@ class DemoBlueprint:
981
  # board shipped Baseline and Optimized Revenue equal to the cent
982
  # on all eight categories. Repair it like any other broken
983
  # formula rather than shipping the duplicate silently.
 
 
 
 
 
984
  pending = [
985
  m for m in fact.measures
986
  if m.kind == "derived" and (
987
  validate_formula(m.formula, set(by_name) - {m.name}, measure=m.name)
988
  or formula_alias_target(m.formula) in (set(by_name) - {m.name})
 
989
  )
990
  ]
991
  if not pending:
@@ -1813,6 +1833,49 @@ def _alias_reason(measure, by_name: dict) -> str:
1813
  return ""
1814
 
1815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1816
  def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1817
  """Case-fix, demote, or drop ONE uncomputable derived measure."""
1818
  siblings = {name for name in by_name if name != measure.name}
@@ -1820,7 +1883,11 @@ def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1820
  # 0. A copy is not broken, so the case-fix path below cannot help it and the
1821
  # message must not claim it is "not computable". Go straight to demotion,
1822
  # which gives the measure its own variation off the source it copied.
 
1823
  alias_reason = _alias_reason(measure, by_name)
 
 
 
1824
 
1825
  # 1. case-only mismatches are a rewrite, not a loss
1826
  upper_map = {name.upper(): name for name in siblings}
@@ -1834,11 +1901,35 @@ def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1834
  import re as _re
1835
  rewritten = _re.sub(rf"\b{_re.escape(token)}\b", target, rewritten)
1836
  renames.append(f"{token}->{target}")
1837
- if not alias_reason and renames and not validate_formula(rewritten, siblings, measure=measure.name):
 
 
1838
  old = measure.formula
1839
  measure.formula = rewritten
1840
  return [f"{measure.name}: formula '{old}' -> '{rewritten}' ({', '.join(renames)})"]
1841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1842
  # 2. demote to a base measure scaled off a sibling the formula referenced
1843
  donor = _pick_donor(measure, by_name)
1844
  if donor is not None:
@@ -1893,7 +1984,7 @@ def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1893
  measure.params = {"low": round(low, 6), "high": round(high, 6)}
1894
  shape = f"rate in {measure.params['low']}..{measure.params['high']}"
1895
  return [
1896
- f"{measure.name}: " + (alias_reason or f"formula '{old}' is not computable in fact {fact.name}") + " "
1897
  f"-> base measure on {donor.name}'s scale ({shape}). "
1898
  "The tile stays on the board; the value is sampled, not derived."
1899
  ]
@@ -1913,7 +2004,7 @@ def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1913
  measure.params = {"mean": spread, "sigma": 0.5}
1914
  shape = f"mean {spread}"
1915
  return [
1916
- f"{measure.name}: " + (alias_reason or f"formula '{old}' is not computable in fact {fact.name}") + " "
1917
  f"-> base measure scaled off {donor.name} ({shape}). "
1918
  "The tile stays on the board; the value is sampled, not derived."
1919
  ]
@@ -1929,13 +2020,13 @@ def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1929
  measure.params = {"mean": 100.0, "sigma": 0.5}
1930
  measure.share_of = ""
1931
  return [
1932
- f"{measure.name}: formula '{old}' is not computable and it is the only measure in "
1933
- f"fact {fact.name} -> sampled base measure, so the fact still has something to chart."
1934
  ]
1935
  fact.measures = [m for m in fact.measures if m.name != measure.name]
1936
  return [
1937
- f"{measure.name}: dropped β€” formula '{old}' is not computable in fact {fact.name} "
1938
- "and no sibling measure to scale it off. The demo ships without this measure."
1939
  ]
1940
 
1941
 
 
31
  difference_pairs as formula_difference_pairs,
32
  identifiers as formula_identifiers,
33
  alias_target as formula_alias_target,
34
+ constant_value as formula_constant_value,
35
  is_signed as formula_is_signed,
36
  parse as parse_formula,
37
  ratio_pairs as formula_ratio_pairs,
 
950
  issues: list[str] = []
951
  for fact in self.facts:
952
  allowed = {m.name for m in fact.measures}
953
+ by_name = {m.name: m for m in fact.measures}
954
  for m in fact.measures:
955
  if m.kind != "derived" or not m.formula:
956
  continue
957
+ problems = validate_formula(m.formula, allowed - {m.name}, measure=m.name)
958
+ for problem in problems:
959
  issues.append(f"{problem} (fact {fact.name})")
960
+ if problems:
961
+ continue
962
+ # Valid, computable, and useless: the same value on every row.
963
+ # Reported here, beside validate()'s identity report, so the
964
+ # LLM repair round sees it before repair_formulas() demotes it.
965
+ reason, _ = _constant_reason(m, by_name)
966
+ if reason:
967
+ issues.append(
968
+ f"Measure {m.name}: {reason}. Compute something that changes with its "
969
+ f"inputs, or drop this measure. (fact {fact.name})"
970
+ )
971
  return issues
972
 
973
  def repair_formulas(self) -> list[str]:
 
995
  # board shipped Baseline and Optimized Revenue equal to the cent
996
  # on all eight categories. Repair it like any other broken
997
  # formula rather than shipping the duplicate silently.
998
+ # A CONSTANT is the same defect in a shape no identity check
999
+ # can enumerate: Frontline's RATE_ON_LINE = WRITTEN_PREMIUM /
1000
+ # (WRITTEN_PREMIUM / 0.55) is 0.55 on every row by algebra
1001
+ # (R4, 2026-10-20). Found by evaluating the formula, not by
1002
+ # recognising it β€” see formula.constant_value().
1003
  pending = [
1004
  m for m in fact.measures
1005
  if m.kind == "derived" and (
1006
  validate_formula(m.formula, set(by_name) - {m.name}, measure=m.name)
1007
  or formula_alias_target(m.formula) in (set(by_name) - {m.name})
1008
+ or _formula_constant(m, by_name) is not None
1009
  )
1010
  ]
1011
  if not pending:
 
1833
  return ""
1834
 
1835
 
1836
+ def _measure_scale(measure) -> float:
1837
+ """A positive magnitude typical of this measure, for probing a formula."""
1838
+ params = measure.params or {}
1839
+
1840
+ def number(key: str) -> float:
1841
+ value = params.get(key)
1842
+ if isinstance(value, (int, float)) and not isinstance(value, bool):
1843
+ return abs(float(value))
1844
+ return 0.0
1845
+
1846
+ low, high = number("low"), number("high")
1847
+ for candidate in (number("mean"), number("sigma"), (low + high) / 2.0, high):
1848
+ if candidate > 0:
1849
+ return candidate
1850
+ return 1.0
1851
+
1852
+
1853
+ def _formula_constant(measure, by_name: dict) -> float | None:
1854
+ """The one value `measure.formula` takes on every row, or None if it varies.
1855
+
1856
+ Probes the formula at its siblings' own scales and signs (see
1857
+ formula.constant_value), so a clamp or a rounding step is judged where the
1858
+ data will actually be, not at 1.0.
1859
+ """
1860
+ siblings = {name: m for name, m in by_name.items() if name != measure.name}
1861
+ return formula_constant_value(
1862
+ measure.formula,
1863
+ scales={name: _measure_scale(m) for name, m in siblings.items()},
1864
+ signed={name for name, m in siblings.items() if getattr(m, "signed", False)},
1865
+ )
1866
+
1867
+
1868
+ def _constant_reason(measure, by_name: dict) -> tuple[str, float | None]:
1869
+ """(why, value) when this measure's formula is constant, else ("", None)."""
1870
+ value = _formula_constant(measure, by_name)
1871
+ if value is None:
1872
+ return "", None
1873
+ return (
1874
+ f"formula '{measure.formula}' is CONSTANT β€” it evaluates to {value:g} whatever its "
1875
+ "inputs are, so it would ship a flat column with no story"
1876
+ ), value
1877
+
1878
+
1879
  def _repair_one_formula(fact, measure, by_name: dict) -> list[str]:
1880
  """Case-fix, demote, or drop ONE uncomputable derived measure."""
1881
  siblings = {name for name in by_name if name != measure.name}
 
1883
  # 0. A copy is not broken, so the case-fix path below cannot help it and the
1884
  # message must not claim it is "not computable". Go straight to demotion,
1885
  # which gives the measure its own variation off the source it copied.
1886
+ # A CONSTANT is the same: valid, computable, and a flat column.
1887
  alias_reason = _alias_reason(measure, by_name)
1888
+ constant_reason, constant = ("", None) if alias_reason else _constant_reason(measure, by_name)
1889
+ why = (alias_reason or constant_reason
1890
+ or f"formula '{measure.formula}' is not computable in fact {fact.name}")
1891
 
1892
  # 1. case-only mismatches are a rewrite, not a loss
1893
  upper_map = {name.upper(): name for name in siblings}
 
1901
  import re as _re
1902
  rewritten = _re.sub(rf"\b{_re.escape(token)}\b", target, rewritten)
1903
  renames.append(f"{token}->{target}")
1904
+ if not (alias_reason or constant_reason) and renames and not validate_formula(
1905
+ rewritten, siblings, measure=measure.name
1906
+ ):
1907
  old = measure.formula
1908
  measure.formula = rewritten
1909
  return [f"{measure.name}: formula '{old}' -> '{rewritten}' ({', '.join(renames)})"]
1910
 
1911
+ # 1b. A formula constant at a NONZERO value has told us one thing only: the
1912
+ # magnitude its author had in mind. Frontline's RATE_ON_LINE =
1913
+ # WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55) means "about 0.55", and a
1914
+ # donor's scale (the premium, six figures) would put that rate at
1915
+ # 15..85. Sample around the value the formula produced instead; the
1916
+ # bound pass in harden() still applies the measure's own range. A
1917
+ # constant ZERO (`X - X`, `X * 0`) says nothing about magnitude and
1918
+ # takes the donor path below like any other broken formula.
1919
+ if constant:
1920
+ low, high = sorted((round(constant * 0.75, 6), round(constant * 1.25, 6)))
1921
+ measure.kind = "base"
1922
+ measure.formula = ""
1923
+ measure.share_of = ""
1924
+ measure.distribution = "uniform"
1925
+ measure.signed = constant < 0
1926
+ measure.params = {"low": low, "high": high}
1927
+ return [
1928
+ f"{measure.name}: {constant_reason} -> base measure sampled in {low:g}..{high:g}, "
1929
+ "around the one value the formula produced. The tile stays on the board; the "
1930
+ "value is sampled, not derived."
1931
+ ]
1932
+
1933
  # 2. demote to a base measure scaled off a sibling the formula referenced
1934
  donor = _pick_donor(measure, by_name)
1935
  if donor is not None:
 
1984
  measure.params = {"low": round(low, 6), "high": round(high, 6)}
1985
  shape = f"rate in {measure.params['low']}..{measure.params['high']}"
1986
  return [
1987
+ f"{measure.name}: {why} "
1988
  f"-> base measure on {donor.name}'s scale ({shape}). "
1989
  "The tile stays on the board; the value is sampled, not derived."
1990
  ]
 
2004
  measure.params = {"mean": spread, "sigma": 0.5}
2005
  shape = f"mean {spread}"
2006
  return [
2007
+ f"{measure.name}: {why} "
2008
  f"-> base measure scaled off {donor.name} ({shape}). "
2009
  "The tile stays on the board; the value is sampled, not derived."
2010
  ]
 
2020
  measure.params = {"mean": 100.0, "sigma": 0.5}
2021
  measure.share_of = ""
2022
  return [
2023
+ f"{measure.name}: {why}, and it is the only measure in fact {fact.name} -> sampled "
2024
+ "base measure, so the fact still has something to chart."
2025
  ]
2026
  fact.measures = [m for m in fact.measures if m.name != measure.name]
2027
  return [
2028
+ f"{measure.name}: dropped β€” {why}, and no sibling measure to scale it off. "
2029
+ "The demo ships without this measure."
2030
  ]
2031
 
2032
 
tests/test_blueprint_measure_hardening.py CHANGED
@@ -384,3 +384,93 @@ def test_each_formula_repair_is_reported_exactly_once():
384
  bp.autorepair()
385
  repairs = [f for f in bp.metadata.get("autorepairs", []) if "MARGIN_ERROR" in f]
386
  assert len(repairs) == 1, repairs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  bp.autorepair()
385
  repairs = [f for f in bp.metadata.get("autorepairs", []) if "MARGIN_ERROR" in f]
386
  assert len(repairs) == 1, repairs
387
+
388
+
389
+ # --- constant formulas are demoted BEFORE generation (findings triage R4) ------
390
+ # Frontline (2026-10-20, run 5ec4b833c11b): RATE_ON_LINE = WRITTEN_PREMIUM /
391
+ # (WRITTEN_PREMIUM / 0.55) is 0.55 on every row by algebra. The identity guard
392
+ # did not recognise it, the column loaded flat, and the post-load gate recomputed
393
+ # it from the same formula and posted repair_failed on top of measure_constant.
394
+ # The repair loop now catches it where the identity guard lives.
395
+
396
+
397
+ def _frontline(formula, *, fmt="pct"):
398
+ return _blueprint([
399
+ {"name": "WRITTEN_PREMIUM", "fmt": "currency", "params": {"mean": 250000}},
400
+ {"name": "POLICY_LIMIT", "fmt": "currency", "params": {"mean": 1000000}},
401
+ {"name": "RATE_ON_LINE", "kind": "derived", "formula": formula, "fmt": fmt},
402
+ ], insights=_insights("WRITTEN_PREMIUM"))
403
+
404
+
405
+ def test_a_formula_constant_by_algebra_is_demoted_around_its_value_before_generation():
406
+ bp = _frontline("WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55)")
407
+ # The LLM repair round sees it, beside the identity report.
408
+ problems = bp.formula_problems()
409
+ assert len(problems) == 1 and "RATE_ON_LINE" in problems[0]
410
+ assert "CONSTANT" in problems[0] and "0.55" in problems[0]
411
+
412
+ fixes = bp.repair_formulas()
413
+ m = _measure(bp, "RATE_ON_LINE")
414
+ assert m.kind == "base" and m.formula == ""
415
+ # Sampled around the value the formula produced, not off the premium's scale.
416
+ assert m.distribution == "uniform"
417
+ assert m.params["low"] < 0.55 < m.params["high"]
418
+ assert 0.3 <= m.params["low"] and m.params["high"] <= 0.8
419
+ fix = next(f for f in fixes if f.startswith("RATE_ON_LINE"))
420
+ assert "WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55)" in fix
421
+ assert "CONSTANT" in fix and "0.55" in fix and "not computable" not in fix
422
+ assert bp.formula_problems() == []
423
+
424
+ rows = BlueprintEngine().generate(bp, 500).table_map()["LOAD_TRANSACTION"].rows
425
+ values = {round(r["RATE_ON_LINE"], 6) for r in rows}
426
+ assert len(values) > 1, "the demoted measure must vary row to row"
427
+ assert all(0.0 < v < 1.0 for v in values)
428
+
429
+
430
+ def test_a_literal_formula_is_constant_too():
431
+ bp = _frontline("0.55")
432
+ # from_dict() already hardened the pct formula into its MIN/MAX wrap; the
433
+ # guard judges the formula as it stands and names that.
434
+ assert _measure(bp, "RATE_ON_LINE").formula == "MIN(MAX(0.55, 0), 1)"
435
+ fixes = bp.repair_formulas()
436
+ m = _measure(bp, "RATE_ON_LINE")
437
+ assert m.kind == "base" and m.distribution == "uniform"
438
+ assert m.params["low"] < 0.55 < m.params["high"]
439
+ assert any("'MIN(MAX(0.55, 0), 1)' is CONSTANT" in f and "0.55 whatever" in f for f in fixes)
440
+
441
+
442
+ def test_a_formula_constant_at_zero_takes_the_donor_path_and_says_why():
443
+ # X - X and X * 0 say nothing about magnitude, so they demote off a sibling
444
+ # like any other broken formula β€” a difference signed and centred on zero.
445
+ bp = _frontline("WRITTEN_PREMIUM - WRITTEN_PREMIUM", fmt="currency")
446
+ fixes = bp.repair_formulas()
447
+ m = _measure(bp, "RATE_ON_LINE")
448
+ assert m.kind == "base" and m.formula == "" and m.signed is True
449
+ fix = next(f for f in fixes if f.startswith("RATE_ON_LINE"))
450
+ assert "WRITTEN_PREMIUM - WRITTEN_PREMIUM" in fix and "CONSTANT" in fix
451
+ assert "not computable" not in fix
452
+
453
+ bp = _frontline("WRITTEN_PREMIUM * 0", fmt="currency")
454
+ fixes = bp.repair_formulas()
455
+ m = _measure(bp, "RATE_ON_LINE")
456
+ assert m.kind == "base" and m.signed is False
457
+ assert any("WRITTEN_PREMIUM * 0" in f and "CONSTANT" in f for f in fixes)
458
+
459
+
460
+ def test_a_constant_formula_with_nothing_to_scale_off_is_dropped_and_named():
461
+ bp = _blueprint([
462
+ {"name": "BASE_AMOUNT", "fmt": "currency", "params": {"mean": 100}},
463
+ {"name": "DOUBLED", "kind": "derived", "formula": "BASE_AMOUNT * 2"},
464
+ {"name": "ZEROED", "kind": "derived", "formula": "DOUBLED - DOUBLED"},
465
+ ], insights=_insights("BASE_AMOUNT"))
466
+ fixes = bp.repair_formulas()
467
+ assert {m.name for m in bp.facts[0].measures} == {"BASE_AMOUNT", "DOUBLED"}
468
+ fix = next(f for f in fixes if f.startswith("ZEROED"))
469
+ assert "dropped" in fix and "DOUBLED - DOUBLED" in fix and "CONSTANT" in fix
470
+
471
+
472
+ def test_a_real_formula_is_left_alone_by_the_constant_guard():
473
+ bp = _frontline("WRITTEN_PREMIUM / POLICY_LIMIT")
474
+ assert bp.formula_problems() == []
475
+ assert bp.repair_formulas() == []
476
+ assert _measure(bp, "RATE_ON_LINE").kind == "derived"
tests/test_measure_formula.py CHANGED
@@ -13,6 +13,7 @@ import pytest
13
  from demoprep_app.dataset.formula import (
14
  FormulaEvaluationError,
15
  alias_target,
 
16
  evaluate,
17
  identifiers,
18
  ratio_pairs,
@@ -141,6 +142,71 @@ def test_a_real_computation_is_not_an_identity(formula):
141
  assert validate(formula, {"RENTAL_DAYS", "IDLE_DAYS"}, measure="DAYS_ON_SITE") == []
142
 
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  # --- helpers ----------------------------------------------------------------
145
 
146
 
 
13
  from demoprep_app.dataset.formula import (
14
  FormulaEvaluationError,
15
  alias_target,
16
+ constant_value,
17
  evaluate,
18
  identifiers,
19
  ratio_pairs,
 
142
  assert validate(formula, {"RENTAL_DAYS", "IDLE_DAYS"}, measure="DAYS_ON_SITE") == []
143
 
144
 
145
+ # --- constant formulas cannot produce a measure (findings triage 2026-10-20, R4)
146
+ #
147
+ # Frontline's RATE_ON_LINE = WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55) is 0.55
148
+ # on every row by algebra. The identity guard above recognises shapes; it
149
+ # cannot enumerate every algebraic identity, so constant_value() EVALUATES the
150
+ # formula on random inputs and asks whether the output moved. It sits beside
151
+ # alias_target() so there is one place for "this formula cannot produce a
152
+ # measure", and the blueprint repair loop demotes or drops it before generation.
153
+
154
+
155
+ @pytest.mark.parametrize("formula, value", [
156
+ ("WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55)", 0.55), # the Frontline case
157
+ ("WRITTEN_PREMIUM - WRITTEN_PREMIUM", 0.0),
158
+ ("WRITTEN_PREMIUM * 0", 0.0),
159
+ ("0.55", 0.55), # a literal: no inputs at all
160
+ ("WRITTEN_PREMIUM / WRITTEN_PREMIUM", 1.0),
161
+ ("(WRITTEN_PREMIUM + POLICY_LIMIT) * 0 + 7", 7.0),
162
+ ("ROUND(WRITTEN_PREMIUM * 0.55 / WRITTEN_PREMIUM, 2)", 0.55),
163
+ ])
164
+ def test_a_formula_that_cannot_vary_is_reported_with_its_value(formula, value):
165
+ assert constant_value(formula) == pytest.approx(value)
166
+
167
+
168
+ @pytest.mark.parametrize("formula", [
169
+ "WRITTEN_PREMIUM / POLICY_LIMIT", "WRITTEN_PREMIUM * 0.55", "WRITTEN_PREMIUM - POLICY_LIMIT",
170
+ "MIN(MAX(WRITTEN_PREMIUM / POLICY_LIMIT, 0), 1)", "ROUND(WRITTEN_PREMIUM / POLICY_LIMIT, 2)",
171
+ "1 / WRITTEN_PREMIUM", "ABS(WRITTEN_PREMIUM)", "COALESCE(WRITTEN_PREMIUM, 0)",
172
+ "WRITTEN_PREMIUM * 1", # an identity varies: that is alias_target's case
173
+ ])
174
+ def test_a_formula_that_varies_with_its_inputs_is_not_constant(formula):
175
+ assert constant_value(formula) is None
176
+
177
+
178
+ def test_constant_detection_is_by_evaluation_so_it_never_guesses():
179
+ # Not parseable, or not evaluable: validate() reports those; a constant
180
+ # verdict is only ever reached on a formula that actually ran.
181
+ assert constant_value("this is not ( a formula") is None
182
+ assert constant_value("SQRT(WRITTEN_PREMIUM) * 0") is None
183
+ assert constant_value("") is None
184
+ # Deterministic for the same formula text: a re-parse reaches the same verdict.
185
+ assert constant_value("WRITTEN_PREMIUM / POLICY_LIMIT") is None
186
+ assert constant_value("WRITTEN_PREMIUM / (WRITTEN_PREMIUM / 0.55)") == pytest.approx(0.55)
187
+
188
+
189
+ def test_a_signed_input_is_probed_on_both_sides_of_zero():
190
+ # MIN(V, 0) is the downside of a signed variance. Probed only with positive
191
+ # inputs it would read as constant 0 and lose the tile.
192
+ assert constant_value("MIN(BUDGET_VARIANCE, 0)", signed={"BUDGET_VARIANCE"}) is None
193
+ # ...while a formula that really is constant on both sides stays caught.
194
+ assert constant_value("MAX(BUDGET_VARIANCE, 0) * MIN(BUDGET_VARIANCE, 0)",
195
+ signed={"BUDGET_VARIANCE"}) == pytest.approx(0.0)
196
+
197
+
198
+ def test_a_rounding_step_is_judged_at_the_measures_own_scale():
199
+ # ROUND(X / 1e6, 1) is a real computation for a seven-figure premium and a
200
+ # column of zeros for a two-figure one β€” the scale decides, not the shape.
201
+ formula = "ROUND(WRITTEN_PREMIUM / 1000000, 1)"
202
+ assert constant_value(formula, scales={"WRITTEN_PREMIUM": 5_000_000}) is None
203
+ assert constant_value(formula, scales={"WRITTEN_PREMIUM": 50}) == pytest.approx(0.0)
204
+ # The same for whole hundreds: a six-figure premium varies, an unscaled
205
+ # probe around 1.0 does not β€” which is why the blueprint passes its scales.
206
+ assert constant_value("ROUND(WRITTEN_PREMIUM / 100, 0)", scales={"WRITTEN_PREMIUM": 250000}) is None
207
+ assert constant_value("ROUND(WRITTEN_PREMIUM / 100, 0)") == pytest.approx(0.0)
208
+
209
+
210
  # --- helpers ----------------------------------------------------------------
211
 
212
 
tests/test_quality_gate.py CHANGED
@@ -895,6 +895,78 @@ def test_a_mirror_is_omitted_without_a_recompute_and_names_the_identity():
895
  assert "not a measure of" not in defect["suggestion"]
896
 
897
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
  def test_a_hollow_difference_names_the_input_that_contributed_nothing():
899
  from demoprep_app.integrations.snowflake.quality_gate import _mirror_explanation
900
 
 
895
  assert "not a measure of" not in defect["suggestion"]
896
 
897
 
898
+ def _frontline_cursor(*, rate_formula_known: bool):
899
+ """Frontline's POLICY_UNDERWRITING with RATE_ON_LINE flat at 0.55.
900
+
901
+ Five measures, so one dropped column (20%) stays under the 25% abort line.
902
+ """
903
+ money = lambda lo, hi, avg: {"non_zero": 4000, "min": lo, "max": hi, "avg": avg}
904
+ cursor = FakeCursor(
905
+ columns_rows=[
906
+ ("POLICY_UNDERWRITING", "WRITTEN_PREMIUM_USD", "NUMBER(16,2)"),
907
+ ("POLICY_UNDERWRITING", "POLICY_LIMIT_USD", "NUMBER(16,2)"),
908
+ ("POLICY_UNDERWRITING", "LOSS_PAID_USD", "NUMBER(16,2)"),
909
+ ("POLICY_UNDERWRITING", "EXPENSE_USD", "NUMBER(16,2)"),
910
+ ("POLICY_UNDERWRITING", "RATE_ON_LINE", "NUMBER(16,4)"),
911
+ ],
912
+ profiles={"POLICY_UNDERWRITING": [profile_row(4000, [
913
+ ("WRITTEN_PREMIUM_USD", money(1200.0, 980000.0, 142000.0)),
914
+ ("POLICY_LIMIT_USD", money(10000.0, 5000000.0, 910000.0)),
915
+ ("LOSS_PAID_USD", money(0.0, 640000.0, 61000.0)),
916
+ ("EXPENSE_USD", money(90.0, 88000.0, 12500.0)),
917
+ ("RATE_ON_LINE", {"non_zero": 4000, "min": 0.55, "max": 0.55, "avg": 0.55}),
918
+ ])]},
919
+ part_whole={"POLICY_UNDERWRITING": [(0,), (0,)]},
920
+ )
921
+ formulas = (
922
+ {"POLICY_UNDERWRITING.RATE_ON_LINE": "WRITTEN_PREMIUM_USD / (WRITTEN_PREMIUM_USD / 0.55)"}
923
+ if rate_formula_known else {}
924
+ )
925
+ return cursor, formulas
926
+
927
+
928
+ def test_a_constant_derived_column_is_omitted_without_a_recompute():
929
+ """Frontline (2026-10-20, run 5ec4b833c11b): RATE_ON_LINE = WRITTEN_PREMIUM
930
+ / (WRITTEN_PREMIUM / 0.55) is 0.55 on every row. The gate recomputed it from
931
+ the same formula, re-profiled, and posted repair_failed on top of
932
+ measure_constant β€” two findings and a capped grade for one dropped tile."""
933
+ cursor, formulas = _frontline_cursor(rate_formula_known=True)
934
+ profile = run_measure_quality_gate(FakeConnection(cursor), "FRO_sch", formulas=formulas)
935
+
936
+ assert [d["defect"] for d in profile["defects"]] == ["constant"]
937
+ assert cursor.sql_of_kind("UPDATE") == [], "a constant is never recomputed"
938
+ assert profile["repair_failures"] == [] and profile["repairs"] == []
939
+ assert [o["column"] for o in profile["omissions"]] == ["RATE_ON_LINE"]
940
+ assert cursor.sql_of_kind("ALTER") == [
941
+ 'ALTER TABLE "FRO_sch"."POLICY_UNDERWRITING" DROP COLUMN "RATE_ON_LINE"'
942
+ ]
943
+ assert profile["failures"] == []
944
+ # Exactly one finding for the dropped measure β€” and it is not repair_failed.
945
+ findings = [f for f in profile["findings"] if f["severity"] != "info"]
946
+ assert [f["code"] for f in findings] == ["measure_constant"]
947
+ assert findings[0]["measure"] == "RATE_ON_LINE" and findings[0]["extra"]["omitted"] is True
948
+ assert "DROPPED" in findings[0]["message"]
949
+ defect = profile["defects"][0]
950
+ assert "WRITTEN_PREMIUM_USD / (WRITTEN_PREMIUM_USD / 0.55)" in defect["detail"]
951
+ assert "is constant" in defect["suggestion"] and "blueprint" in defect["suggestion"]
952
+
953
+
954
+ def test_a_constant_base_column_is_kept_on_the_board_and_named():
955
+ # No formula: nothing to recompute and nothing to blame the blueprint for β€”
956
+ # a flat attribute is reported and kept, not dropped.
957
+ cursor, formulas = _frontline_cursor(rate_formula_known=False)
958
+ profile = run_measure_quality_gate(FakeConnection(cursor), "FRO_sch", formulas=formulas)
959
+
960
+ assert [d["defect"] for d in profile["defects"]] == ["constant"]
961
+ assert cursor.sql_of_kind("UPDATE") == [] and cursor.sql_of_kind("ALTER") == []
962
+ assert profile["repair_failures"] == [] and profile["omissions"] == []
963
+ assert [d["column"] for d in profile["failures"]] == ["RATE_ON_LINE"]
964
+ findings = [f for f in profile["findings"] if f["severity"] != "info"]
965
+ assert [f["code"] for f in findings] == ["measure_constant"]
966
+ assert findings[0]["extra"]["omitted"] is False
967
+ assert profile["defects"][0]["detail"] == "every row is 0.55"
968
+
969
+
970
  def test_a_hollow_difference_names_the_input_that_contributed_nothing():
971
  from demoprep_app.integrations.snowflake.quality_gate import _mirror_explanation
972