From f81d5a4a3374af971b84f41d8c8f732a783f61f0 Mon Sep 17 00:00:00 2001 From: xodapi <4956501+xodapi@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:10:34 +0700 Subject: [PATCH 1/2] docs(dev): evaluate optional Jujutsu workflow (closes #138) --- README.md | 37 +++++++++++++++++++++++++++++++++++++ README.ru.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/README.md b/README.md index 05419c1..acca391 100644 --- a/README.md +++ b/README.md @@ -378,6 +378,43 @@ See [ROADMAP.md](ROADMAP.md) for the current improvement backlog. - Linux (x86_64, aarch64) - Android/Termux — see [docs/termux.md](docs/termux.md); native Slint Android spike is tracked in [docs/android.md](docs/android.md) +## Optional Jujutsu Workflow + +`jj` is reasonable here only as an optional local workflow on top of the +existing Git repository. It can improve local iteration with operation log, +conflict recovery, and cleaner in-progress history, but it should not replace +the project's canonical GitHub flow. + +Recommended stance: + +- Use `jj` only if a developer or agent already prefers it locally. +- Keep GitHub Issues, branches, PRs, and remote state managed through `git` + + `gh`. +- Do not require `jj` in CI, build scripts, onboarding, or AGENTS workflow. +- Do not add `vcs-jj` or `vcs-core` unless a future automation issue proves + they solve a concrete project problem. + +Minimal issue workflow with `jj`: + +```bash +jj git clone https://github.com/xodapi/vimit.git +cd vimit +gh issue view 138 +git checkout -b issue-138-evaluate-optional-jujutsu-workflow +jj bookmark create issue-138-evaluate-optional-jujutsu-workflow -r @ + +# edit files, then verify the required check +cargo fmt --check + +# when ready, sync the current jj commit to the Git branch and push normally +jj git push --bookmark issue-138-evaluate-optional-jujutsu-workflow +gh pr create --base main --title "docs(dev): evaluate optional Jujutsu workflow" --body "Closes #138" +``` + +If you use `jj`, treat it as a personal productivity layer. The repository +still expects Git-compatible branch names, standard commits, and the same issue +assignment / PR review flow documented in `AGENTS.md`. + ## Tests ```bash diff --git a/README.ru.md b/README.ru.md index 3caa2ec..d345836 100644 --- a/README.ru.md +++ b/README.ru.md @@ -368,6 +368,43 @@ https://github.com/xodapi/vimit/discussions - Linux (x86_64, aarch64) - Android/Termux — см. [docs/termux.md](docs/termux.md); native Slint Android spike описан в [docs/android.md](docs/android.md) +## Optional Jujutsu Workflow + +`jj` здесь уместен только как optional локальный workflow поверх уже +существующего Git-репозитория. Он может сделать локальные итерации удобнее за +счёт operation log, более мягкого восстановления после конфликтов и аккуратной +истории промежуточных изменений, но не должен заменять canonical GitHub flow +проекта. + +Рекомендация по проекту: + +- Использовать `jj` только если разработчику или агенту он уже удобен локально. +- GitHub Issues, ветки, PR и remote state оставлять на `git` + `gh`. +- Не делать `jj` обязательным для CI, build scripts, onboarding или AGENTS workflow. +- Не добавлять `vcs-jj` или `vcs-core`, пока отдельный automation issue не + докажет, что это решает конкретную проблему проекта. + +Минимальный issue workflow с `jj`: + +```bash +jj git clone https://github.com/xodapi/vimit.git +cd vimit +gh issue view 138 +git checkout -b issue-138-evaluate-optional-jujutsu-workflow +jj bookmark create issue-138-evaluate-optional-jujutsu-workflow -r @ + +# правки, затем обязательная проверка +cargo fmt --check + +# когда всё готово, синхронизировать текущий jj commit с Git-веткой и пушить как обычно +jj git push --bookmark issue-138-evaluate-optional-jujutsu-workflow +gh pr create --base main --title "docs(dev): evaluate optional Jujutsu workflow" --body "Closes #138" +``` + +Если использовать `jj`, то только как личный слой удобства поверх Git. Для +репозитория по-прежнему обязательны Git-совместимые имена веток, обычные +коммиты и тот же issue/PR workflow, который описан в `AGENTS.md`. + ## Тесты ```bash From b99b68e4b98dd47fcb0ec8b3edae85bad09c0308 Mon Sep 17 00:00:00 2001 From: xodapi <4956501+xodapi@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:17:15 +0700 Subject: [PATCH 2/2] test(tui): expand snapshots for agent states (closes #119) --- src/cli/monitor.rs | 164 ++++++++++++++++++ ...tests__tui_snapshot_agent_stuck_state.snap | 44 +++++ ...snapshot_reset_edge_with_empty_trends.snap | 44 +++++ 3 files changed, 252 insertions(+) create mode 100644 src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_agent_stuck_state.snap create mode 100644 src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_reset_edge_with_empty_trends.snap diff --git a/src/cli/monitor.rs b/src/cli/monitor.rs index 8e9dd04..f9914d6 100644 --- a/src/cli/monitor.rs +++ b/src/cli/monitor.rs @@ -1575,6 +1575,74 @@ mod tests { } } + fn agent_stuck_snapshot() -> StatusSnapshot { + let mut snapshot = test_snapshot(); + snapshot.abtop = Some(serde_json::json!({ + "token_rate": 128.4, + "sessions_total": 4, + "sessions_active": 1, + "agents": [ + { + "agent_cli": "codex", + "sessions": 3, + "active": 1, + "waiting": 2, + "total_tokens": 18500, + "active_tokens": 9200, + "max_context_pct": 88.0, + "max_turn_count": 54 + }, + { + "agent_cli": "claude", + "sessions": 1, + "active": 0, + "waiting": 1, + "total_tokens": 2400, + "active_tokens": 0, + "max_context_pct": 12.0, + "max_turn_count": 8 + } + ] + })); + snapshot + } + + fn reset_edge_snapshot() -> StatusSnapshot { + let mut snapshot = test_snapshot(); + snapshot.windows = vec![ + ng::WindowState { + key: "5h", + level: "ok".to_string(), + reset: "sync pending".to_string(), + reset_in_seconds: None, + credits: Some(ng::Metric { + used: 20.0, + limit: 100.0, + remaining: 80.0, + percent: 20.0, + }), + requests: None, + percent: 20.0, + }, + ng::WindowState { + key: "24h", + level: "warning".to_string(), + reset: "manual review".to_string(), + reset_in_seconds: Some(600), + credits: None, + requests: Some(ng::Metric { + used: 87.0, + limit: 100.0, + remaining: 13.0, + percent: 87.0, + }), + percent: 87.0, + }, + ]; + snapshot.abtop = None; + snapshot + } + #[test] fn monitor_output_has_dashboard_sections() { let snapshot = test_snapshot(); @@ -1655,6 +1723,56 @@ mod tests { ) } + #[allow(clippy::too_many_arguments)] + fn render_tui_to_string_with_context( + snapshot: Option<&StatusSnapshot>, + error: Option<&str>, + interval_secs: u64, + next_refresh_secs: u64, + with_abtop: bool, + warning_threshold: f64, + window_history: &HashMap<&str, WindowHistory>, + preset: Preset, + width: u16, + height: u16, + panels: PanelState, + trend_days: &[TrendDay], + ) -> String { + use ratatui::backend::TestBackend; + let backend = TestBackend::new(width, height); + let mut terminal = Terminal::new(backend).unwrap(); + terminal + .draw(|frame| { + draw_frame( + frame, + snapshot, + error, + interval_secs, + next_refresh_secs, + with_abtop, + warning_threshold, + window_history, + preset, + Theme::Btop, + &panels, + &[], + 0, + trend_days, + ); + }) + .unwrap(); + let buffer = terminal.backend().buffer(); + let mut out = String::new(); + for y in 0..height { + for x in 0..width { + let cell = &buffer[(x, y)]; + out.push_str(cell.symbol()); + } + out.push('\n'); + } + out + } + #[allow(clippy::too_many_arguments)] fn render_tui_to_string_themed( snapshot: Option<&StatusSnapshot>, @@ -1885,4 +2003,50 @@ mod tests { ); insta::assert_snapshot!(output); } + + #[test] + fn tui_snapshot_agent_stuck_state() { + let snapshot = agent_stuck_snapshot(); + let history = HashMap::new(); + + let output = render_tui_to_string( + Some(&snapshot), + None, + 5, + 1, + true, + 75.0, + &history, + Preset::Full, + 120, + 40, + ); + insta::assert_snapshot!(output); + } + + #[test] + fn tui_snapshot_reset_edge_with_empty_trends() { + let snapshot = reset_edge_snapshot(); + let history = HashMap::new(); + let panels = PanelState { + show_trends: true, + ..PanelState::default() + }; + + let output = render_tui_to_string_with_context( + Some(&snapshot), + None, + 5, + 4, + true, + 75.0, + &history, + Preset::Full, + 120, + 40, + panels, + &[], + ); + insta::assert_snapshot!(output); + } } diff --git a/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_agent_stuck_state.snap b/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_agent_stuck_state.snap new file mode 100644 index 0000000..0a1b035 --- /dev/null +++ b/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_agent_stuck_state.snap @@ -0,0 +1,44 @@ +--- +source: src/cli/monitor.rs +expression: output +--- +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ VibeMode v0.6.4 Dir | WARNING | peak 78% │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + ┌ 5h | warning | reset через 3ч 59м ─────────────────────┐ ┌ 24h | ok | reset через 18ч 59м ────────────────────────┐ + │██████████████████████████78% ██████████████ │ │██████████████████████████51% │ + └────────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────────┘ + cr 39/50 (78%) cr 91/180 (51%) + rq 610/1,0K (61%) rq 1,5K/4,0K (38%) + + + + + + + + ┌ 7d | ok | reset через 5д 23ч ──────────────────────────┐ ┌ 30d | ok | reset через 20д 23ч ────────────────────────┐ + │███████████████████████ 42% │ │███████████████████████ 41% │ + └────────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────────┘ + cr 214/600 (36%) cr 819/2,0K (41%) + rq 8,3K/20,0K (42%) rq 26,0K/80,0K (32%) + + + + + + +┌ alerts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│warning 5h/credits at 78.0%: 11 left, reset через 3ч 59м │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌ agents ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│token rate 128.4/min | sessions 4 active 1 │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ ? help 5 trends q quit r refresh auto 5s next 1s │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_reset_edge_with_empty_trends.snap b/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_reset_edge_with_empty_trends.snap new file mode 100644 index 0000000..95a5d17 --- /dev/null +++ b/src/cli/snapshots/vimit__cli__monitor__tests__tui_snapshot_reset_edge_with_empty_trends.snap @@ -0,0 +1,44 @@ +--- +source: src/cli/monitor.rs +expression: output +--- +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ VibeMode v0.6.4 Dir | WARNING | peak 87% │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + ┌ 5h | ok | reset unknown ───────────────────────────────┐ ┌ 24h | warning | reset через 10м ───────────────────────┐ + │███████████ 20% │ │██████████████████████████87% ███████████████████ │ + └────────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────────┘ + cr 20/100 (20%) cr n/a + rq n/a rq 87/100 (87%) + + + + + + + + + + +┌ alerts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│warning 24h/requests at 87.0%: 13 left, reset через 10м │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌ agents ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│run with --with-abtop for agent data │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌ 30-day trends ───────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│no trend data yet — run vimit to collect snapshots │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ ? help 5 trends q quit r refresh auto 5s next 4s │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘