mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-06 12:52:04 +00:00
Add TUI v2 scaffold, plan docs, and discovery command hints
This commit is contained in:
1 parent
982fba6404
commit
8d3d2a3993
10 files changed
+222
-2
No files matched your search
@@ -108,6 +108,7 @@ For machine-readable discovery, run:
|
||||
```bash
|
||||
seedpass capabilities --format json
|
||||
seedpass agent bootstrap-context
|
||||
seedpass tui2 --check
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
@@ -23,6 +23,7 @@ This directory contains SeedPass project documentation.
|
||||
- `SPEC.md`
|
||||
- `entry_types.md`
|
||||
- `entry_graph.md`
|
||||
- `tui_v2_plan.md`
|
||||
- `security.md`
|
||||
- `nostr_setup.md`
|
||||
- `nostr_namespace_reset.md`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generator entry point for Archivox
|
||||
// Generator entry point for SeedPass docs
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const matter = require('gray-matter');
|
||||
@@ -213,7 +213,7 @@ async function generate({ contentDir = 'content', outputDir = '_site', configPat
|
||||
}
|
||||
|
||||
// Copy the main assets directory (theme, js, etc.)
|
||||
// Always resolve assets relative to the Archivox package so it works
|
||||
// Always resolve assets relative to the docs package so it works
|
||||
// regardless of the current working directory or config location.
|
||||
const mainAssetsSrc = path.resolve(__dirname, '../../assets');
|
||||
const mainAssetsDest = path.join(outputDir, 'assets');
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# TUI v2 Plan (Textual)
|
||||
|
||||
Status: Draft implementation plan on `beta` branch.
|
||||
|
||||
Goal: Introduce a modern, modular TUI (`seedpass tui2`) without rewriting core logic or breaking existing CLI/API behavior.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Keep `seedpass.core` as the source of truth for all business logic.
|
||||
- Keep current TUI (`seedpass` default path) operational during migration.
|
||||
- Maintain interface modularity:
|
||||
- CLI/TUI
|
||||
- API
|
||||
- future GUI
|
||||
|
||||
## Proposed Stack
|
||||
|
||||
- Primary: `Textual` for TUI v2 shell and interaction model.
|
||||
- Keep dependency optional initially; runtime check from `seedpass tui2 --check`.
|
||||
|
||||
## Architecture
|
||||
|
||||
1. `seedpass.core`
|
||||
- Existing logic/services (`EntryManager`, `EntryService`, sync, vault, policy).
|
||||
|
||||
2. `seedpass.app` (future thin orchestration layer)
|
||||
- UI-agnostic use-cases and view-model mappers.
|
||||
- Shared by Textual TUI and future GUI.
|
||||
|
||||
3. Interface adapters
|
||||
- `seedpass.cli` (Typer commands)
|
||||
- `seedpass.tui_v2` (Textual app)
|
||||
- `seedpass.api` (FastAPI)
|
||||
|
||||
## Phased Rollout
|
||||
|
||||
### Phase 0: Scaffold (this PR)
|
||||
- [x] Add plan doc.
|
||||
- [x] Add `seedpass tui2` command.
|
||||
- [x] Add runtime check utility and placeholder launcher.
|
||||
- [ ] Add CI smoke command for `seedpass tui2 --check`.
|
||||
|
||||
### Phase 1: Read-only shell
|
||||
- [ ] Textual app skeleton with 3-pane layout:
|
||||
- filters panel
|
||||
- entry list panel
|
||||
- details panel
|
||||
- [ ] Unlock/profile context hookup.
|
||||
- [ ] Entry list/search/detail read paths.
|
||||
- [ ] Status line for sync/profile/lock state.
|
||||
|
||||
### Phase 2: Core editing workflows
|
||||
- [ ] Add/modify/archive flows for common entry kinds.
|
||||
- [ ] Document editor panel with dirty-state and save/cancel.
|
||||
- [ ] Keybindings + command palette.
|
||||
|
||||
### Phase 3: Graph workflows
|
||||
- [ ] Entry links panel (list, add, remove).
|
||||
- [ ] Relation-aware search controls.
|
||||
- [ ] Neighbor navigation and quick traversal.
|
||||
|
||||
### Phase 4: Cutover readiness
|
||||
- [ ] Feature parity checklist against legacy TUI.
|
||||
- [ ] UX/perf pass for large vaults.
|
||||
- [ ] Error messaging and recovery flows.
|
||||
- [ ] Decide default switch timing (`seedpass` -> `tui2`).
|
||||
|
||||
## Test Strategy
|
||||
|
||||
- Unit tests:
|
||||
- runtime checks and command wiring.
|
||||
- view-model transformations (when `seedpass.app` exists).
|
||||
- Integration tests:
|
||||
- command-level smoke (`seedpass tui2 --check`).
|
||||
- later: Textual interaction tests for list/search/edit/link.
|
||||
- Regression:
|
||||
- full suite must remain green during phased migration.
|
||||
|
||||
## Risks and Mitigations
|
||||
|
||||
- Risk: UI code bypasses core invariants.
|
||||
- Mitigation: enforce service-layer-only mutation from TUI.
|
||||
- Risk: dependency churn (`textual` changes).
|
||||
- Mitigation: pin versions when enabling default path.
|
||||
- Risk: branch drift while both TUIs exist.
|
||||
- Mitigation: parity checklist and shared orchestration layer.
|
||||
|
||||
## Deliverables
|
||||
|
||||
- New command:
|
||||
- `seedpass tui2`
|
||||
- `seedpass tui2 --check`
|
||||
- New package:
|
||||
- `seedpass/tui_v2/`
|
||||
- Docs updates:
|
||||
- this file listed in docs index and discoverability nav.
|
||||
@@ -56,6 +56,7 @@
|
||||
<li><a href="#" data-file="SPEC.md" class="doc-link">> Specification</a></li>
|
||||
<li><a href="#" data-file="entry_types.md" class="doc-link">> Entry Types</a></li>
|
||||
<li><a href="#" data-file="entry_graph.md" class="doc-link">> Entry Graph</a></li>
|
||||
<li><a href="#" data-file="tui_v2_plan.md" class="doc-link">> TUI v2 Plan</a></li>
|
||||
<li><a href="#" data-file="security.md" class="doc-link">> Security</a></li>
|
||||
<li><a href="#" data-file="security_readiness_checklist.md" class="doc-link">> Security Readiness</a></li>
|
||||
<li><a href="#" data-file="agent_autonomy_security_plan.md" class="doc-link">> Agent Security Plan</a></li>
|
||||
|
||||
@@ -162,3 +162,17 @@
|
||||
- Verification:
|
||||
- `.venv/bin/pytest -q src/tests/test_typer_cli.py -k "capabilities_text or capabilities_json" src/tests/test_cli_agent_mode.py -k "bootstrap_context"`
|
||||
- Result: `2 passed`.
|
||||
|
||||
## TUI v2 scaffold kickoff on beta
|
||||
- Added `docs/tui_v2_plan.md` with phased migration plan, risk controls, and testing strategy for Textual-based TUI v2.
|
||||
- Added experimental CLI command `seedpass tui2` and diagnostics mode `seedpass tui2 --check`.
|
||||
- Added new runtime-check/launcher scaffold package at `src/seedpass/tui_v2/`.
|
||||
- Updated discoverability/docs surfaces:
|
||||
- `docs/README.md` includes `tui_v2_plan.md`
|
||||
- `landing/docs.html` includes `TUI v2 Plan`
|
||||
- `README.md` discovery snippet includes `seedpass tui2 --check`
|
||||
- `capabilities` root commands/help hints include `tui2`
|
||||
- Validation:
|
||||
- `py_compile` for updated modules
|
||||
- `pytest` capabilities tests (`2 passed`)
|
||||
- `.venv` smoke run confirms `seedpass tui2 --check` emits runtime diagnostics.
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import importlib.util
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional
|
||||
@@ -11,6 +12,7 @@ import typer
|
||||
from .common import _get_services
|
||||
from seedpass.core.errors import SeedPassError
|
||||
from constants import GUI_BACKEND_CONFIG
|
||||
from seedpass.tui_v2.app import check_tui2_runtime, launch_tui2
|
||||
|
||||
app = typer.Typer(
|
||||
help=(
|
||||
@@ -105,6 +107,45 @@ def root_lock(ctx: typer.Context) -> None:
|
||||
typer.echo("locked")
|
||||
|
||||
|
||||
@app.command("tui2")
|
||||
def tui2(
|
||||
ctx: typer.Context,
|
||||
check: bool = typer.Option(
|
||||
False,
|
||||
"--check",
|
||||
help="Check whether TUI v2 runtime dependencies are available",
|
||||
),
|
||||
fallback_legacy: bool = typer.Option(
|
||||
True,
|
||||
"--fallback-legacy/--no-fallback-legacy",
|
||||
help="Fall back to legacy TUI when TUI v2 runtime is unavailable",
|
||||
),
|
||||
) -> None:
|
||||
"""Launch experimental TUI v2 scaffold."""
|
||||
if check:
|
||||
typer.echo(json.dumps(check_tui2_runtime(), indent=2, sort_keys=True))
|
||||
return
|
||||
|
||||
fingerprint = (ctx.obj or {}).get("fingerprint")
|
||||
launched = launch_tui2(fingerprint=fingerprint)
|
||||
if launched:
|
||||
return
|
||||
|
||||
if fallback_legacy:
|
||||
typer.echo(
|
||||
"TUI v2 runtime unavailable; falling back to legacy TUI. "
|
||||
"Run `seedpass tui2 --check` for diagnostics."
|
||||
)
|
||||
tui = importlib.import_module("main")
|
||||
raise typer.Exit(tui.main(fingerprint=fingerprint))
|
||||
|
||||
typer.echo(
|
||||
"TUI v2 runtime unavailable. Install `textual` and retry.",
|
||||
err=True,
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def gui(
|
||||
install: bool = typer.Option(
|
||||
|
||||
@@ -17,6 +17,7 @@ def build_capabilities() -> dict[str, Any]:
|
||||
"root_commands": [
|
||||
"lock",
|
||||
"gui",
|
||||
"tui2",
|
||||
"capabilities",
|
||||
"entry",
|
||||
"vault",
|
||||
@@ -239,6 +240,7 @@ def build_capabilities() -> dict[str, Any]:
|
||||
"Run `seedpass --help` for top-level commands.",
|
||||
"Run `seedpass <group> --help` for detailed options.",
|
||||
"Use `seedpass capabilities --format json` for machine-readable discovery.",
|
||||
"Run `seedpass tui2 --check` before adopting Textual-based TUI v2.",
|
||||
"For graph workflows, start with `seedpass entry link-add --help` and `seedpass entry links --help`.",
|
||||
"For document workflows, run `seedpass entry import-document --help` and `seedpass agent document-import --help`.",
|
||||
"After unlock/login, run `seedpass capabilities` before autonomous runs.",
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
"""TUI v2 package scaffold (Textual-backed)."""
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
from typing import Any
|
||||
|
||||
|
||||
def check_tui2_runtime() -> dict[str, Any]:
|
||||
"""Return runtime capability diagnostics for TUI v2."""
|
||||
textual_available = importlib.util.find_spec("textual") is not None
|
||||
return {
|
||||
"status": "ok" if textual_available else "unavailable",
|
||||
"backend": "textual",
|
||||
"textual_available": textual_available,
|
||||
"message": (
|
||||
"Textual runtime available."
|
||||
if textual_available
|
||||
else "Textual is not installed. Install `textual` to run tui2."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def launch_tui2(*, fingerprint: str | None = None) -> bool:
|
||||
"""Launch TUI v2 when runtime dependencies are available.
|
||||
|
||||
Returns ``True`` when launch succeeds, ``False`` when runtime is unavailable.
|
||||
"""
|
||||
runtime = check_tui2_runtime()
|
||||
if not runtime["textual_available"]:
|
||||
return False
|
||||
|
||||
# Placeholder shell for incremental migration.
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.containers import Container
|
||||
from textual.widgets import Footer, Header, Static
|
||||
|
||||
class SeedPassTuiV2(App[None]):
|
||||
BINDINGS = [("q", "quit", "Quit")]
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(show_clock=True)
|
||||
with Container():
|
||||
fp_line = f"Fingerprint: {fingerprint}" if fingerprint else "No fingerprint selected"
|
||||
yield Static(
|
||||
"\n".join(
|
||||
[
|
||||
"SeedPass TUI v2 scaffold",
|
||||
fp_line,
|
||||
"",
|
||||
"Next steps:",
|
||||
"- Implement list/search/details panes",
|
||||
"- Add document editor panel",
|
||||
"- Add graph links panel",
|
||||
"",
|
||||
"Press 'q' to quit.",
|
||||
]
|
||||
)
|
||||
)
|
||||
yield Footer()
|
||||
|
||||
SeedPassTuiV2().run()
|
||||
return True
|
||||
|
||||
Reference in new issue
Block a user