From b230fbb4951e9c27d32e9e717874e7decc192e51 Mon Sep 17 00:00:00 2001
From: th-kim0823
Date: Thu, 7 May 2026 19:58:56 +0900
Subject: [PATCH] =?UTF-8?q?fix:=20apply=20review=20nits=20=E2=80=94=20kb?=
=?UTF-8?q?=E2=86=92kebab=20comment,=20quiet=20reset=20guard,=20ingest-std?=
=?UTF-8?q?in=20readonly=20test,=20README+SMOKE=20docs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Sonnet 4.6
---
README.md | 2 ++
crates/kebab-cli/src/main.rs | 6 ++++--
crates/kebab-cli/tests/cli_readonly_quiet.rs | 16 ++++++++++++++++
docs/SMOKE.md | 2 +-
4 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index de5dabf..c19e8b7 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,8 @@ kebab doctor
모든 명령에 `--json` 플래그. 출력은 frozen wire schema v1 (`schema_version` 항상 포함, 예: `ingest_report.v1`, `ingest_progress.v1`, `search_hit.v1`, `answer.v1`, `doctor.v1`, `reset_report.v1`, `schema.v1`). `--json` 모드에서 fatal error 는 stderr 에 `error.v1` ndjson 으로 emit (exit code 0/1/2/3 unchanged).
+글로벌 플래그: `--readonly` (또는 `KEBAB_READONLY=1`) — 모든 write-path 명령 (`ingest` / `ingest-file` / `ingest-stdin` / `reset`) 을 비활성화, exit 1. `--quiet` — 진행 바 / hint 등 human-readable stderr 억제 (exit code / stdout 출력은 그대로). `KEBAB_PROGRESS=plain` — TTY 가 없는 환경에서도 진행 상황을 plain-text 한 줄씩 stderr 로 출력 (spinner 대신).
+
## 논리 아키텍처
```mermaid
diff --git a/crates/kebab-cli/src/main.rs b/crates/kebab-cli/src/main.rs
index f7ad9af..7832485 100644
--- a/crates/kebab-cli/src/main.rs
+++ b/crates/kebab-cli/src/main.rs
@@ -1,4 +1,4 @@
-//! `kb` — command-line interface. Each subcommand maps 1:1 to a `kb-app`
+//! `kebab` — command-line interface. Each subcommand maps 1:1 to a `kebab-app`
//! function. Exit codes per design §10.
use std::path::PathBuf;
@@ -659,7 +659,9 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
);
}
if !confirm_destructive(scope, &paths, bytes)? {
- eprintln!("aborted.");
+ if !cli.quiet {
+ eprintln!("aborted.");
+ }
return Ok(());
}
}
diff --git a/crates/kebab-cli/tests/cli_readonly_quiet.rs b/crates/kebab-cli/tests/cli_readonly_quiet.rs
index 2e5ac6d..26ab305 100644
--- a/crates/kebab-cli/tests/cli_readonly_quiet.rs
+++ b/crates/kebab-cli/tests/cli_readonly_quiet.rs
@@ -63,6 +63,22 @@ fn readonly_flag_blocks_ingest_file() {
assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}
+#[test]
+fn readonly_flag_blocks_ingest_stdin() {
+ let (tmp, _ws) = fixture_workspace();
+ let out = Command::new(kebab_bin())
+ .args(["--readonly", "ingest-stdin", "--title", "test"])
+ .env("KEBAB_READONLY", "1")
+ .envs(xdg_envs(tmp.path()))
+ .stdin(std::process::Stdio::null())
+ .output()
+ .unwrap();
+
+ assert_eq!(out.status.code(), Some(1), "expected exit 1");
+ let stderr = String::from_utf8_lossy(&out.stderr);
+ assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
+}
+
#[test]
fn readonly_flag_blocks_reset() {
let (tmp, _ws) = fixture_workspace();
diff --git a/docs/SMOKE.md b/docs/SMOKE.md
index 84af2bd..43bd6ef 100644
--- a/docs/SMOKE.md
+++ b/docs/SMOKE.md
@@ -114,7 +114,7 @@ max_context_tokens = 6000
theme = "dark" # p9-fb-14 — TUI palette ("dark" / "light", default "dark")
```
-`KEBAB_*` 환경변수로 override 가능 (`KEBAB_MODELS_LLM_MODEL=gemma4:26b kebab …` 등). 자세한 키 목록은 `crates/kebab-config/src/lib.rs` 의 `apply_env` 매치 암.
+`KEBAB_*` 환경변수로 override 가능 (`KEBAB_MODELS_LLM_MODEL=gemma4:26b kebab …` 등). 자세한 키 목록은 `crates/kebab-config/src/lib.rs` 의 `apply_env` 매치 암. `KEBAB_READONLY=1` — write-path 비활성화 (CI 안전망). `KEBAB_PROGRESS=plain` — non-TTY 환경에서 진행 상황을 plain 한 줄씩 stderr 출력 (spinner 대신).
## 명령 시퀀스