style: cargo fmt --all (round 4 ingest log feature follow-up)

Phase C4 executor 의 마지막 `fix(test): clippy + fmt fixes` commit 이
test file 부분만 fmt 적용. workspace 전체 fmt 누락 발견 → cargo fmt --all
적용. 모든 import alphabetical reorder + line wrapping 정합.

추가 untracked artifact 동시 commit:
- docs/superpowers/specs/2026-05-28-v0.20-ingest-log-spec.md (491 line, ACCEPT)
- docs/superpowers/plans/2026-05-28-v0.20-ingest-log-plan.md (616 line, ACCEPT)

workspace test: 1370 passed / 0 failed / 50 ignored, ingest_log_smoke green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 04:18:40 +00:00
parent 445b096215
commit 685007789a
235 changed files with 6520 additions and 3955 deletions

View File

@@ -7,9 +7,8 @@
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use kebab_config::Config;
use kebab_core::{
Answer, AnswerCitation, AnswerRetrievalSummary, Citation, ModelRef,
PromptTemplateVersion, RefusalReason, SearchMode, TokenUsage, TraceId, Turn,
WorkspacePath,
Answer, AnswerCitation, AnswerRetrievalSummary, Citation, ModelRef, PromptTemplateVersion,
RefusalReason, SearchMode, TokenUsage, TraceId, Turn, WorkspacePath,
};
use kebab_tui::{App, AskState, KeyOutcome, Pane, handle_key_ask, render_ask};
use ratatui::Terminal;
@@ -90,10 +89,7 @@ fn esc_returns_to_library_and_clears_streaming() {
s.streaming = true;
s.partial = "partial answer…".into();
}
let outcome = handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE),
);
let outcome = handle_key_ask(&mut app, KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE));
assert_eq!(outcome, KeyOutcome::SwitchPane(Pane::Library));
let s = app.ask.as_ref().unwrap();
assert!(!s.streaming);
@@ -155,12 +151,20 @@ fn jk_scroll_in_normal_mode_type_in_insert() {
&mut app,
KeyEvent::new(KeyCode::Char('j'), KeyModifiers::NONE),
);
assert_eq!(app.ask.as_ref().unwrap().scroll, 1, "j scrolls down in Normal");
assert_eq!(
app.ask.as_ref().unwrap().scroll,
1,
"j scrolls down in Normal"
);
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('k'), KeyModifiers::NONE),
);
assert_eq!(app.ask.as_ref().unwrap().scroll, 0, "k scrolls up in Normal");
assert_eq!(
app.ask.as_ref().unwrap().scroll,
0,
"k scrolls up in Normal"
);
// Now Insert — j/k type.
app.mode = kebab_tui::Mode::Insert;
handle_key_ask(
@@ -213,10 +217,7 @@ fn e_typed_into_input_when_input_nonempty() {
#[test]
fn enter_with_empty_input_is_continue() {
let mut app = fresh_app();
let outcome = handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE),
);
let outcome = handle_key_ask(&mut app, KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
assert_eq!(outcome, KeyOutcome::Continue);
assert!(!app.ask.as_ref().unwrap().streaming);
}
@@ -229,10 +230,7 @@ fn enter_while_streaming_is_noop() {
s.input.push_str("anything");
s.streaming = true;
}
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE),
);
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
// streaming flag remains true (no new worker spawned)
assert!(app.ask.as_ref().unwrap().streaming);
// No thread spawned because enter was a no-op.
@@ -335,7 +333,10 @@ fn render_grounded_answer_with_citation() {
})
.collect::<Vec<_>>()
.join("\n");
assert!(rendered.contains("test answer body"), "answer body rendered");
assert!(
rendered.contains("test answer body"),
"answer body rendered"
);
assert!(rendered.contains("grounded ✓"), "grounded status visible");
assert!(rendered.contains("notes/foo.md"), "citation path rendered");
assert!(rendered.contains("[1]"), "citation marker rendered");
@@ -346,7 +347,11 @@ fn render_refusal_score_gate_shows_status_without_citation_index_panic() {
let mut app = fresh_app();
{
let s = app.ask.as_mut().unwrap();
let mut ans = make_answer(false, Some(RefusalReason::ScoreGate), "insufficient grounding to answer.");
let mut ans = make_answer(
false,
Some(RefusalReason::ScoreGate),
"insufficient grounding to answer.",
);
ans.citations.clear(); // refusal often has no citations
s.turns.push(Turn {
question: "test refusal question".into(),
@@ -374,7 +379,10 @@ fn render_refusal_score_gate_shows_status_without_citation_index_panic() {
})
.collect::<Vec<_>>()
.join("\n");
assert!(rendered.contains("insufficient grounding"), "refusal body rendered");
assert!(
rendered.contains("insufficient grounding"),
"refusal body rendered"
);
assert!(rendered.contains("grounded ✗"), "ungrounded status visible");
assert!(rendered.contains("score_gate"), "refusal reason surfaced");
}
@@ -535,10 +543,7 @@ fn enter_with_detached_prior_thread_is_blocked() {
}
}));
}
let outcome = handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE),
);
let outcome = handle_key_ask(&mut app, KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
// Enter is a no-op while a prior thread is attached.
assert_eq!(outcome, KeyOutcome::Continue);
let s = app.ask.as_ref().unwrap();
@@ -693,7 +698,10 @@ fn render_transcript_shows_completed_turns_in_order() {
assert!(q1_pos < q2_pos, "chronological order: Q1 before Q2");
assert!(rendered.contains("first question"), "first question text");
assert!(rendered.contains("second answer"), "second answer text");
assert!(rendered.contains("transcript (2 turns)"), "title shows count");
assert!(
rendered.contains("transcript (2 turns)"),
"title shows count"
);
}
#[test]
@@ -772,10 +780,16 @@ fn left_arrow_then_typing_inserts_at_cursor_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Insert;
for ch in "abc".chars() {
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE),
);
}
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('X'), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('X'), KeyModifiers::NONE),
);
let s = app.ask.as_ref().unwrap();
assert_eq!(s.input.as_str(), "abXc", "X inserts before c, not at end");
assert_eq!(s.input.cursor_col(), 3, "cursor sits between X and c");
@@ -787,7 +801,10 @@ fn left_arrow_then_typing_inserts_at_cursor_in_ask() {
fn right_arrow_at_end_is_noop_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Insert;
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE),
);
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Right, KeyModifiers::NONE));
let s = app.ask.as_ref().unwrap();
assert_eq!(s.input.cursor_col(), 1);
@@ -800,7 +817,10 @@ fn home_end_jump_cursor_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Insert;
for ch in "hello".chars() {
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE),
);
}
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Home, KeyModifiers::NONE));
assert_eq!(app.ask.as_ref().unwrap().input.cursor_col(), 0);
@@ -815,7 +835,10 @@ fn delete_key_removes_char_at_cursor_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Insert;
for ch in "abc".chars() {
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE),
);
}
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Home, KeyModifiers::NONE));
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE));
@@ -831,14 +854,20 @@ fn hangul_left_arrow_rewinds_by_two_cols_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Insert;
for ch in "한글".chars() {
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE),
);
}
assert_eq!(app.ask.as_ref().unwrap().input.cursor_col(), 4);
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Left, KeyModifiers::NONE));
assert_eq!(app.ask.as_ref().unwrap().input.cursor_col(), 2);
// Inserting at the new cursor position lands between the two
// syllables, proving cursor_col is not just a display annotation.
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('X'), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('X'), KeyModifiers::NONE),
);
assert_eq!(app.ask.as_ref().unwrap().input.as_str(), "한X글");
}
@@ -859,7 +888,10 @@ fn ask_state_default_follow_tail_is_true() {
fn k_disengages_follow_tail_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Normal;
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('k'), KeyModifiers::NONE));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('k'), KeyModifiers::NONE),
);
assert!(!app.ask.as_ref().unwrap().follow_tail);
}
@@ -875,7 +907,10 @@ fn shift_g_re_engages_follow_tail_in_ask() {
s.follow_tail = false;
s.scroll = 7;
}
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('G'), KeyModifiers::SHIFT));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('G'), KeyModifiers::SHIFT),
);
let s = app.ask.as_ref().unwrap();
assert!(s.follow_tail, "Shift-G re-engages follow-tail");
assert_eq!(s.scroll, 0, "scroll cleared (renderer recomputes)");
@@ -888,7 +923,10 @@ fn ctrl_l_resets_follow_tail_in_ask() {
let mut app = fresh_app();
app.mode = kebab_tui::Mode::Normal;
app.ask.as_mut().unwrap().follow_tail = false;
handle_key_ask(&mut app, KeyEvent::new(KeyCode::Char('l'), KeyModifiers::CONTROL));
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::Char('l'), KeyModifiers::CONTROL),
);
assert!(app.ask.as_ref().unwrap().follow_tail);
}
@@ -917,18 +955,12 @@ fn page_up_rewinds_scroll_saturating_and_freezes_follow_tail_in_ask() {
app.mode = kebab_tui::Mode::Normal;
app.ask.as_mut().unwrap().scroll = 25;
app.ask.as_mut().unwrap().follow_tail = true;
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::PageUp, KeyModifiers::NONE),
);
handle_key_ask(&mut app, KeyEvent::new(KeyCode::PageUp, KeyModifiers::NONE));
let s = app.ask.as_ref().unwrap();
assert_eq!(s.scroll, 15);
assert!(!s.follow_tail);
app.ask.as_mut().unwrap().scroll = 3;
handle_key_ask(
&mut app,
KeyEvent::new(KeyCode::PageUp, KeyModifiers::NONE),
);
handle_key_ask(&mut app, KeyEvent::new(KeyCode::PageUp, KeyModifiers::NONE));
assert_eq!(app.ask.as_ref().unwrap().scroll, 0);
}
@@ -1173,7 +1205,6 @@ fn ask_state_multi_hop_field_default_false_and_round_trips() {
assert!(!s.multi_hop, "settable back to false");
}
/// Small render helper shared with the rest of the test module's
/// buffer-snapshot pattern. We define it locally here to avoid
/// reaching into private internals.