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

@@ -41,9 +41,7 @@
use std::io::{BufRead, BufReader};
use std::time::Duration;
use kebab_core::{
FinishReason, GenerateRequest, LanguageModel, ModelRef, TokenChunk, TokenUsage,
};
use kebab_core::{FinishReason, GenerateRequest, LanguageModel, ModelRef, TokenChunk, TokenUsage};
use serde::{Deserialize, Serialize};
use crate::error::LlmError;
@@ -346,9 +344,9 @@ impl Iterator for OllamaStream {
// misrouted reverse proxy returning 200). Per §10
// error taxonomy this is `Stream`, not
// `Malformed`.
return Some(Err(anyhow::Error::from(LlmError::Stream(
truncate_body(&preview, 512),
))));
return Some(Err(anyhow::Error::from(LlmError::Stream(truncate_body(
&preview, 512,
)))));
}
// Mid-stream corruption — earlier lines parsed, this
// one didn't. That's `Malformed`.
@@ -364,9 +362,9 @@ impl Iterator for OllamaStream {
// Server-side error envelope on a 200 stream.
if let Some(err) = line.error {
self.done = true;
return Some(Err(anyhow::Error::from(LlmError::Stream(
truncate_body(&err, 512),
))));
return Some(Err(anyhow::Error::from(LlmError::Stream(truncate_body(
&err, 512,
)))));
}
if line.done {
@@ -451,11 +449,7 @@ fn map_send_error(err: reqwest::Error, endpoint: &str) -> LlmError {
/// Map a non-2xx HTTP response to an [`LlmError`]. Pattern-matches on the
/// 404 + "model" / "not found" body envelope to surface the actionable
/// `ollama pull <model>` hint.
fn map_status_error(
status: reqwest::StatusCode,
body: &str,
model_id: &str,
) -> LlmError {
fn map_status_error(status: reqwest::StatusCode, body: &str, model_id: &str) -> LlmError {
if status == reqwest::StatusCode::NOT_FOUND {
let lower = body.to_ascii_lowercase();
// Heuristic: Ollama's "model not pulled" envelope is roughly
@@ -473,10 +467,7 @@ fn map_status_error(
return LlmError::ModelNotPulled(model_id.to_string());
}
}
LlmError::Stream(truncate_body(
&format!("status={status} body={body}"),
512,
))
LlmError::Stream(truncate_body(&format!("status={status} body={body}"), 512))
}
/// Truncate a body / error string to `n` characters, appending an
@@ -491,7 +482,10 @@ fn truncate_body(s: &str, n: usize) -> String {
return s.to_string();
}
let mut out: String = s.chars().take(n).collect();
out.push_str(&format!("... (truncated, original {} chars)", s.chars().count()));
out.push_str(&format!(
"... (truncated, original {} chars)",
s.chars().count()
));
out
}
@@ -512,11 +506,7 @@ mod tests {
#[test]
fn map_status_error_404_with_model_not_found_returns_not_pulled() {
let body = r#"{"error":"model 'qwen2.5:7b-instruct' not found, try pulling it first"}"#;
let err = map_status_error(
reqwest::StatusCode::NOT_FOUND,
body,
"qwen2.5:7b-instruct",
);
let err = map_status_error(reqwest::StatusCode::NOT_FOUND, body, "qwen2.5:7b-instruct");
match err {
LlmError::ModelNotPulled(m) => assert_eq!(m, "qwen2.5:7b-instruct"),
other => panic!("expected ModelNotPulled, got {other:?}"),
@@ -540,11 +530,7 @@ mod tests {
// The English "not found" substring is absent, but the model id
// is echoed — heuristic should still route to ModelNotPulled.
let body = r#"{"error":"모델 'qwen2.5:7b-instruct' 을(를) 찾을 수 없습니다"}"#;
let err = map_status_error(
reqwest::StatusCode::NOT_FOUND,
body,
"qwen2.5:7b-instruct",
);
let err = map_status_error(reqwest::StatusCode::NOT_FOUND, body, "qwen2.5:7b-instruct");
assert!(
matches!(err, LlmError::ModelNotPulled(ref m) if m == "qwen2.5:7b-instruct"),
"expected ModelNotPulled for localized 404 body, got {err:?}",

View File

@@ -41,10 +41,7 @@ fn sample_request() -> GenerateRequest {
/// Helper: drive `generate_stream` to completion on a blocking thread so
/// the sync `OllamaLanguageModel` stays off the async runtime.
async fn collect_chunks(
cfg: Config,
req: GenerateRequest,
) -> anyhow::Result<Vec<TokenChunk>> {
async fn collect_chunks(cfg: Config, req: GenerateRequest) -> anyhow::Result<Vec<TokenChunk>> {
tokio::task::spawn_blocking(move || -> anyhow::Result<Vec<TokenChunk>> {
let llm = OllamaLanguageModel::new(&cfg)?;
let stream = llm.generate_stream(req)?;
@@ -58,10 +55,7 @@ async fn collect_chunks(
/// `generate_stream` itself (rather than a stream-mid error). Used by the
/// "unreachable endpoint" / "model not pulled" tests where the error
/// surfaces on `.send()` before any chunks flow.
async fn run_expecting_request_error(
cfg: Config,
req: GenerateRequest,
) -> anyhow::Error {
async fn run_expecting_request_error(cfg: Config, req: GenerateRequest) -> anyhow::Error {
tokio::task::spawn_blocking(move || -> anyhow::Result<()> {
let llm = OllamaLanguageModel::new(&cfg)?;
let _stream = llm.generate_stream(req)?;
@@ -78,9 +72,12 @@ async fn run_expecting_request_error(
async fn streamed_response_produces_tokens_then_done() {
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"hi","done":false}"#, "\n",
r#"{"response":" there","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":3,"eval_count":2,"total_duration":1500000}"#, "\n",
r#"{"response":"hi","done":false}"#,
"\n",
r#"{"response":" there","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":3,"eval_count":2,"total_duration":1500000}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -96,7 +93,10 @@ async fn streamed_response_produces_tokens_then_done() {
assert!(matches!(&chunks[0], TokenChunk::Token(t) if t == "hi"));
assert!(matches!(&chunks[1], TokenChunk::Token(t) if t == " there"));
match &chunks[2] {
TokenChunk::Done { finish_reason, usage } => {
TokenChunk::Done {
finish_reason,
usage,
} => {
assert!(matches!(finish_reason, FinishReason::Stop));
assert_eq!(usage.prompt_tokens, 3);
assert_eq!(usage.completion_tokens, 2);
@@ -155,10 +155,13 @@ async fn multibyte_chars_within_a_line_round_trip() {
let server = MockServer::start().await;
let body = concat!(
// "한국어" (Korean) — each char is 3 bytes in UTF-8.
r#"{"response":"한국어","done":false}"#, "\n",
r#"{"response":"한국어","done":false}"#,
"\n",
// Followed by an emoji ZWJ sequence (4 bytes per scalar).
r#"{"response":"🦀","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":4,"total_duration":0}"#, "\n",
r#"{"response":"🦀","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":4,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -257,8 +260,10 @@ async fn other_4xx_maps_to_stream_error() {
async fn done_reason_length_maps_to_finish_reason_length() {
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"a","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"length","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#, "\n",
r#"{"response":"a","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"length","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -281,8 +286,10 @@ async fn done_reason_length_maps_to_finish_reason_length() {
async fn done_reason_abort_maps_to_finish_reason_aborted() {
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"a","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"abort","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#, "\n",
r#"{"response":"a","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"abort","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -312,9 +319,11 @@ async fn missing_eval_counts_default_to_zero() {
// here — the comment documents the intent.
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"hi","done":false}"#, "\n",
r#"{"response":"hi","done":false}"#,
"\n",
// No prompt_eval_count / eval_count / total_duration.
r#"{"response":"","done":true,"done_reason":"stop"}"#, "\n",
r#"{"response":"","done":true,"done_reason":"stop"}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -339,9 +348,11 @@ async fn missing_eval_counts_default_to_zero() {
async fn missing_done_reason_defaults_to_stop() {
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"hi","done":false}"#, "\n",
r#"{"response":"hi","done":false}"#,
"\n",
// Final frame omits done_reason entirely.
r#"{"response":"","done":true,"prompt_eval_count":1,"eval_count":1,"total_duration":0}"#, "\n",
r#"{"response":"","done":true,"prompt_eval_count":1,"eval_count":1,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -406,8 +417,10 @@ async fn endpoint_with_trailing_slash_does_not_double_slash() {
// fail the assertion.
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"ok","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#, "\n",
r#"{"response":"ok","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))
@@ -451,8 +464,10 @@ async fn determinism_seed_zero_temp_zero_two_runs_identical() {
// (#[ignore]) where reproducibility is modulo model-internal nondet.
let server = MockServer::start().await;
let body = concat!(
r#"{"response":"deterministic","done":false}"#, "\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#, "\n",
r#"{"response":"deterministic","done":false}"#,
"\n",
r#"{"response":"","done":true,"done_reason":"stop","prompt_eval_count":1,"eval_count":1,"total_duration":0}"#,
"\n",
);
Mock::given(method("POST"))
.and(path("/api/generate"))