Repository navigation
Conversation
T45–T49: TUI slash handler fixes, test fixes, cleanup
- Remove unused imports (PawanConfig, ToolDefinition) in execute.rs - Remove dead duplicate functions from construction.rs (already in mod.rs) - Gate test-only re-exports behind #[cfg(test)] in agent/mod.rs, config/mod.rs - Remove unused QUEUE_DONE_TTL_MS constant from tools/task.rs - Add #[allow(dead_code)] on future-API items in pawan-cli (theme, layout, etc.) - Add v0.5.7 changelog entry with refactoring, features, and test summary - Update test counts from 988+ to 1627+ across README, crate READMEs, and docs
- pawan-core: remove unused imports, fix mut variables - pawan-cli: fix clamp, sort_by_key, checked_div, needless borrows - rename ExportFormat::from_str to parse to avoid std trait confusion - fix unused variables in tests with .. rest patterns
fix: resolve all clippy -D warnings across workspace
- README.md, crate READMEs, guide.md, triage.md, CHANGELOG.md
docs: update test count and version refs for v0.5.7
…#27) * fix: remove maki refs, fix NVIDIA model catalog auth, trim fallback list - Remove 'inspired by maki-ui' from theme.rs and layout.rs comments - Send Authorization Bearer header when NVIDIA_API_KEY is set - Replace 500+ hardcoded models with 13 curated fallback models - Fix clippy sort_by_key and redundant import warnings * fix: update model catalog tests and snapshot for curated fallback list - Lower test_default_models_not_empty threshold from 50 to 10 - Accept new model selector snapshot with 13 curated models * refactor: decompose high-CRAP functions into focused helpers CRAP Reduction (execute.rs): - execute_with_all_callbacks: 730 lines → 179 lines (75% reduction) - Extracted 9 helpers: inject_eruka_context, build_user_prompt, apply_iteration_budgets, call_llm_with_retry, accumulate_token_usage, strip_thinking_blocks, handle_no_tool_response, check_tool_permissions, execute_pending_tools, collect_tool_results CRAP Reduction (session_ops.rs): - export_as_html: CC 46 → ~3 (4 helpers: build_html_header, build_html_footer, render_message_html, render_tool_calls_html) - generate_handoff_prompt: CC 49 → ~4 (5 helpers: extract_recent_context, extract_mentioned_files, extract_task_items, extract_constraints, build_prompt_header) All 1643 tests pass. Clippy clean. * refactor: decompose main.rs run(), parse_compaction_summary, quality_score_for CRAP Reduction: - main.rs run(): CC 60 → ~30 via setup_config, resolve_session_resume extraction - parse_compaction_summary: CC 35 → 1 via 6 helper functions (extract_section_content, parse_summary_field, parse_token_counts, parse_compressed_sections, parse_preserved_sections, parse_numbered_items) - quality_score_for: CC 37 → 1 via 3 helpers (score_by_vendor, score_by_capability, score_by_size) Coverage baseline captured: 77.28% lines / 79.08% functions / 76.83% branches All 1643 tests pass. Clippy clean. * chore(pawan): sync 3 file(s) * test: add unit tests for pure TUI functions - scrollbar.rs: 9 tests (construction, render edge cases, color handling) - fuzzy_search.rs: 12 tests (filter, navigation, command_prefix) - status_bar.rs: 11 tests (abbrev_model, format_tokens, context_bar) All 1655 tests pass. Clippy clean. * refactor(tui): convert render.rs to render/ directory module * chore(pawan): sync 3 file(s) * refactor(cli): decompose high-complexity main.rs run functions Break down run_headless (CC=51), run_commit (CC=40), run_doctor (CC=31), and run_tasks (CC=31) into focused helper functions to reduce cyclomatic complexity and CRAP scores. Behavior preserved verbatim. * test(tui): relocate render snapshots and make CWD redaction width-stable Move render snapshots into render/snapshots/ after the render module split and regenerate them against current TUI output. Pad the [CWD] redaction to preserve line width so the welcome box border stays aligned regardless of working-directory length, making the snapshot portable across environments. * refactor: decompose high-complexity functions across cli and core Decompose App::main_loop, MiseTool::execute, OpenAiCompatBackend streaming/generate, App::slash_route, and handle_input_panel_key into focused helper functions. Behavior preserved verbatim.
- LspTool::execute: 10 tests (error paths, arg validation, schema) - InjectionDetector: 22 tests (scan_file, scan_file_streaming, helpers) - main.rs helpers: 20 tests (parse_git_status, commit prompt, headless) - TUI model picker: 8 tests (navigation, input, selection) Total workspace tests: 1715+
- Workspace version 0.5.8, workspace deps pawan-core/pawan-mcp 0.5.8 - CHANGELOG: add v0.5.8 entry (CRAP reduction, render decomposition, 60 tests) - Fix CHANGELOG corruption (embedded line numbers, snapshot tags) - Update test counts 1643→1779 across README, guide, triage, crate READMEs - Regenerate insta welcome snapshots for v0.5.8 - Update pawan-api health endpoint version in README
TUI redesign + animate-core value tweens (v0.5.9)
chore: v0.5.9 version bump + docs update
Replaces the unmaintained `atty 0.2.14` crate with the stdlib `std::io::IsTerminal` trait (stable since Rust 1.70). Resolves RUSTSEC-2024-0375 (unmaintained) and RUSTSEC-2021-0145 (Windows unaligned read) for pawan-cli's direct dependency on `atty`.
**Changes**
- `crates/pawan-cli/src/main.rs`: 3 call sites switched from `atty::is(Stream::*)` to `std::io::{stdin,stderr}().is_terminal()` (one new `use std::io::IsTerminal;` import)
- `crates/pawan-cli/Cargo.toml`: drop `atty = "0.2.14"`
- `Cargo.lock`: atty and its transitive `hermit-abi` are no longer resolved
- `.cargo/audit.toml`: document accepted-risk suppressions for the 11 advisories (5 vulnerabilities + 6 unmaintained warnings) that remain in the lockfile but are out of reach or already patched
- `cargo fmt --all`: bring workspace into compliance with the current rustfmt (35 files, 446+/396-, no semantic changes)
- Refresh stale welcome-screen snapshot (v0.5.8 → v0.5.9) for the lib and bin targets
**Verification**
- `cargo check -p pawan`: clean
- `cargo test -p pawan`: 269/269 pass locally
- `cargo audit`: clean (0 advisories with the new `.cargo/audit.toml` suppressions)
- `cargo fmt --all -- --check`: clean
**Note on CI**
The 4 `test_render_welcome_snapshot` / `test_session_tags_persist_on_save` failures in CI are pre-existing on `main` (the welcome snapshot still has v0.5.8 but the code is v0.5.9, and `test_session_tags_persist_on_save` is environment-flaky on the session-dir path). The atty fix is unrelated to those failures. They should be addressed in a separate PR.
Closes #4 (RUSTSEC-2024-0375) and #13 (RUSTSEC-2021-0145) via auto-close on merge.
Adds RMUX-backed terminal workflow support, /rmux typed slash command, /model key-release fix, and PTY-backed TUI QA.
Bump workspace crates to v0.5.10 and finalize release notes after RMUX terminal workflow integration.
Adds RMUX live roundtrip testing, kill_session support, /rmux kill routing, and stricter RMUX validation/diagnostics.
Bump workspace crates to v0.5.11 and finalize release notes for RMUX hardening.
Render RMUX snapshot tool results as terminal-focused TUI cards and switch fixed TUI statics to LazyLock.
Bump workspace crates to v0.5.12 and finalize release notes for RMUX snapshot cards.
Adds rmux list_sessions support, /rmux list routing, live roundtrip list assertions, and docs.
Bump workspace crates to v0.5.13 and finalize release notes for RMUX session discovery.
Adds rmux list_panes support, /rmux panes routing, live pane inventory assertions, and docs.
Bump workspace crates to v0.5.14 and finalize release notes for RMUX pane discovery.
Renders rmux list_panes tool results as active-pane inventory cards while preserving generic tool rendering.
Bump workspace crates to v0.5.15 and finalize release notes for RMUX pane-list cards.
Renders rmux list_sessions tool results as active-session inventory cards while preserving other tool rendering.
Bump workspace crates to v0.5.16 and finalize release notes for RMUX session-list cards.
Renders rmux send, key, wait, and kill tool results as action-focused TUI cards.
Bump workspace crates to v0.5.17 and finalize release notes for RMUX status cards.
Bump workspace crates to v0.5.18 and finalize release notes for TUI slash-command hotfix.
Adds PTY-backed /tools smoke coverage for core and RMUX tools.
Bump workspace crates to v0.5.19 and finalize release notes for expanded headless slash-command smoke coverage.
Preserve fetched NVIDIA /v1/models catalogs when opening /model, and add live model-picker regression smoke coverage.
Bump workspace crates to v0.5.20 and finalize release notes for model picker live catalog preservation.
Adds weekly/manual regression smoke workflow and checklist tests for prior TUI/model regressions.
Bump workspace crates to v0.5.21 and finalize release notes for periodic regression smoke.
Track and render model picker catalog source metadata for fallback vs live NVIDIA catalogs.
…o changes' (#102) pawan review printed "No changes to review" and exited 0 whenever a git diff probe failed, because both probes in run_review read stdout only and never consulted output.status or stderr. Command::output() yields Ok whenever the process spawns, so a git that ran and failed (not a repo, dubious ownership, corrupt .git) produced empty stdout and was reported as "no changes" — and the fallback probe failed identically, reading as corroboration. Restructure run_review to call review_diff(), which classifies each probe into a tri-state DiffProbe (Found / Empty / NoHead / Failed): - git_diff_stdout now checks output.status and surfaces stderr. A non-zero exit is a probe failure, never evidence of an empty diff. - git diff HEAD exiting 128 with "ambiguous argument 'HEAD'" is the one legitimate failure (a repository with no commits) and is classified NoHead, treated as Empty, with the new git diff --cached probe covering staged work in that case (also fixes the fresh-repo gap behind #108). - Emptiness is reported only when every probe ran clean-empty; if any probe failed unexplained, the error is surfaced instead of a false "No changes to review." Regression tests cover: staged work in a fresh repo, clean repo, empty fresh repo (NoHead not an error), unstaged fallback, broken git surfaces an error, and the NoHead classifier.
Review: strongest of the three fail-open fixes — correct mechanism, real tests, red gate is pre-existing driftWhat the change does (main.rs +138/-45): extracts Addresses pawan#102? Yes, and it also subsumes the no-commit-repo false negative (#108) as a natural consequence — the staged probe finds staged work the HEAD probe cannot see. The probe-ordering note ( The tests are the real evidence. Five new tests with a scratch-repo fixture: (1) staged work in a no-commit repo is found — the #108 repro; (2) a genuinely clean repo reports nothing — the control, so the fix hasn't traded one wrong answer for another; (3) an empty fresh repo yields no diff, not an error — NoHead is not a hard failure; (4) unstaged work still found via the plain-diff fallback; (5) fault injection — CI: Check & Lint FAIL is the same pre-existing |
Amendments to my review (two measured corrections)Pre-existing lint — now measured, not inferred. Main's latest Check & Lint (run 27495472815, headSha de893a9, 2026-06-14) is green but predates the rust 1.99.0 promotion of Overlap/supersession with #105. #115 and #105 rewrite the same Scope note (per an earlier review concern): the completed-but-nonzero-exit path is correct — the unchanged parse logic reads stdout regardless of exit status ("exit code is non-zero when vulnerabilities are present, but stdout still contains the JSON"). One residual, out of #102's scope: Body should add |
…use (fix #116) rust 1.99.0 promoted clippy::double_must_use. async-trait 0.1.89 macro-generates a #[must_use] on the boxed future that the new lint reads as a redundant hand-written one — a macro-expansion false positive, fatal under CI's -D warnings. Four trait sites in pawan-core (LlmBackend, TaskRunner, PoolExecutor, Tool) failed Check & Lint on every open PR (#105/#113/#115) despite none touching those files. async-trait 0.1.92 stops emitting the redundant must_use, silencing the lint at the source. This matches the estate's own 1.99 migration (eruka moved 0.1.89 -> 0.1.92 in its fix stack). No source changes, no allows. Verified: cargo +1.99.0 clippy --workspace -- -D warnings -> clean rc=0; cargo +1.99.0 fmt --all -- --check -> clean. The floating-stable toolchain pin (rust-toolchain.toml, matching ares's 1.99.0) is separate drift infrastructure; left for a follow-up so this PR stays the minimal unblock.
|
Correction to my earlier note (which pointed at #117 — I've since closed that as a duplicate): the red Check & Lint here is not caused by this PR's diff. rust 1.99.0 promoted clippy::double_must_use, which false-fires on async-trait 0.1.89's macro-generated #[must_use] and is fatal under -D warnings — unchanged main was already red. The fix is the async-trait 0.1.89 -> 0.1.92 bump, which already exists as #94 (also #87, #92 — byte-identical Cargo.lock diffs). Once one of those lands, rebasing this PR should clear the red. |
4c00cd1 to
45e5da8
Compare
…use (fix #116) rust 1.99.0 promoted clippy::double_must_use. async-trait 0.1.89 macro-generates a #[must_use] on the boxed future that the new lint reads as a redundant hand-written one — a macro-expansion false positive, fatal under CI's -D warnings. Four trait sites in pawan-core (LlmBackend, TaskRunner, PoolExecutor, Tool) failed Check & Lint on every open PR (#105/#113/#115) despite none touching those files. async-trait 0.1.92 stops emitting the redundant must_use, silencing the lint at the source. This matches the estate's own 1.99 migration (eruka moved 0.1.89 -> 0.1.92 in its fix stack). No source changes, no allows. Verified: cargo +1.99.0 clippy --workspace -- -D warnings -> clean rc=0; cargo +1.99.0 fmt --all -- --check -> clean. The floating-stable toolchain pin (rust-toolchain.toml, matching ares's 1.99.0) is separate drift infrastructure; left for a follow-up so this PR stays the minimal unblock.
…f is never 'no changes' (closes #102) (#133) Extracted from the #115 head (which carried the real fix but was closed on a surface match): review_diff now probes staged + unstaged diffs via git_diff_stdout, which classifies each probe as Found/Empty/NoHead/Failed and CHECKS output.status.success() — so a failing `git diff` (bad ref, not-a-repo, bad pathspec, broken .git) surfaces PawanError::Git instead of printing 'No changes to review' (#102). NoHead (a repo with no commits) is the one legitimate failure and is treated as empty. 6 regression tests cover staged/unstaged/fresh-repo/clean/broken-git/no-head. Supersedes the simpler direct fix in #131. Verified: 5 review tests pass, cargo check clean. bkataru.
What this fixes
pawan reviewprinted "No changes to review" and exited 0 whenever agit diffprobe failed. Both probes inrun_reviewread stdout only and never consultedoutput.statusorstderr.Command::output()yieldsOkwhenever the process spawns, so a git that ran and failed (not a repo, dubious ownership, corrupt.git) produced empty stdout and was reported as "no changes" — and the fallback probe failed identically, reading as corroboration.Closes #102. Also closes the fresh-repo gap behind #108 (a staged first commit in a repo with no commits was invisible to both probes).
How
run_reviewnow callsreview_diff(), which classifies each probe into a tri-stateDiffProbe(Found/Empty/NoHead/Failed):git_diff_stdoutchecksoutput.statusand surfacesstderr. A non-zero exit is a probe failure, never evidence of an empty diff.git diff HEADexiting 128 with "ambiguous argument 'HEAD'" is classifiedNoHead— the one legitimate failure (a repository with no commits) — treated asEmpty, with the newgit diff --cachedprobe covering staged work in that case.PawanError::Gitinstead of a false "No changes to review."Relationship to #105 and #111
This supersedes both for #102:
checked_git_stdout) surfaces probe failures — covers pawan review prints "No changes to review" and exits 0 when git diff fails (same shape as #98) #102's call sites — but does not add the fresh-repo--cachedprobe.git diff --cached) covers the fresh-repo case but itsgit_diff_stdoutstill ignoresoutput.status/stderr, so it does not fix pawan review prints "No changes to review" and exits 0 when git diff fails (same shape as #98) #102 (its own docstring defers that to pawan commit reports "working tree clean" and exits 0 when the git probe fails (fails open) #98/pawan review prints "No changes to review" and exits 0 when git diff fails (same shape as #98) #102).review_diff(commit-sequenced merge produces conflict markers), and merging fix(review): staged work in a fresh repo must not read as 'no changes' #111 orphans fix(pawan): surface git probe failures instead of failing open (#98, #102) #105'schecked_git_stdoutaway fromrun_review.This branch combines both intents so neither is lost. Happy to reconcile differently if the owners of #105/#111 prefer.
Verification
cargo check -p pawancargo fmt -p pawan --checkcargo clippy -p pawan --all-targetscargo test -p pawan --bin pawanMutation proof: reverting
git_diff_stdout's failure branch toEmpty(the pre-fix shape, proven present by grep before running) makes the broken-git test fail on exactly the defect assertion — "a broken git must surface as an error, not 'no changes'" (rc=101). The test has teeth.Six regression tests: staged work in a fresh repo (#108), clean repo, empty fresh repo (NoHead is not an error), unstaged fallback, broken git surfaces an error (#102), and the NoHead classifier.