Add CI-like large-vault validation for TUI v2

This commit is contained in:
thePR0M3TH3AN committed 2026-03-01 16:39:35 -05:00
1 parent eba7ff3353
commit 733a70c16f
6 files changed
+138 -2

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ This directory contains SeedPass project documentation.
- `tui_v2_plan.md`
- `tui_v2_parity_checklist.md`
- `tui_v2_cutover_decision.md`
- `tui_v2_large_vault_validation.md`
- `security.md`
- `nostr_setup.md`
- `nostr_namespace_reset.md`
+48
View File
@@ -0,0 +1,48 @@
# TUI v2 Large-Vault Validation
Status: Added on `beta` (March 1, 2026).
This document defines a deterministic, CI-like validation pass for TUI v2 behavior at large vault sizes.
## What Is Validated
- Pagination behavior across large deterministic datasets.
- Detail preview truncation behavior for large document content.
## Test Module
- `src/tests/test_tui_v2_large_vault_validation.py`
## Deterministic Data Profile
- Standard profile: `10,000` entries.
- Stress profile: `50,000` entries (`--stress`).
- Labels are deterministic (`Entry-000000` style).
## Runtime Thresholds
Pagination scan budget (wall-clock for scan loop):
- `10,000` rows: `<= 2.0s`
- `50,000` rows: `<= 8.0s`
Detail truncation checks:
- Confirms bounded preview behavior at large content sizes.
## Commands
Standard CI-like run:
```bash
.venv/bin/python -m pytest -q src/tests/test_tui_v2_large_vault_validation.py
```
Extended stress run:
```bash
.venv/bin/python -m pytest -q --stress src/tests/test_tui_v2_large_vault_validation.py
```
## Notes
- Stress tests are opt-in in this repository (require `--stress`).
- Thresholds are intentionally conservative to reduce environment flakiness while still catching regressions.
+4 -2
View File
@@ -39,7 +39,7 @@ This checklist tracks readiness to switch default interactive mode from legacy T
- Incomplete parity for legacy-only interactive operations not yet mapped into TUI v2.
- Textual runtime/version behavior can vary by environment.
- No dedicated Textual interaction test suite yet for pagination and graph traversal.
- Large-vault validation is bounded to deterministic pagination/preview checks and should be expanded with full end-to-end sync workloads.
## Validation Checklist Before Cutover
@@ -48,5 +48,7 @@ This checklist tracks readiness to switch default interactive mode from legacy T
- `src/tests/test_tui_v2_textual_interactions.py` (skips when `textual` is unavailable).
- [x] Add non-UI unit tests for TUI v2 helper logic.
- `src/tests/test_tui_v2_helpers.py` covers command parsing, pagination, and detail truncation.
- [ ] Verify large vault behavior with realistic data volume in CI-like environment.
- [x] Verify large vault behavior with realistic data volume in CI-like environment.
- `src/tests/test_tui_v2_large_vault_validation.py`
- standard: `10,000` rows, stress: `50,000` rows (`--stress`)
- [ ] Confirm help text and docs match shipped keybindings and palette commands.
+1
View File
@@ -59,6 +59,7 @@
<li><a href="#" data-file="tui_v2_plan.md" class="doc-link">&gt; TUI v2 Plan</a></li>
<li><a href="#" data-file="tui_v2_parity_checklist.md" class="doc-link">&gt; TUI v2 Parity</a></li>
<li><a href="#" data-file="tui_v2_cutover_decision.md" class="doc-link">&gt; TUI v2 Cutover</a></li>
<li><a href="#" data-file="tui_v2_large_vault_validation.md" class="doc-link">&gt; TUI v2 Large Vault</a></li>
<li><a href="#" data-file="security.md" class="doc-link">&gt; Security</a></li>
<li><a href="#" data-file="security_readiness_checklist.md" class="doc-link">&gt; Security Readiness</a></li>
<li><a href="#" data-file="agent_autonomy_security_plan.md" class="doc-link">&gt; Agent Security Plan</a></li>
+2
View File
@@ -194,3 +194,5 @@
- Added `src/tests/test_tui_v2_helpers.py` with coverage for palette parsing edge cases, pagination normalization, and large-vault pagination smoke sizes up to 50k rows.
- 2026-03-01: Added Textual interaction tests in `src/tests/test_tui_v2_textual_interactions.py` for pagination/search, document edit+save, link add/remove + neighbor open, and retry-after-failure.
- Introduced a test hook in `launch_tui2(..., app_hook=...)` so tests can capture and pilot the Textual app instance without starting a live terminal run.
- 2026-03-01: Added CI-like large-vault validation with explicit thresholds in `src/tests/test_tui_v2_large_vault_validation.py` (10k rows standard, 50k rows under `--stress`).
- Added docs `docs/tui_v2_large_vault_validation.md` with exact commands and budgets; parity checklist now marks large-vault CI-like validation complete.
@@ -0,0 +1,82 @@
from __future__ import annotations
from time import perf_counter
import pytest
from seedpass.tui_v2.app import pagination_window, truncate_entry_for_display
def _deterministic_labels(rows: int) -> list[str]:
return [f"Entry-{i:06d}" for i in range(rows)]
@pytest.mark.parametrize(
("rows", "max_seconds"),
[
(10000, 2.0),
pytest.param(50000, 8.0, marks=pytest.mark.stress),
],
)
def test_large_vault_pagination_validation(rows: int, max_seconds: float) -> None:
"""CI-like pagination scan over deterministic large-vault datasets."""
labels = _deterministic_labels(rows)
start = perf_counter()
total_seen = 0
page = 0
seen_first = None
seen_last = None
while True:
page, start_idx, end_idx, total_pages = pagination_window(rows, 200, page)
if start_idx >= end_idx:
break
batch = labels[start_idx:end_idx]
assert len(batch) <= 200
if seen_first is None:
seen_first = batch[0]
seen_last = batch[-1]
total_seen += len(batch)
if page >= total_pages - 1:
break
page += 1
elapsed = perf_counter() - start
assert total_seen == rows
assert seen_first == "Entry-000000"
assert seen_last == f"Entry-{rows - 1:06d}"
assert (
elapsed <= max_seconds
), f"Large-vault pagination scan exceeded budget: {elapsed:.3f}s > {max_seconds:.3f}s"
@pytest.mark.parametrize(
("content_size", "limit", "expected_truncated"),
[
(4096, 4000, True),
(1000, 4000, False),
pytest.param(200000, 4000, True, marks=pytest.mark.stress),
],
)
def test_large_document_detail_truncation_validation(
content_size: int, limit: int, expected_truncated: bool
) -> None:
"""Ensure large document previews remain bounded and deterministic."""
payload = truncate_entry_for_display(
{
"kind": "document",
"label": "Big Doc",
"content": "X" * content_size,
},
limit,
)
assert payload["label"] == "Big Doc"
assert payload["kind"] == "document"
assert ("content_truncated" in payload) is expected_truncated
if expected_truncated:
assert payload["content"].startswith("X" * limit)
assert "truncated" in payload["content"]
else:
assert payload["content"] == "X" * content_size