feat(fb-26,fb-28): ingest log consistency + --readonly/--quiet flags + schema sync #113

Merged
altair823 merged 10 commits from feat/p9-fb-26-fb-28-agent-ux into main 2026-05-07 12:09:06 +00:00
Owner

요약

세 독립 변경을 한 PR로 묶었습니다.

§1 CLAUDE.md wire schema 목록 정리

  • 존재하지 않는 eval_run.v1, eval_compare.v1, list_docs.v1 제거
  • 누락된 chunk_inspection.v1, citation.v1, doc_summary.v1 추가

§2 fb-26: ingest 로그 출력 일관성 (progress.rs)

  • 버그 수정: Aborted arm의 writeln! 이 TTY 모드에서도 무조건 발사 → if !tty && !quiet 가드 추가
  • 버그 수정: Completed TTY path에서 bar.finish_and_clear() 후 summary 없음 → !quiet 시 항상 summary writeln 추가
  • ProgressMode::Human { tty, quiet }quiet 필드 추가
  • from_flags(json, quiet, plain_env)KEBAB_PROGRESS=plain env override (CI pty wrapper 대응)

§3 fb-28: agent invocation flags (main.rs)

  • --readonly 글로벌 플래그 (KEBAB_READONLY=1 env 동치): ingest, ingest-file, ingest-stdin, reset 차단 → exit 1 + plain error / error.v1 (json 모드)
  • --quiet 글로벌 플래그: 모든 human-readable stderr progress/hint 억제. error는 여전히 stderr.
  • --json 은 auto-quiet (기존 동작 명시화)
  • is_mutating() 헬퍼 + readonly guard block in main()
  • parse_bool_env value parser (1/true/yes/on truthy 지원)

테스트 계획

  • cli_readonly_quiet.rs — 8개 통합 테스트 (readonly flag/env, json error.v1, quiet suppression)
  • ingest_progress_cli.rsKEBAB_PROGRESS=plain 동작 확인
  • 전체 kebab-cli suite: 37 tests, all pass

관련 태스크

  • tasks/p9/p9-fb-26-ingest-log-consistency.mdstatus: merged
  • tasks/p9/p9-fb-28-agent-invocation-flags.mdstatus: merged
## 요약 세 독립 변경을 한 PR로 묶었습니다. ### §1 CLAUDE.md wire schema 목록 정리 - 존재하지 않는 `eval_run.v1`, `eval_compare.v1`, `list_docs.v1` 제거 - 누락된 `chunk_inspection.v1`, `citation.v1`, `doc_summary.v1` 추가 ### §2 fb-26: ingest 로그 출력 일관성 (`progress.rs`) - **버그 수정**: `Aborted` arm의 `writeln!` 이 TTY 모드에서도 무조건 발사 → `if !tty && !quiet` 가드 추가 - **버그 수정**: `Completed` TTY path에서 `bar.finish_and_clear()` 후 summary 없음 → `!quiet` 시 항상 summary writeln 추가 - `ProgressMode::Human { tty, quiet }` — `quiet` 필드 추가 - `from_flags(json, quiet, plain_env)` — `KEBAB_PROGRESS=plain` env override (CI pty wrapper 대응) ### §3 fb-28: agent invocation flags (`main.rs`) - `--readonly` 글로벌 플래그 (`KEBAB_READONLY=1` env 동치): `ingest`, `ingest-file`, `ingest-stdin`, `reset` 차단 → exit 1 + plain error / `error.v1` (json 모드) - `--quiet` 글로벌 플래그: 모든 human-readable stderr progress/hint 억제. error는 여전히 stderr. - `--json` 은 auto-quiet (기존 동작 명시화) - `is_mutating()` 헬퍼 + readonly guard block in `main()` - `parse_bool_env` value parser (`1`/`true`/`yes`/`on` truthy 지원) ## 테스트 계획 - [ ] `cli_readonly_quiet.rs` — 8개 통합 테스트 (readonly flag/env, json error.v1, quiet suppression) - [ ] `ingest_progress_cli.rs` — `KEBAB_PROGRESS=plain` 동작 확인 - [ ] 전체 kebab-cli suite: 37 tests, all pass ## 관련 태스크 - `tasks/p9/p9-fb-26-ingest-log-consistency.md` → `status: merged` - `tasks/p9/p9-fb-28-agent-invocation-flags.md` → `status: merged`
altair823 added 9 commits 2026-05-07 11:46:24 +00:00
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add `quiet: bool` to `Human` variant and expand `from_flags` to three
args (`json`, `quiet`, `plain_env`). Update `handle`/`handle_human`
accordingly; add four targeted unit tests (TDD).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add readonly/quiet fields to Cli, parse_bool_env for 1/true/yes/on support,
is_mutating guard that short-circuits with error.v1 on write-path commands,
and wire KEBAB_PROGRESS=plain through from_flags in the Ingest arm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fb-26 (progress.rs): Fixed Aborted unconditional writeln (TTY duplicate output)
  and Completed TTY path missing summary line. Added KEBAB_PROGRESS=plain env
  override and quiet field to ProgressMode.
- fb-28 (main.rs): Added --readonly / --quiet global flags with KEBAB_READONLY env.
  Readonly blocks mutating commands (ingest/ingest-file/ingest-stdin/reset) with
  exit code 1; error.v1 code "readonly_mode" in --json mode. Quiet suppresses all
  human progress/hint stderr while preserving errors.
- Updated task spec status for p9-fb-26 and p9-fb-28 to 'merged'.
- Updated tasks/INDEX.md and HANDOFF.md with merge status and summary entries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-07 11:47:13 +00:00
claude-reviewer-01 left a comment
Member

회차 1 — spec 전체 항목 충족, 37개 테스트 통과, Clippy 경고 없음. APPROVE.

회차 1 — spec 전체 항목 충족, 37개 테스트 통과, Clippy 경고 없음. APPROVE.
@@ -299,1 +319,4 @@
let _log_guard = kebab_app::logging::init(level).ok();
if cli.readonly && is_mutating(&cli.command) {
let msg = "kebab: readonly mode — mutating commands are disabled";
if cli.json {

[nit — pre-existing] proceed without a guard rather than crashing — \kb` is still usable.kb잔존. 모듈 doc comment 는 이번 PR 에서 수정됐는데 이 인라인 주석은 놓침. 다음kbsweep 때kebab` 로 정정 권장.

**[nit — pre-existing]** `proceed without a guard rather than crashing — \`kb\` is still usable.` 에 `kb` 잔존. 모듈 doc comment 는 이번 PR 에서 수정됐는데 이 인라인 주석은 놓침. 다음 `kb` sweep 때 `kebab` 로 정정 권장.
altair823 added 1 commit 2026-05-07 11:52:42 +00:00
claude-reviewer-01 approved these changes 2026-05-07 11:54:32 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 지적 (잔여 kb 참조 3건: session ID 예시, logging init 코멘트, init hint 출력) 모두 반영. 추가 actionable 지적 없음. 37개 테스트 통과, Clippy 경고 없음. APPROVE.

회차 2 — 회차 1 지적 (잔여 `kb` 참조 3건: session ID 예시, logging init 코멘트, init hint 출력) 모두 반영. 추가 actionable 지적 없음. 37개 테스트 통과, Clippy 경고 없음. APPROVE.
@@ -287,1 +297,4 @@
/// Parse boolean env var accepting "1", "true", "yes", "on" (case-insensitive)
/// as truthy; "0", "false", "no", "off" as falsy. Used for `KEBAB_READONLY`.
fn parse_bool_env(s: &str) -> Result<bool, String> {

[칭찬] parse_bool_env custom value parser — clap 기본 bool env 처리는 "true"/"false" 만 허용하지만, KEBAB_READONLY=1 관용을 지원하려면 이 커스텀 파서가 필요하다. 선택이 맞다.

**[칭찬]** `parse_bool_env` custom value parser — clap 기본 bool env 처리는 `"true"`/`"false"` 만 허용하지만, `KEBAB_READONLY=1` 관용을 지원하려면 이 커스텀 파서가 필요하다. 선택이 맞다.
@@ -857,6 +904,13 @@ fn print_schema_text(s: &kebab_app::SchemaV1) {
println!(" last_ingest_at {last}");
}
fn is_mutating(cmd: &Cmd) -> bool {

[칭찬] is_mutatingmatches! 패턴에 _ 폴백이 없다 — 새 mutating subcommand 추가 시 컴파일 에러로 guard 업데이트를 강제한다. 안전한 설계.

**[칭찬]** `is_mutating` 의 `matches!` 패턴에 `_` 폴백이 없다 — 새 mutating subcommand 추가 시 컴파일 에러로 guard 업데이트를 강제한다. 안전한 설계.
@@ -155,3 +161,3 @@
bar.finish_and_clear();
}
if !tty {
// Always emit summary in both TTY and non-TTY (unless quiet).

[칭찬] Completed fix — !tty 제거하고 !quiet 로 교체한 것이 맞다. TTY/non-TTY 양쪽에서 summary 한 줄이 항상 나와야 하고, quiet 만이 억제 조건이어야 한다.

**[칭찬]** `Completed` fix — `!tty` 제거하고 `!quiet` 로 교체한 것이 맞다. TTY/non-TTY 양쪽에서 summary 한 줄이 항상 나와야 하고, quiet 만이 억제 조건이어야 한다.

[칭찬] from_flags_quiet_sets_quiet_field + from_flags_plain_env_forces_tty_false — 두 신규 파라미터마다 각각 전용 단위 테스트를 추가한 것이 깔끔하다.

**[칭찬]** `from_flags_quiet_sets_quiet_field` + `from_flags_plain_env_forces_tty_false` — 두 신규 파라미터마다 각각 전용 단위 테스트를 추가한 것이 깔끔하다.
@@ -0,0 +108,4 @@
assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}
#[test]

[칭찬] readonly_json_mode_emits_error_v1schema_versioncode 를 분리해서 assertion 한다 — exit code 만 확인하는 것보다 wire contract 를 훨씬 단단하게 잡는다.

**[칭찬]** `readonly_json_mode_emits_error_v1` 가 `schema_version` 과 `code` 를 분리해서 assertion 한다 — exit code 만 확인하는 것보다 wire contract 를 훨씬 단단하게 잡는다.
altair823 merged commit fea91d5c99 into main 2026-05-07 12:09:06 +00:00
altair823 deleted branch feat/p9-fb-26-fb-28-agent-ux 2026-05-07 12:09:08 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#113