research(rectification): offline R1/R2/R3 — answer-flip tolerance, V1/V2 rerun, dasha shift arithmetic
- R1: flipping 1 answer keeps truth in range 98-100% but cuts head hit by a third or more; 2 flips squeeze truth out in 7-10% of ±30/±60 replays (two flips = 8 points = SEPARATION_LEAD). - R2: weights do apply (research scorer == production at V0); V1/V2 are identity at ±30/±60 by construction and leave six-question metrics unchanged at ±10 -> no_benefit (measured). Supplementary V1n does not pass the gate. - R3: boundary shift is ~3.8 days/minute (1.3-5.9), not 1.1; the 45-day gate is ~8-34 minutes. The _representative_pairs hypothesis is refuted (all-pairs adds no dated probes); the bottleneck is monthly evaluation. New finding recorded as BUG-1048 (investigating): _boundary_windows year-straddle exemption and positional zip misalignment bypass the gate. - Dated errata appended (no deletions) to the 09-14/09-16 briefs and research docs; README board row -> 待验收. No production code, scoring, thresholds, gates or Skill changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7203d94e9c
commit
0f5442cea2
@@ -0,0 +1,77 @@
|
||||
"""Pure-helper regression tests for the 2026-09-26 offline rectification research.
|
||||
|
||||
Fictional inputs only. These cover the research helpers, not production code.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, timedelta
|
||||
|
||||
from scripts.research.offline_research_20260926_lib import (
|
||||
NAKSHATRA_SPAN,
|
||||
answerable_indices,
|
||||
exhaustive_flip_sets,
|
||||
flipped_answers,
|
||||
nakshatra_lord,
|
||||
sample_flip_sets,
|
||||
shift_days_per_minute,
|
||||
zip_misaligned,
|
||||
)
|
||||
from scripts.research.representative_pairs_probe import strict_boundary_windows
|
||||
from scripts.research.varga_sensitivity_rerun import V1N_FACTORS, factor_table
|
||||
|
||||
MEAN_MOON_DEG_PER_DAY = 13.176
|
||||
|
||||
|
||||
def test_shift_per_minute_is_about_one_year_per_degree_not_122_days() -> None:
|
||||
venus = shift_days_per_minute(NAKSHATRA_SPAN * 1 + 1.0, MEAN_MOON_DEG_PER_DAY)
|
||||
sun = shift_days_per_minute(NAKSHATRA_SPAN * 2 + 1.0, MEAN_MOON_DEG_PER_DAY)
|
||||
assert nakshatra_lord(NAKSHATRA_SPAN * 1 + 1.0) == "Venus"
|
||||
assert nakshatra_lord(NAKSHATRA_SPAN * 2 + 1.0) == "Sun"
|
||||
assert 4.9 < venus < 5.1
|
||||
assert 1.45 < sun < 1.55
|
||||
# The 2026-09-14 figure (1.1 days) is below the slowest lord at mean speed.
|
||||
assert sun > 1.1
|
||||
|
||||
|
||||
def test_flip_sets_are_seeded_and_only_touch_answered_questions() -> None:
|
||||
answers = ["yes", None, "no", "yes", None, "no"]
|
||||
assert answerable_indices(answers) == [0, 2, 3, 5]
|
||||
first = sample_flip_sets(answers, 2, 5, case_id="fictional", radius=10)
|
||||
again = sample_flip_sets(answers, 2, 5, case_id="fictional", radius=10)
|
||||
assert first == again
|
||||
assert all(len(item) == 2 and set(item) <= {0, 2, 3, 5} for item in first)
|
||||
assert sample_flip_sets(answers, 5, 3, case_id="fictional", radius=10) == []
|
||||
assert len(exhaustive_flip_sets(answers, 2)) == 6
|
||||
assert flipped_answers(answers, (0, 2)) == ["no", None, "yes", "yes", None, "no"]
|
||||
|
||||
|
||||
# Unequal spacing, like real dasha periods (equal spacing would make an
|
||||
# off-by-one zip look like a constant shift).
|
||||
OFFSETS = (0, 300, 1000, 1200, 2500, 2600)
|
||||
|
||||
|
||||
def test_zip_misalignment_detects_off_by_one_lists() -> None:
|
||||
base = [date(2000, 1, 10) + timedelta(days=days) for days in OFFSETS]
|
||||
shifted = [item + timedelta(days=20) for item in base]
|
||||
assert not zip_misaligned(base, shifted)
|
||||
assert zip_misaligned(base[1:], shifted)
|
||||
|
||||
|
||||
def test_strict_gate_drops_year_straddle_and_realigns() -> None:
|
||||
left = [date(1999, 12, 28), date(2003, 5, 1)]
|
||||
right = [date(2000, 1, 4), date(2003, 5, 8)]
|
||||
assert strict_boundary_windows(left, right, min_days=45) == []
|
||||
base = [date(2000, 3, 1) + timedelta(days=days) for days in OFFSETS]
|
||||
later = [item + timedelta(days=10) for item in base]
|
||||
assert strict_boundary_windows(base, later[1:], min_days=45) == []
|
||||
far = [item + timedelta(days=60) for item in base]
|
||||
assert len(strict_boundary_windows(base, far, min_days=45)) == 2 * len(OFFSETS)
|
||||
|
||||
|
||||
def test_v1_saturates_on_wide_windows_and_v1n_keeps_mean_one() -> None:
|
||||
table = factor_table()
|
||||
assert set(table["30"].values()) == {1.0}
|
||||
assert set(table["60"].values()) == {1.0}
|
||||
assert table["10"]["D2"] < 1.0
|
||||
assert abs(sum(V1N_FACTORS.values()) / len(V1N_FACTORS) - 1.0) < 1e-4
|
||||
assert V1N_FACTORS["D30"] > V1N_FACTORS["D2"]
|
||||
Reference in New Issue
Block a user