Add agent mode, hardened TUI harness, coverage gates, and cross-platform installer smoke CI

This commit delivers four related improvements focused on reliability and automation while preserving existing human/TUI workflows.

1) Agent-first CLI mode (additive)
- Added new `seedpass agent` command group (`src/seedpass/cli/agent.py`) and wired it into CLI root.
- Implemented non-interactive profile bootstrap: `seedpass agent init` with `--seed|--seed-file|--generate-seed` and password env injection (`--password-env`).
- Added policy management commands: `agent policy-show` and `agent policy-set` with allow/deny kind controls.
- Added JSON-based secret retrieval: `seedpass -f <fingerprint> agent get <query> --ttl <sec>` with lease metadata and policy enforcement.
- Kept regular human mode fully available; no behavioral changes to interactive TUI entrypoint.

2) TUI agent harness deepening and stabilization
- Refactored harness into scenario profiles: `core`, `extended`, `stress` with `--scenario` selection.
- Added deterministic seeded stress campaigns: `--stress-cycles`, `--stress-seed`.
- Added scenario-specific required coverage keys and report metadata.
- Added post-condition assertions in extended scenario (archive/restore consistency, lock/unlock retrieval recovery).
- Hardened prompt matching for output variants and fail-fast behavior on non-zero SeedPass exit codes.
- Added harness unit tests for helper logic and control flow.

3) Critical module coverage gate tooling
- Added `scripts/check_critical_coverage.py` to enforce per-module thresholds from coverage JSON and report uncovered functions.
- Added override controls (`--threshold`, `--no-default-thresholds`) and optional JSON result output.
- Integrated coverage JSON generation into CI helper script and optional gate execution via `CRITICAL_COVERAGE_GATE=1`.
- Tuned default thresholds using full-suite baseline and increased strictness:
  - `src/main.py >= 50%`
  - `src/seedpass/core/manager.py >= 60%`
  - `src/seedpass/core/encryption.py >= 80%`
  - `src/seedpass/core/migrations.py >= 90%`
- Added tests for coverage gate parser/analysis logic and targeted manager worker path tests.

4) Installer validation framework for beta/main
- Added cross-platform installer smoke scripts:
  - `scripts/installer_smoke_unix.sh`
  - `scripts/installer_smoke_windows.ps1`
- Added GitHub Actions workflow `.github/workflows/installer-smoke.yml` with:
  - reduced PR matrix
  - full scheduled/manual matrix across OS/branch/mode
  - per-job log capture and artifact uploads for failure triage
- Added installer testing documentation and linked from README.

Additional housekeeping
- Added `.venv/` to `.gitignore`.
- Updated docs for new harness scenarios, seeded stress mode, post-condition metadata, coverage gate usage, and installer testing workflow.
This commit is contained in:
thePR0M3TH3AN committed 2026-02-23 15:47:59 -05:00
1 parent dd7290e83b
commit 03958106e1
16 files changed
+1826 -54

No files matched your search

@@ -0,0 +1,58 @@
import asyncio
from seedpass.core.manager import PasswordManager
from seedpass.core import manager as manager_module
def test_start_background_vault_sync_thread_worker_path(monkeypatch):
pm = PasswordManager.__new__(PasswordManager)
pm.offline_mode = False
events = []
async def fake_sync_vault_async(*, alt_summary=None):
return {"alt_summary": alt_summary}
monkeypatch.setattr(pm, "sync_vault_async", fake_sync_vault_async)
monkeypatch.setattr(
manager_module.bus, "publish", lambda *args: events.append(args)
)
class ImmediateThread:
def __init__(self, target, daemon):
self._target = target
self.daemon = daemon
def start(self):
self._target()
monkeypatch.setattr(manager_module.threading, "Thread", ImmediateThread)
pm.start_background_vault_sync("thread-path")
assert ("sync_started",) in events
assert ("sync_finished", {"alt_summary": "thread-path"}) in events
def test_start_background_vault_sync_async_worker_path(monkeypatch):
pm = PasswordManager.__new__(PasswordManager)
pm.offline_mode = False
events = []
async def fake_sync_vault_async(*, alt_summary=None):
return {"alt_summary": alt_summary}
monkeypatch.setattr(pm, "sync_vault_async", fake_sync_vault_async)
monkeypatch.setattr(
manager_module.bus, "publish", lambda *args: events.append(args)
)
async def runner():
pm.start_background_vault_sync("async-path")
await asyncio.sleep(0.02)
asyncio.run(runner())
assert ("sync_started",) in events
assert ("sync_finished", {"alt_summary": "async-path"}) in events