110 lines
6.7 KiB
Markdown
110 lines
6.7 KiB
Markdown
# Project State
|
|
|
|
## Project Reference
|
|
|
|
See: .planning/PROJECT.md (updated 2026-02-28)
|
|
|
|
**Core value:** Users can connect via SSH and seamlessly browse a vault of linked markdown documents with retro BBS aesthetics
|
|
**Current focus:** PROJECT COMPLETE — All 4 phases and 10 plans executed
|
|
|
|
## Current Position
|
|
|
|
Phase: 4 of 4 (BBS Polish and Live Content) — COMPLETE
|
|
Plan: 3 of 3 in current phase (04-01, 04-02, 04-03 all done)
|
|
Status: PROJECT COMPLETE — live reload with 300ms debounce, scroll preservation, and non-fatal watcher failure handling
|
|
Last activity: 2026-03-01 - Completed quick task 2: Demo vault content with ASCII art splash and feature pages
|
|
|
|
Progress: [██████████] 100%
|
|
|
|
## Performance Metrics
|
|
|
|
**Velocity:**
|
|
- Total plans completed: 10
|
|
- Average duration: 3.5 min
|
|
- Total execution time: 0.58 hours
|
|
|
|
**By Phase:**
|
|
|
|
| Phase | Plans | Total | Avg/Plan |
|
|
|-------|-------|-------|----------|
|
|
| 01-safety-foundation | 3 | 7 min | 2.3 min |
|
|
| 02-vault-core-and-rendering | 3 | 9 min | 3.0 min |
|
|
| 03-navigation-and-links | 2 | 7 min | 3.5 min |
|
|
| 04-bbs-polish-and-live-content | 3 | 19 min | 6.3 min |
|
|
|
|
**Recent Trend:**
|
|
- Last 5 plans: 4 min, 3 min, 4 min, 8 min, 7 min
|
|
- Trend: Stable
|
|
|
|
*Updated after each plan completion*
|
|
|
|
## Accumulated Context
|
|
|
|
### Decisions
|
|
|
|
Decisions are logged in PROJECT.md Key Decisions table.
|
|
Recent decisions affecting current work:
|
|
|
|
- Pre-Phase 1: Verify `edition = "2024"` compiles before changing to 2021 — leave it if `cargo build` succeeds
|
|
- Pre-Phase 1: Use pulldown-cmark event-based approach for markdown parsing (not comrak)
|
|
- Pre-Phase 1: No tokio/async runtime — synchronous event loop only
|
|
- Pre-Phase 2: Choose wiki-link parsing strategy before implementation (regex pre-pass vs post-parse interception)
|
|
- 01-01: Resolve relative vault_path against config file parent dir (not cwd) — bbs.toml lives next to binary
|
|
- 01-01: detect_login_shell() called before parse_cli() — both read argv[0], parse_cli strips the dash
|
|
- 01-02: Use ratatui::crossterm re-export path — crossterm is transitive dep, not direct dep in Cargo.toml
|
|
- 01-02: SIGINT not registered via signal-hook — crossterm key events handle double-press Ctrl+C in Plan 03
|
|
- 01-02: restore_terminal() skips ratatui::restore() — that would call LeaveAlternateScreen (never entered)
|
|
- 01-03: show_goodbye() called after restore_terminal() — terminal must be in cooked mode before println! is safe
|
|
- 01-03: app_config stored in App struct for Phase 2 access — vault_path accessible inside event loop
|
|
- 01-03: Quit prompt cleared on any non-Ctrl+C key — pressing any key dismisses double-press window
|
|
- 02-01: LinesWithNewlines iterator added to preserve trailing \n for syntect grammar correctness
|
|
- 02-01: mod declarations added to main.rs during Plan 02 (not Plan 03) — compiler needs them to check renderer.rs
|
|
- 02-01: syntect default-fancy feature uses pure-Rust fancy-regex (avoids Oniguruma C lib)
|
|
- 02-02: Full emit_code_block and emit_table written in Task 1 (not stubs) — avoids throwaway code
|
|
- 02-02: Box width for code blocks capped at terminal width — prevents border overflow on long lines
|
|
- 02-02: Table n_cols derived from max(alignments.len(), max row length) — handles malformed GFM tables
|
|
- [Phase 02-03]: raw_content stored in App for resize re-render — avoids disk re-read on window resize
|
|
- [Phase 02-03]: draw_error_screen() unified for Missing and Error via Option<&str> reason parameter
|
|
- [Phase 02-03]: Scroll keys placed before _ catch-all — j/k during quit prompt does not dismiss it
|
|
- [Phase 03-navigation-and-links]: vault_path added to render_markdown for render-time broken wiki-link detection
|
|
- [Phase 03-navigation-and-links]: Broken wiki-links checked at render time; standard links deferred to navigation time
|
|
- [Phase 03-navigation-and-links]: link_span_start_count field tracks span array position at Tag::Link Start for span_len computation
|
|
- [Phase 03-02]: navigate_to does NOT push to history on Missing/ReadError — user stays on current page conceptually
|
|
- [Phase 03-02]: navigate_back/forward re-loads from disk (no render cache) per research recommendation
|
|
- [Phase 03-02]: Draw-time REVERSED uses lines.clone() per frame — stored lines unchanged for resize re-render
|
|
- [Phase 03-02]: Span overlap detection extended beyond plan spec — catches spans starting before col_offset that extend into link range
|
|
- [Phase 04]: resolve_wiki_link() Directory sentinel placed before rfind('/') split — prevents 'directory' being misinterpreted as a subpath prefix
|
|
- [Phase 04]: navigate_back/forward use if/else-if branch for __directory__ not load_document — avoids spurious Missing document state for virtual page
|
|
- [Phase 04]: handle_resize() returns early for __directory__ — raw_content is None for virtual pages, prevents stale-content confusion
|
|
- [Phase 04-03]: Watch parent directory (not the file itself) — survives atomic saves where editors rename temp file over target
|
|
- [Phase 04-03]: try_recv drain loop per poll iteration — drains all queued events, debounce collapses burst into single reload
|
|
- [Phase 04-03]: FileWatcher initialized in main.rs before App::new() — avoids self-referential ownership, keeps constructor pure
|
|
- [Phase 04-03]: Non-fatal watcher failure — warning printed, None passed to App, app runs without live reload
|
|
- [quick-1]: Bare Left/Right match arms placed after Alt+Left/Alt+Right guards — match order ensures Alt combos consumed first
|
|
- [quick-1]: BufReader + take(20) for frontmatter parsing — avoids loading entire large files
|
|
- [quick-1]: span_len covers only [name] bracket not description — keeps Tab-cycling highlight correct
|
|
|
|
### Pending Todos
|
|
|
|
None. Project complete. Quick task 1 executed.
|
|
|
|
### Blockers/Concerns
|
|
|
|
All blockers resolved:
|
|
- **REND blocker resolved**: renderer.rs uses no Widget trait at all
|
|
- **NAV path traversal resolved**: is_within_vault() with canonicalize + starts_with guards all link resolution in vault.rs
|
|
- **LIVE resolved**: notify 6.1 API verified; parent-directory watch pattern avoids inotify exhaustion and survives atomic saves
|
|
|
|
### Quick Tasks Completed
|
|
|
|
| # | Description | Date | Commit | Directory |
|
|
|---|-------------|------|--------|-----------|
|
|
| 1 | Arrow key navigation and directory description column | 2026-03-01 | 2d1e018 | [1-arrow-key-navigation-and-directory-descr](./quick/1-arrow-key-navigation-and-directory-descr/) |
|
|
| 2 | Demo vault content with ASCII art splash and feature pages | 2026-03-01 | 4464774 | [2-create-demo-vault-content-with-ascii-art](./quick/2-create-demo-vault-content-with-ascii-art/) |
|
|
|
|
## Session Continuity
|
|
|
|
Last session: 2026-03-01
|
|
Stopped at: Completed quick-1 (arrow key navigation + directory descriptions)
|
|
Resume file: N/A — project complete, quick task 1 done
|