Archive research scripts, regression tests, M1 results and safe M0 smoke. Keep the incomplete study and failing quick gate explicit. Exclude full M0 JSON, raw logs and unrelated oracle newline changes. Co-Authored-By: Claude Code <noreply@anthropic.com>
350 lines
15 KiB
Python
350 lines
15 KiB
Python
#!/usr/bin/env python3
|
|
"""Run the deterministic BUG-1105 varga-resolution M0 replay.
|
|
|
|
The production scorer remains untouched. Scoring candidates are sampled at a
|
|
fixed two-minute step, while an independent one-minute context scan supplies
|
|
varga rising-sign segments. ``refresh_probes=False`` is intentional and is
|
|
recorded in the machine result; an empty probe pool is reported rather than
|
|
silently replaced with refreshed dasha-boundary probes.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
from typing import Any, Iterable, Sequence
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from scripts.research.cluster_width_lib import delivery_from_public # noqa: E402
|
|
from scripts.research.varga_resolution_lib import ( # noqa: E402
|
|
RADII,
|
|
VARGA_PREFIXES,
|
|
native_case,
|
|
segment_rows,
|
|
sign_value,
|
|
)
|
|
|
|
HOLDOUT = ROOT / "references" / "real_case_calibration" / "minute_rectification_holdout_v5.json"
|
|
SCHEMA = "bug-1105-varga-resolution-v1"
|
|
SCORING_STEP = 2
|
|
SCAN_STEP = 1
|
|
REFRESH_PROBES = False
|
|
|
|
|
|
def load_cases() -> list[dict[str, Any]]:
|
|
payload = json.loads(HOLDOUT.read_text(encoding="utf-8"))
|
|
return list(payload.get("cases") or [])
|
|
|
|
|
|
def hhmm(value: object) -> str:
|
|
return str(value or "")[:5]
|
|
|
|
|
|
def clock(stamp: str) -> int:
|
|
hour, minute = stamp[:5].split(":")
|
|
return int(hour) * 60 + int(minute)
|
|
|
|
|
|
def in_envelope(stamp: str, start: str | None, end: str | None) -> bool:
|
|
if not start or not end:
|
|
return False
|
|
value, lower, upper = clock(stamp), clock(start), clock(end)
|
|
return lower <= value <= upper if lower <= upper else value >= lower or value <= upper
|
|
|
|
|
|
def stable_unique(values: Iterable[str]) -> list[str]:
|
|
return list(dict.fromkeys(str(value)[:5] for value in values if value))
|
|
|
|
|
|
def interval_times(chart_rows: Sequence[dict[str, Any]], delivery: dict[str, Any]) -> list[str]:
|
|
return [
|
|
hhmm(row.get("time"))
|
|
for row in chart_rows
|
|
if in_envelope(hhmm(row.get("time")), delivery.get("start"), delivery.get("end"))
|
|
]
|
|
|
|
|
|
def valid_candidate_times(state: dict[str, Any]) -> list[str]:
|
|
values: list[str] = []
|
|
for row in state.get("valid") or []:
|
|
values.extend(hhmm(value) for value in row.get("cluster_times") or [row.get("time")])
|
|
return stable_unique(values)
|
|
|
|
|
|
def represented_segments(
|
|
chart_rows: Sequence[dict[str, Any]],
|
|
prefix: str,
|
|
times: Iterable[str],
|
|
) -> list[dict[str, Any]]:
|
|
wanted = set(stable_unique(times))
|
|
return [
|
|
segment for segment in segment_rows(chart_rows, prefix)
|
|
if wanted.intersection(segment.get("times") or [])
|
|
]
|
|
|
|
|
|
def represented_values(rows: Sequence[dict[str, Any]], prefix: str, times: Iterable[str]) -> list[Any]:
|
|
wanted = set(stable_unique(times))
|
|
return stable_values(sign_value(row, prefix) for row in rows if hhmm(row.get("time")) in wanted)
|
|
|
|
|
|
def stable_values(values: Iterable[Any]) -> list[Any]:
|
|
result: list[Any] = []
|
|
for value in values:
|
|
if value is None or value in result:
|
|
continue
|
|
result.append(value)
|
|
return result
|
|
|
|
|
|
def majority(values: Sequence[Any], truth: Any) -> tuple[bool | None, bool]:
|
|
if not values:
|
|
return None, False
|
|
counts = Counter(values)
|
|
peak = max(counts.values())
|
|
leaders = {value for value, count in counts.items() if count == peak}
|
|
return (truth in leaders if len(leaders) == 1 else None), len(leaders) > 1
|
|
|
|
|
|
def window_summary(chart_rows: Sequence[dict[str, Any]]) -> dict[str, Any]:
|
|
counts: dict[str, int] = {}
|
|
segments: dict[str, int] = {}
|
|
for prefix in VARGA_PREFIXES:
|
|
counts[prefix] = len(stable_values(sign_value(row, prefix) for row in chart_rows))
|
|
segments[prefix] = len(segment_rows(chart_rows, prefix))
|
|
combinations = len({tuple(sign_value(row, prefix) for prefix in VARGA_PREFIXES) for row in chart_rows})
|
|
return {
|
|
"scan_point_count": len(chart_rows),
|
|
"sign_counts": counts,
|
|
"segment_counts": segments,
|
|
"combination_count": combinations,
|
|
"d1_single_sign": counts["D1"] == 1,
|
|
}
|
|
|
|
|
|
def interval_summary(
|
|
chart_rows: Sequence[dict[str, Any]],
|
|
state: dict[str, Any],
|
|
true_time: str,
|
|
) -> dict[str, Any]:
|
|
delivery = state.get("delivery") or {}
|
|
envelope = interval_times(chart_rows, delivery)
|
|
real = valid_candidate_times(state)
|
|
values: dict[str, dict[str, Any]] = {}
|
|
for prefix in VARGA_PREFIXES:
|
|
truth_row = next((row for row in chart_rows if hhmm(row.get("time")) == true_time), None)
|
|
truth = sign_value(truth_row or {}, prefix)
|
|
envelope_segments = represented_segments(chart_rows, prefix, envelope)
|
|
real_segments = represented_segments(chart_rows, prefix, real)
|
|
envelope_values = [sign_value(row, prefix) for row in chart_rows if hhmm(row.get("time")) in set(envelope)]
|
|
exact_values = represented_values(chart_rows, prefix, real)
|
|
envelope_majority, envelope_tie = majority(envelope_values, truth)
|
|
exact_majority, exact_tie = majority(exact_values, truth)
|
|
truth_segment = next(
|
|
(segment for segment in segment_rows(chart_rows, prefix) if true_time in (segment.get("times") or [])),
|
|
None,
|
|
)
|
|
truth_segment_id = truth_segment.get("segment_id") if truth_segment else None
|
|
values[prefix] = {
|
|
"truth_sign": truth,
|
|
"truth_segment_id": truth_segment_id,
|
|
"envelope_start": delivery.get("start"),
|
|
"envelope_end": delivery.get("end"),
|
|
"envelope_scan_point_count": len(envelope),
|
|
"envelope_sign_count": len(stable_values(envelope_values)),
|
|
"envelope_segment_count": len(envelope_segments),
|
|
"envelope_majority_truth": envelope_majority,
|
|
"envelope_majority_tie": envelope_tie,
|
|
"real_valid_candidate_count": len(real),
|
|
"real_valid_sign_count": len(exact_values),
|
|
"real_valid_segment_count": len(real_segments),
|
|
"real_valid_majority_truth": exact_majority,
|
|
"real_valid_majority_tie": exact_tie,
|
|
"truth_segment_retained_in_real_set": truth_segment_id is not None and any(
|
|
segment.get("segment_id") == truth_segment_id for segment in real_segments
|
|
),
|
|
}
|
|
combo_envelope = {
|
|
tuple(sign_value(row, prefix) for prefix in VARGA_PREFIXES)
|
|
for row in chart_rows
|
|
if hhmm(row.get("time")) in set(envelope)
|
|
}
|
|
combo_real = {
|
|
tuple(sign_value(row, prefix) for prefix in VARGA_PREFIXES)
|
|
for row in chart_rows
|
|
if hhmm(row.get("time")) in set(real)
|
|
}
|
|
truth_row = next((row for row in chart_rows if hhmm(row.get("time")) == true_time), None)
|
|
truth_combo = tuple(sign_value(truth_row or {}, prefix) for prefix in VARGA_PREFIXES)
|
|
envelope_combo_majority, envelope_combo_tie = majority(
|
|
[tuple(sign_value(row, prefix) for prefix in VARGA_PREFIXES) for row in chart_rows if hhmm(row.get("time")) in set(envelope)],
|
|
truth_combo,
|
|
)
|
|
return {
|
|
"scoring_candidate_times": real,
|
|
"interval_envelope": {
|
|
"start": delivery.get("start"),
|
|
"end": delivery.get("end"),
|
|
"scan_point_count": len(envelope),
|
|
"times": envelope,
|
|
},
|
|
"by_varga": values,
|
|
"combination": {
|
|
"envelope_count": len(combo_envelope),
|
|
"real_valid_count": len(combo_real),
|
|
"envelope_majority_truth": envelope_combo_majority,
|
|
"envelope_majority_tie": envelope_combo_tie,
|
|
},
|
|
}
|
|
|
|
|
|
def case_result(case: dict[str, Any], radius: int) -> dict[str, Any]:
|
|
result = native_case(case, radius, do_reconcile=True)
|
|
state = result["state"]
|
|
chart_rows = result["chart_rows"]
|
|
return {
|
|
"case_id": str(case.get("case_id") or ""),
|
|
"radius": radius,
|
|
"true_time": result["true_time"],
|
|
"scoring_candidate_count": len(result["rows"]),
|
|
"scan_point_count": len(chart_rows),
|
|
"probe_count": len(result["probes"]),
|
|
"answered_count": int((state.get("result") or {}).get("questions") or 0),
|
|
"reconciliation": result["reconciliation"],
|
|
"window": window_summary(chart_rows),
|
|
"six_question_delivery": interval_summary(chart_rows, state, result["true_time"]),
|
|
}
|
|
|
|
|
|
def ratio(numerator: int, denominator: int) -> float | None:
|
|
return round(numerator / denominator, 8) if denominator else None
|
|
|
|
|
|
def aggregate(results: Sequence[dict[str, Any]], radius: int) -> dict[str, Any]:
|
|
rows = [row for row in results if row["radius"] == radius]
|
|
n = len(rows)
|
|
window = {
|
|
"case_count": n,
|
|
"d1_single_sign": sum(row["window"]["d1_single_sign"] for row in rows),
|
|
"mean_sign_counts": {
|
|
prefix: round(sum(row["window"]["sign_counts"][prefix] for row in rows) / n, 8) if n else None
|
|
for prefix in VARGA_PREFIXES
|
|
},
|
|
"mean_segment_counts": {
|
|
prefix: round(sum(row["window"]["segment_counts"][prefix] for row in rows) / n, 8) if n else None
|
|
for prefix in VARGA_PREFIXES
|
|
},
|
|
"mean_combination_count": round(sum(row["window"]["combination_count"] for row in rows) / n, 8) if n else None,
|
|
}
|
|
by_varga: dict[str, Any] = {}
|
|
for prefix in VARGA_PREFIXES:
|
|
items = [row["six_question_delivery"]["by_varga"][prefix] for row in rows]
|
|
by_varga[prefix] = {
|
|
"envelope_only_one_sign": sum(item["envelope_sign_count"] == 1 for item in items),
|
|
"envelope_at_most_two_signs": sum(item["envelope_sign_count"] <= 2 for item in items),
|
|
"envelope_majority_truth": sum(item["envelope_majority_truth"] is True for item in items),
|
|
"envelope_majority_ties": sum(item["envelope_majority_tie"] for item in items),
|
|
"real_truth_segment_retained": sum(item["truth_segment_retained_in_real_set"] for item in items),
|
|
"real_at_most_two_segments": sum(item["real_valid_segment_count"] <= 2 for item in items),
|
|
"denominator": n,
|
|
}
|
|
for key in (
|
|
"envelope_only_one_sign",
|
|
"envelope_at_most_two_signs",
|
|
"envelope_majority_truth",
|
|
"real_truth_segment_retained",
|
|
"real_at_most_two_segments",
|
|
):
|
|
by_varga[prefix][f"{key}_rate"] = ratio(by_varga[prefix][key], n)
|
|
combo = [row["six_question_delivery"]["combination"] for row in rows]
|
|
return {
|
|
"radius": radius,
|
|
"case_count": n,
|
|
"reconciliation": {
|
|
"all_zero_diff": all(not row["reconciliation"].get("changed") for row in rows),
|
|
"case_count": n,
|
|
"changed_case_count": sum(bool(row["reconciliation"].get("changed")) for row in rows),
|
|
"denominator": n,
|
|
},
|
|
"window": window,
|
|
"delivery_envelope": {
|
|
"by_varga": by_varga,
|
|
"combination_only_one": sum(item["envelope_count"] == 1 for item in combo),
|
|
"combination_at_most_two": sum(item["envelope_count"] <= 2 for item in combo),
|
|
"combination_majority_truth": sum(item["envelope_majority_truth"] is True for item in combo),
|
|
"combination_majority_ties": sum(item["envelope_majority_tie"] for item in combo),
|
|
"denominator": n,
|
|
},
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--radii", default=",".join(str(value) for value in RADII))
|
|
parser.add_argument("--vargas", default=",".join(VARGA_PREFIXES))
|
|
parser.add_argument("--limit", type=int, default=0)
|
|
parser.add_argument("--json-out", required=True)
|
|
args = parser.parse_args()
|
|
radii = tuple(int(value) for value in str(args.radii).split(",") if value.strip())
|
|
vargas = tuple(value.strip() for value in str(args.vargas).split(",") if value.strip())
|
|
cases = load_cases()
|
|
if args.limit:
|
|
cases = cases[: args.limit]
|
|
results: list[dict[str, Any]] = []
|
|
errors: list[dict[str, str | int]] = []
|
|
for case in cases:
|
|
for radius in radii:
|
|
label = f"{case.get('case_id')} ±{radius}"
|
|
try:
|
|
row = case_result(case, radius)
|
|
results.append(row)
|
|
print(
|
|
f"{label} score={row['scoring_candidate_count']} scan={row['scan_point_count']} "
|
|
f"probes={row['probe_count']} reconcile_changed={bool(row['reconciliation'].get('changed'))}",
|
|
flush=True,
|
|
)
|
|
except Exception as exc: # noqa: BLE001
|
|
errors.append({"case_id": str(case.get("case_id") or ""), "radius": radius, "error": f"{type(exc).__name__}: {exc}"})
|
|
print(f"{label} ERROR {type(exc).__name__}: {exc}", flush=True)
|
|
payload = {
|
|
"schema": SCHEMA,
|
|
"metadata": {
|
|
"holdout": str(HOLDOUT.relative_to(ROOT)).replace("\\", "/"),
|
|
"case_count_requested": len(cases),
|
|
"case_count_completed": len({row["case_id"] for row in results}),
|
|
"radii": list(radii),
|
|
"vargas": list(vargas),
|
|
"ayanamsa": "raman",
|
|
"node_mode": "mean",
|
|
"scoring_candidate_step_minutes": SCORING_STEP,
|
|
"segment_scan_step_minutes": SCAN_STEP,
|
|
"refresh_probes": REFRESH_PROBES,
|
|
"replay_probe_source": "existing event_probes.discriminating_event_probes; no refresh",
|
|
"questions_requested": 6,
|
|
"questions_answered_is_recorded_per_case": True,
|
|
"real_valid_candidate_set": "union of cluster_times from still_valid_public after replay; scoring-grid candidates only",
|
|
"interval_envelope": "unionStillValidRange equivalent: min/max clock edges over the real valid candidate clusters; envelope is not the real set",
|
|
"segment_definition": "maximal contiguous one-minute scan run of equal D1/D9/D10 sign; repeated non-contiguous signs retain separate IDs; 23:59->00:00 is contiguous",
|
|
"aggregation_denominator": "77 cases per radius when full run completes; empty coverage and ties are separate counts",
|
|
"reconciliation_scope": "every case and radius, scoring grid only; single-case zero-diff is smoke evidence, not full-set evidence",
|
|
"deterministic_json": True,
|
|
},
|
|
"aggregates": [aggregate(results, radius) for radius in radii],
|
|
"results": results,
|
|
"errors": errors,
|
|
}
|
|
out = Path(args.json_out)
|
|
out.parent.mkdir(parents=True, exist_ok=True)
|
|
out.write_text(json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
print(json.dumps(payload["aggregates"], ensure_ascii=False, indent=2, sort_keys=True), flush=True)
|
|
return 0 if not errors and all(item["reconciliation"]["all_zero_diff"] for item in payload["aggregates"]) else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|