Two Repos-tab quality-of-life changes:
- External/vendored clones (repos with zero of your own commits — e.g. an
upstream cloned for reference and never pushed to) are measured on
refresh, cached in stats_cache (RepoStatsEntry.authored), shown with a
dim ⧉ marker prefixed to the name, and hidden by the persistent
hide_external_clones config toggle (key `x`, the `S` menu, or
`vulp list --external|--no-external`). A fork you do commit to stays
yours, so only true reference clones are flagged.
- Inside the `/` filter box, ↑↓ now move through the live-filtered
results and Enter opens the highlighted repo/project directly, instead
of the filter only "locking" on Enter with no way to scroll or select.
The hub hands its live terminal to detail/project_detail on open (already
flash-free going in), but both sub-views unconditionally tore the terminal
down on exit; the hub's next loop iteration then always called tui::setup()
again, producing a real LeaveAlternateScreen -> (plain terminal visible for
one frame) -> EnterAlternateScreen blink on every trip back.
- detail::run / project_detail::run now return the live terminal on a clean
exit instead of tearing it down (only torn down if the inner loop itself
errors); hub::tui_phase accepts an already-live terminal and skips its own
setup() when given one, threading it across loop iterations
- project_detail's own nested repo-detail call (Enter on its Repos tab) had
the same issue one level down, fixed the same way via Option<Tty> so the
terminal can be taken out for the nested call and put back
- verified via raw pty byte counts: two full hub<->detail round trips now
show zero EnterAlternateScreen/LeaveAlternateScreen pairs in between,
vs. one pair per trip before
- src/stats/: OwnEmailMatcher (config emails + GH no-reply per account) +
git-side --author filtering (cheap even on the pterodactyl fork's 4700+
commits); streak (current/longest, midnight-grace rule), 52-week heatmap,
day/hour histograms — one scan feeds all of them, data layer only for now
(visual Stats-tab redesign stays in Sprint D's mockup-first cycle)
- src/stats/cadence.rs: release cadence (median tag gap, local tags, Tier A)
- src/stats/size.rs + cache.rs: git-object vs working-tree size, persisted
in new ~/.vulp/stats_cache.toml (max 1 sample/day), recorded only during
[R]/vulp refresh — confirms vulp's own filter-repo cleanup (539MB->834KB)
- src/digest.rs: WeeklyDigest struct + 3 renderers (Discord embed/markdown
archive/plaintext); vulp digest [send discord|webhook <url>] CLI, webhook
stored via existing auth token store (~/.vulp/.tokens, 0600), never logged;
send respects --dry-run
- TUI: [d] on Stats previews the digest in a Modal::Info before anything is
ever sent
- fix: list_contributors used --all (double-counts after fetching remotes),
now --branches
- config: stats_author_emails field (TUI-editable)
- verified: streak/delta/top-repo/release math against a hand-built commit
history, webhook validation+permissions, dry-run, real refresh (51 repos,
vulp's own entry confirms the filter-repo win), TUI preview via pyte