"""Cross-cutting acceptance sweep (issue #32). Systematic verification of every acceptance criterion that spans multiple subsystems. Grouped by criterion ID; each test cites its clause. CI-1 Exhaustive state matrix: confidence × freshness × baseline tier CI-2 TUI/CLI parity: identical outcomes and wording CI-3 Prohibition set: automated structural checks CI-4 Required wording and six disclosures in both views """ import re import sqlite3 from datetime import datetime, timedelta, timezone from pathlib import Path from unittest.mock import patch import pytest import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from fenris.store import init_store, SCHEMA_VERSION from fenris.monitoring_periods import ensure_period_open from fenris.projection import ( compute_projection, ConfidenceState, BaselineTier, DISCLOSURES, STALENESS_HOURS, WARMING_MIN_DAYS, YOUNG_REGIME_DAYS, ) from fenris.status import ( grade_freshness, get_status, render_status, format_disclosures, FRESH_THRESHOLD_S, STALENESS_THRESHOLD_S, CADENCE_DEFAULT_S, ACCURACY_SEC, ) from fenris.tui import ( FenrisTuiApp, _format_remaining, ) SRC_DIR = Path(__file__).parent.parent / "src" FENRIS_PKG = SRC_DIR / "fenris" def _clock(year=2026, month=9, day=30, hour=12): return datetime(year, month, day, hour, 0, 0, tzinfo=timezone.utc) def _insert_baseline(conn, tbw_tb=1.0, verified=True, model="Samsung SSD 970 EVO Plus 1TB", source_url="https://example.com/spec", doc_rev="v1.0", entry_date="2026-01-01", nominal_cap=1024000000000): conn.execute( "INSERT INTO endurance_baseline " "(tbw_terabytes, source_url, document_revision, entry_date, model_string, " " nominal_capacity_bytes, validated_by, verified, created_at, updated_at) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (tbw_tb, source_url, doc_rev, entry_date, model, nominal_cap, "machine_match" if verified else None, verified, "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00"), ) conn.commit() def _insert_segment(conn, opened_at="2026-09-01T00:00:00+00:00", identity_key="nqn.test", degraded=False, mn="Samsung SSD 970 EVO Plus 1TB"): conn.execute( "INSERT INTO controller_segments " "(opened_at, identity_key, identity_degraded, subnqn, sn, mn, fr, vid, ssvid, transport) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (opened_at, identity_key, degraded, "nqn.test", "SN123", mn, "FW1", "0x144d", "0x144d", "pcie"), ) conn.commit() def _insert_day(conn, day, bw=1024*1024*100, coverage=0.95, samples=24): conn.execute( "INSERT INTO day_aggregates (day, active_seconds, idle_seconds, " "powered_off_seconds, unknown_seconds, bytes_written_delta, " "bytes_read_delta, sample_count, coverage) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", (day, 3600, 0, 0, 0, bw, 0, samples, coverage), ) conn.commit() def _insert_sample(conn, ts, pu=5): conn.execute( "INSERT INTO samples (ts, device, data_units_written, data_units_read, " "percentage_used, bytes_written, bytes_read, power_on_hours) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (ts, "/dev/nvme0n1", 1000000, 500000, pu, 512000000000, 256000000000, 8765), ) conn.commit() def _open_period(conn, start="2026-09-01T00:00:00+00:00"): ensure_period_open(conn, datetime.fromisoformat(start)) def _insert_local_day(conn, local_date, tz_name="UTC", tz_offset="+00:00", utc_start=None, utc_end=None, bw=1024*1024*100, br=0, coverage=0.95, samples=24, complete=True): """Insert a local_days row (issue #94 gate prerequisite).""" if utc_start is None: utc_start = local_date + "T00:00:00+00:00" if utc_end is None: dt = datetime.strptime(local_date, "%Y-%m-%d") + timedelta(days=1) utc_end = dt.strftime("%Y-%m-%dT00:00:00+00:00") conn.execute( "INSERT INTO local_days " "(local_date, tz_name, tz_offset, utc_start, utc_end, " " bytes_written, bytes_read, coverage, sample_count, complete, activity_intervals) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)", (local_date, tz_name, tz_offset, utc_start, utc_end, bw, br, coverage, samples, complete), ) conn.commit() def _insert_complete_local_days(conn, start_date, count, bw=1024*1024*100): """Insert multiple complete local days to satisfy the issue #94 gate.""" for i in range(count): d = (datetime.strptime(start_date, "%Y-%m-%d") + timedelta(days=i)).strftime("%Y-%m-%d") _insert_local_day(conn, d, bw=bw) def _setup_full_store(conn, *, baseline=True, segment=True, days=30, bw=1024*1024*100, coverage=0.95, samples_per_day=24, sample_ts="2026-09-30T10:00:00+00:00", period_start="2026-09-01T00:00:00+00:00", segment_opened="2026-09-01T00:00:00+00:00", baseline_kw=None, segment_kw=None, local_days=True): if baseline: _insert_baseline(conn, **(baseline_kw or {})) if segment: _insert_segment(conn, opened_at=segment_opened, **(segment_kw or {})) _open_period(conn, start=period_start) for i in range(days): d = (datetime(2026, 9, 1) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=bw, coverage=coverage, samples=samples_per_day) if sample_ts: _insert_sample(conn, sample_ts) # Issue #94: satisfy the complete-observation-day gate if local_days and days > 0: _insert_complete_local_days(conn, "2026-09-29", 1, bw=bw) # =================================================================== # CI-1: Exhaustive state matrix # =================================================================== class TestCI1StateMatrix: """Systematic walk of confidence x freshness x baseline tier combinations.""" def test_no_baseline_unavailable(self, tmp_path): conn = init_store(tmp_path / "db") _insert_segment(conn) _open_period(conn) for i in range(30): d = (datetime(2026, 9, 1) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100, coverage=0.95, samples=24) _insert_sample(conn, "2026-09-30T10:00:00+00:00") proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.UNSUPPORTED assert proj.headline_remaining_seconds is None assert proj.baseline_tier == BaselineTier.NONE conn.close() def test_verified_baseline_possible_supported(self, tmp_path): conn = init_store(tmp_path / "db") _setup_full_store(conn, baseline_kw=dict(tbw_tb=10.0, verified=True)) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.SUPPORTED assert proj.baseline_tier == BaselineTier.VERIFIED assert proj.headline_remaining_seconds is not None conn.close() def test_unverified_baseline_possible_limited(self, tmp_path): conn = init_store(tmp_path / "db") _setup_full_store(conn, baseline_kw=dict( tbw_tb=10.0, verified=False, source_url=None)) proj = compute_projection(conn, _clock()) assert proj.baseline_tier == BaselineTier.UNVERIFIED assert proj.confidence_state != ConfidenceState.SUPPORTED conn.close() def test_model_mismatch_unavailable(self, tmp_path): conn = init_store(tmp_path / "db") _setup_full_store(conn, baseline_kw=dict(model="Different Model")) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.UNSUPPORTED assert proj.baseline_tier == BaselineTier.NONE conn.close() def test_fresh_sample_grades_fresh(self, tmp_path): now = _clock() ts = (now - timedelta(seconds=FRESH_THRESHOLD_S - 10)).isoformat() assert grade_freshness(ts, now) == "fresh" def test_missed_sample_grades_missed(self, tmp_path): now = _clock() ts = (now - timedelta(hours=2)).isoformat() assert grade_freshness(ts, now) == "missed" def test_stale_sample_grades_stale(self, tmp_path): now = _clock() ts = (now - timedelta(hours=49)).isoformat() assert grade_freshness(ts, now) == "stale" def test_empty_store_grades_empty(self, tmp_path): now = _clock() assert grade_freshness(None, now) == "empty" def test_unsupported_fresh(self, tmp_path): conn = init_store(tmp_path / "db") _insert_segment(conn) _open_period(conn) for i in range(20): d = (datetime(2026, 9, 10) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100) fresh_ts = (_clock() - timedelta(seconds=60)).isoformat() _insert_sample(conn, fresh_ts) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.UNSUPPORTED assert grade_freshness(fresh_ts, _clock()) == "fresh" conn.close() def test_limited_young_regime(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=10.0, verified=True) _insert_segment(conn) _open_period(conn) for i in range(5): d = (datetime(2026, 9, 25) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100) _insert_sample(conn, "2026-09-30T10:00:00+00:00") _insert_complete_local_days(conn, "2026-09-29", 1) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.LIMITED conn.close() def test_limited_warming(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=10.0, verified=True) _insert_segment(conn) _open_period(conn) for i in range(10): d = (datetime(2026, 9, 20) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100, coverage=0.95, samples=24) _insert_sample(conn, "2026-09-30T10:00:00+00:00") _insert_complete_local_days(conn, "2026-09-29", 1) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.LIMITED assert proj.warming_fact is not None conn.close() def test_limited_stale_data(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=10.0, verified=True) _insert_segment(conn, opened_at="2026-08-01T00:00:00+00:00") _open_period(conn, start="2026-08-01T00:00:00+00:00") for i in range(30): d = (datetime(2026, 8, 1) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100, coverage=0.95, samples=24) stale_ts = (_clock() - timedelta(days=5)).isoformat() _insert_sample(conn, stale_ts) _insert_complete_local_days(conn, "2026-08-30", 1) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.LIMITED assert proj.staleness_fact is not None conn.close() def test_limited_degraded_identity(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=10.0, verified=True) _insert_segment(conn, identity_key=None, degraded=True) _open_period(conn) for i in range(30): d = (datetime(2026, 9, 1) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100, coverage=0.95, samples=24) _insert_sample(conn, "2026-09-30T10:00:00+00:00") _insert_complete_local_days(conn, "2026-09-29", 1) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.LIMITED assert proj.degraded_identity_fact is not None conn.close() def test_unsupported_zero_rate(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=10.0, verified=True) _insert_segment(conn) _open_period(conn) for i in range(30): d = (datetime(2026, 9, 1) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=0) _insert_sample(conn, "2026-09-30T10:00:00+00:00") _insert_complete_local_days(conn, "2026-09-29", 1) proj = compute_projection(conn, _clock()) assert proj.confidence_state == ConfidenceState.UNSUPPORTED assert proj.zero_rate_fact is not None conn.close() def test_headline_present_when_projection_exists(self, tmp_path): conn = init_store(tmp_path / "db") _setup_full_store(conn, baseline_kw=dict(tbw_tb=10.0, verified=True)) proj = compute_projection(conn, _clock()) assert proj.headline_remaining_seconds is not None assert proj.headline_remaining_seconds > 0 conn.close() def test_headline_absent_when_unavailable(self, tmp_path): conn = init_store(tmp_path / "db") _insert_segment(conn) _open_period(conn) proj = compute_projection(conn, _clock()) assert proj.headline_remaining_seconds is None conn.close() def test_headline_absent_when_zero_rate(self, tmp_path): conn = init_store(tmp_path / "db") _insert_baseline(conn, tbw_tb=1.0, verified=True) _insert_segment(conn) _open_period(conn) for i in range(20): d = (datetime(2026, 9, 10) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=0) proj = compute_projection(conn, _clock()) assert proj.headline_remaining_seconds is None conn.close() def test_facts_always_list(self, tmp_path): conn = init_store(tmp_path / "db") _insert_segment(conn) _open_period(conn) proj = compute_projection(conn, _clock()) assert isinstance(proj.contributing_facts, list) conn.close() def test_facts_never_empty_for_unavailable(self, tmp_path): conn = init_store(tmp_path / "db") _insert_segment(conn) _open_period(conn) proj = compute_projection(conn, _clock()) assert len(proj.contributing_facts) > 0 conn.close() def test_confidence_never_percentage(self, tmp_path): conn = init_store(tmp_path / "db") _setup_full_store(conn, baseline_kw=dict(tbw_tb=10.0, verified=True)) proj = compute_projection(conn, _clock()) assert proj.confidence_state in ( ConfidenceState.UNSUPPORTED, ConfidenceState.LIMITED, ConfidenceState.SUPPORTED) for f in proj.contributing_facts: if re.match(r"^\\d+%$", f.strip()): pytest.fail("Bare percentage in facts: %r" % f) conn.close() def test_status_renders_same_state_as_projection(self, tmp_path): db = tmp_path / "observations.db" conn = init_store(db) _setup_full_store(conn, baseline_kw=dict(tbw_tb=10.0, verified=True)) conn.close() now = _clock() with patch("fenris.status.query_service_state", return_value={ "boot_enabled": True, "timer_active": True, "last_collect_ok": True, "last_collect_age_s": 60, "last_collect_reason": None, }): status = get_status(store_path=db, clock_now=now, query_services=True, query_journal=False) assert "Supported" in status or "supported" in status.lower() assert "remaining" in status.lower() # =================================================================== # CI-2: TUI/CLI parity # =================================================================== class TestCI2Parity: """Verify TUI and CLI share the same constants, formatting, and wording.""" def test_freshness_constants_shared(self): from fenris import tui as tui_mod from fenris import status as status_mod assert tui_mod.FRESH_THRESHOLD_S == status_mod.FRESH_THRESHOLD_S assert tui_mod.STALENESS_THRESHOLD_S == status_mod.STALENESS_THRESHOLD_S def test_grade_freshness_shared(self): from fenris.tui import grade_freshness as tui_gf from fenris.status import grade_freshness as status_gf assert tui_gf is status_gf def test_disclosures_shared(self): from fenris.projection import DISCLOSURES as proj_disc from fenris.status import format_disclosures output = format_disclosures() for d in proj_disc: assert d in output def test_status_four_facts_match_tui_strip(self, tmp_path): db = tmp_path / "observations.db" conn = init_store(db) _insert_segment(conn) _open_period(conn) for i in range(20): d = (datetime(2026, 9, 10) + timedelta(days=i)).strftime("%Y-%m-%d") _insert_day(conn, d, bw=1024*1024*100) _insert_sample(conn, "2026-09-30T10:00:00+00:00") conn.close() now = _clock() with patch("fenris.status.query_service_state", return_value={ "boot_enabled": True, "timer_active": True, "last_collect_ok": True, "last_collect_age_s": 120, "last_collect_reason": None, }): status = get_status(store_path=db, clock_now=now, query_services=True, query_journal=False) assert "boot:" in status assert "timer:" in status assert "last collect:" in status assert "freshness:" in status def test_dashboard_clarity_parity_strings_have_one_status_source(self): """DC-2/DC-3 wording originates in status and the TUI imports it.""" status_src = (FENRIS_PKG / "status.py").read_text() tui_src = (FENRIS_PKG / "tui.py").read_text() for wording in ( "monitoring: active in background · persists across reboots", "monitoring: does not start on next boot", "monitoring: paused — deliberate disable", "paused time is excluded from your usage habit · resume: fenris monitor resume", ): assert status_src.count(wording) == 1 assert wording not in tui_src @pytest.mark.asyncio @pytest.mark.parametrize( ("state", "service", "expected_lines"), [ ( "active_enabled", {"boot_enabled": True, "timer_active": True}, ["monitoring: active in background · persists across reboots"], ), ( "boot_disabled", {"boot_enabled": False, "timer_active": False}, ["monitoring: does not start on next boot"], ), ( "deliberately_paused", {"boot_enabled": False, "timer_active": False}, [ "monitoring: does not start on next boot", "monitoring: paused — deliberate disable", "paused time is excluded from your usage habit · resume: fenris monitor resume", ], ), ], ) async def test_dashboard_clarity_monitoring_lines_match_both_views( self, tmp_path, state, service, expected_lines ): """CI-2 synthetic-store sweep covers active, disabled, and paused states.""" db = tmp_path / (state + ".db") conn = init_store(db) if state == "active_enabled": ensure_period_open(conn, _clock()) elif state == "deliberately_paused": conn.execute( "INSERT INTO monitoring_periods (started_at, ended_at, end_cause) " "VALUES (?, ?, ?)", ("2026-09-30T09:00:00+00:00", "2026-09-30T10:00:00+00:00", "user_disabled"), ) conn.commit() conn.close() service_state = { **service, "last_collect_ok": None, "last_collect_age_s": None, "last_collect_reason": None, } with patch("fenris.status.query_service_state", return_value=service_state), patch( "fenris.status.query_service_state", return_value=service_state ): status = get_status( store_path=db, clock_now=_clock(), query_services=True, query_journal=False ).lower() app = FenrisTuiApp(store_path=db) async with app.run_test(size=(100, 40)): tui_text = "\n".join( ( str(app.query_one("#service-strip").render()), str(app.query_one("#paused-banner").render()), ) ).lower() for expected in expected_lines: assert expected in status assert expected in tui_text if state != "deliberately_paused": assert "monitoring: paused — deliberate disable" not in status assert "monitoring: paused — deliberate disable" not in tui_text def test_pause_resume_action_names(self): tui_keys = {b.key for b in FenrisTuiApp.BINDINGS} assert "p" in tui_keys assert "r" in tui_keys assert "c" in tui_keys assert "q" in tui_keys def test_empty_store_greeting_both_views(self, tmp_path): db = tmp_path / "observations.db" init_store(db) now = _clock() with patch("fenris.status.query_service_state", return_value={ "boot_enabled": False, "timer_active": False, "last_collect_ok": None, "last_collect_age_s": None, "last_collect_reason": None, }): status = get_status(store_path=db, clock_now=now, query_services=True, query_journal=False) assert "no observations yet" in status.lower() def test_status_never_prompts(self): status_src = (FENRIS_PKG / "status.py").read_text() assert "input(" not in status_src # =================================================================== # CI-3: Prohibition set # =================================================================== class TestCI3ProhibitionSet: """Structural codebase checks for every prohibition clause.""" def _read_all_sources(self): files = {} for py in FENRIS_PKG.glob("*.py"): files[py.name] = py.read_text() return files def test_single_acquisition_path(self): """Only fenris-collect may interrogate the device. [2.1, 8.7] collector.py contains the acquisition functions; collect.py is the fenris-collect entry point that invokes them. No other module may reference smartctl. """ sources = self._read_all_sources() allowed = {"collector.py", "collect.py"} for name, text in sources.items(): if name in allowed: continue assert "smartctl" not in text, ( "%s must not contain smartctl" % name ) def test_no_run_surface(self): """No /run/fenris coordination surface. [1.2, 3]""" sources = self._read_all_sources() for name, text in sources.items(): assert "/run/fenris" not in text, ( "%s references /run/fenris" % name ) def test_single_config_key(self): """Config holds exactly one key: device. [8.3]""" status_src = (FENRIS_PKG / "status.py").read_text() in_read_config = False config_keys = [] for line in status_src.split("\n"): if "def read_config" in line: in_read_config = True elif in_read_config and line.strip().startswith("def "): break elif in_read_config and "key ==" in line: match = re.search(r'key\s*==\s*["\']([^"\']+)["\']', line) if match: config_keys.append(match.group(1)) assert "device" in config_keys assert len(config_keys) == 1, "Found keys: %s" % config_keys def test_no_alerting_machinery(self): """No alerting, notification, or escalation. [9.6]""" sources = self._read_all_sources() alert_keywords = ["send_email", "smtp", "webhook", "push_notification"] for name, text in sources.items(): for kw in alert_keywords: for line in text.split("\n"): stripped = line.strip() if kw in stripped and not stripped.startswith("#"): pytest.fail( "%s contains alerting keyword '%s': %s" % (name, kw, stripped) ) def test_no_synthetic_baselines(self): """No synthetic or capacity-derived baseline. [6.1]""" proj_src = (FENRIS_PKG / "projection.py").read_text() assert "synthetic" not in proj_src.lower() def test_no_stored_projections(self): """Projections never stored; recomputed on read. [3.7, 6.10]""" store_src = (FENRIS_PKG / "store.py").read_text() create_tables = re.findall(r"CREATE TABLE.*?(?=\n\n|$)", store_src, re.DOTALL) table_names = [] for ct in create_tables: m = re.search(r"IF NOT EXISTS\s+(\w+)", ct) if m: table_names.append(m.group(1)) assert "projection" not in [t.lower() for t in table_names] def test_polkit_authorizes_one_binary(self): """Polkit authorizes exactly one binary: fenris-monitor. [8.5]""" monitor_src = (FENRIS_PKG / "monitor.py").read_text() assert "fenris-monitor" in monitor_src or "fenris_monitor" in monitor_src collect_src = (FENRIS_PKG / "collect.py").read_text() assert "polkit" not in collect_src.lower() def test_no_hour_interpolation(self): """No absent hour is interpolated or fabricated. [5.3]""" proj_src = (FENRIS_PKG / "projection.py").read_text() assert "interpolat" not in proj_src.lower() assert "fabricat" not in proj_src.lower() def test_fenris_sh_not_shipped(self): """fenris.sh is not shipped. [8.8]""" repo_root = Path(__file__).parent.parent assert not (repo_root / "fenris.sh").exists() # =================================================================== # CI-4: Required wording and six disclosures # =================================================================== class TestCI4WordingAndDisclosures: """Verify exact fixed phrases and disclosures in both views.""" def test_exactly_six_disclosures(self): assert len(DISCLOSURES) == 6 def test_disclosure_1_endurance_not_failure(self): assert "endurance projection" in DISCLOSURES[0].lower() assert "hardware-failure" in DISCLOSURES[0].lower() or "failure date" in DISCLOSURES[0].lower() def test_disclosure_2_vendor_specific(self): assert "vendor-specific" in DISCLOSURES[1] assert "255 is saturated" in DISCLOSURES[1] def test_disclosure_3_warranty_not_failure(self): assert "warranty" in DISCLOSURES[2].lower() or "endurance threshold" in DISCLOSURES[2].lower() assert "failure threshold" in DISCLOSURES[2].lower() def test_disclosure_4_duw_rounding(self): assert "DUW" in DISCLOSURES[3] assert "upward-rounded" in DISCLOSURES[3] assert "NAND" in DISCLOSURES[3] def test_disclosure_5_quality_depends(self): assert "baseline provenance" in DISCLOSURES[4] assert "future workload" in DISCLOSURES[4] def test_disclosure_6_gaps_and_disabled(self): assert "Gaps" in DISCLOSURES[5] assert "deliberately disabled" in DISCLOSURES[5] def test_disclosures_render_in_status(self): output = format_disclosures() assert output.startswith("Disclosures") for i in range(1, 7): assert "%d." % i in output for d in DISCLOSURES: assert d in output def test_disclosures_render_in_tui(self): tui_src = (FENRIS_PKG / "tui.py").read_text() assert "format_disclosures" in tui_src def test_zero_rate_phrase(self): phrase = "no finite projection from this history" proj_src = (FENRIS_PKG / "projection.py").read_text() assert phrase in proj_src status_src = (FENRIS_PKG / "status.py").read_text() assert phrase in status_src def test_unavailable_no_baseline_phrase(self): phrase = "no applicable endurance baseline" proj_src = (FENRIS_PKG / "projection.py").read_text() assert phrase in proj_src def test_no_observations_phrase(self): phrase = "no observations yet" status_src = (FENRIS_PKG / "status.py").read_text() assert phrase in status_src tui_src = (FENRIS_PKG / "tui.py").read_text() assert phrase in tui_src.lower() def test_config_error_phrase(self): phrase = "configuration error:" status_src = (FENRIS_PKG / "status.py").read_text() assert phrase in status_src def test_degraded_identity_phrase(self): phrase = "controller identity unavailable" proj_src = (FENRIS_PKG / "projection.py").read_text() assert phrase in proj_src phrase2 = "replacement detection relies on write-counter continuity only" assert phrase2 in proj_src def test_scenario_range_only_spread(self): proj_src = (FENRIS_PKG / "projection.py").read_text() assert "confidence interval" not in proj_src.lower() def test_no_percentage_in_confidence_rendering(self): for name in ["projection.py", "tui.py", "status.py"]: src = (FENRIS_PKG / name).read_text() assert not re.search(r"\\d+%\\s*confidence", src, re.IGNORECASE), ( "Found XX%% confidence in %s" % name ) def test_status_disclosures_accessible(self): db = Path("/tmp/_ci4_test.db") conn = init_store(db) conn.close() now = _clock() with patch("fenris.status.query_service_state", return_value={ "boot_enabled": False, "timer_active": False, "last_collect_ok": None, "last_collect_age_s": None, "last_collect_reason": None, }): result = render_status(store_path=db, clock_now=now, query_services=True, query_journal=False, show_disclosures=True) assert "Disclosures" in result assert "1." in result assert "6." in result db.unlink(missing_ok=True)