feat: Fenris persistent TUI monitoring redesign
Implement the complete redesign per fenris-redesign spec: - Observation store: SQLite WAL mode, six entities, schema versioning - Collector: smartctl acquisition, sysfs identity, normalization - Projection: sustained regime rate, habit change, confidence states - Panes TUI: Textual keyboard-first layout with four normative regions - Status CLI: read-only composition with four service facts - Monitor helper: polkit-guarded toggle, collect, baseline ops - Legacy migration: idempotent single-transaction import - Hour classification, day aggregates, monitoring periods - Pruning, segmentation, drive health facts Cross-cutting acceptance sweep (CI-1 through CI-4): - 59 tests covering state matrix, TUI/CLI parity, prohibition set, required wording and six disclosures - Full suite: 289 tests, all green Issues #20, #32 closed.
This commit is contained in:
+44
-3
@@ -176,12 +176,53 @@ def _create_schema(conn: sqlite3.Connection):
|
||||
|
||||
|
||||
def _apply_migrations(conn: sqlite3.Connection, current_version: int):
|
||||
"""Apply forward-only migrations from current_version to SCHEMA_VERSION."""
|
||||
# Future migrations will go here
|
||||
# For now, just upgrade to current version
|
||||
"""Apply forward-only migrations from current_version to SCHEMA_VERSION.
|
||||
|
||||
Each migration step is a transactional block. Add new steps as sequential
|
||||
elif branches when SCHEMA_VERSION increases.
|
||||
|
||||
Spec: §3.6, §10.2
|
||||
"""
|
||||
# Migration 1→2: example placeholder
|
||||
# if current_version < 2:
|
||||
# conn.execute("ALTER TABLE ...")
|
||||
# current_version = 2
|
||||
pass
|
||||
|
||||
|
||||
def migrate_to_latest(store_path: Path) -> int:
|
||||
"""Apply forward-only migrations to bring the store to SCHEMA_VERSION.
|
||||
|
||||
Called by the upgrade target (§10.2). Returns the number of migration
|
||||
steps applied. Raises ValueError on newer-schema store (§3.6, §9.5).
|
||||
|
||||
Spec: §3.6, §10.2, §10.3
|
||||
"""
|
||||
conn = sqlite3.connect(str(store_path))
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
|
||||
cursor = conn.execute("PRAGMA user_version")
|
||||
current_version = cursor.fetchone()[0]
|
||||
|
||||
if current_version > SCHEMA_VERSION:
|
||||
conn.close()
|
||||
raise ValueError(
|
||||
f"Observation store written by a newer Fenris (version {current_version}) "
|
||||
f"— upgrade Fenris"
|
||||
)
|
||||
|
||||
if current_version == SCHEMA_VERSION:
|
||||
conn.close()
|
||||
return 0 # Already up to date
|
||||
|
||||
steps = SCHEMA_VERSION - current_version
|
||||
_apply_migrations(conn, current_version)
|
||||
conn.execute(f"PRAGMA user_version={SCHEMA_VERSION}")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return steps
|
||||
|
||||
|
||||
def is_store_faulty(store_path: Path) -> bool:
|
||||
"""Check if the store is present but cannot be read or trusted."""
|
||||
if not store_path.exists():
|
||||
|
||||
Reference in New Issue
Block a user