fix(core): P87 — Windows .cmd 래퍼 CLI spawn 실패 (#92)#96
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the which crate to resolve command paths on Windows, fixing an issue where npm-installed CLI wrappers (like codex.cmd and claude.cmd) fail to spawn due to missing PATHEXT resolution. It adds a resolve_program helper and updates command execution sites to use it. The reviewer suggested optimizing performance in wiki/reviewers/codex.rs and wiki/reviewers/claude.rs by moving the resolve_program calls outside of the for strict in [false, true] loops to avoid redundant disk I/O operations.
| let output_path = output_file.path().to_path_buf(); | ||
|
|
||
| let mut child = tokio::process::Command::new("codex"); | ||
| let mut child = tokio::process::Command::new(crate::resolve_program("codex")); |
There was a problem hiding this comment.
for strict in [false, true] 루프 내부에서 crate::resolve_program("codex")를 매번 호출하고 있습니다.
resolve_program 내부의 which::which는 PATH 환경 변수에 등록된 디렉토리들을 순회하며 디스크 I/O 작업을 수행하므로, 루프가 돌 때마다 동일한 경로 탐색을 반복하는 것은 비효율적입니다.
루프 실행 전에 한 번만 경로를 찾아 변수에 저장한 뒤, 루프 내부에서는 해당 변수를 참조하도록 변경하는 것을 권장합니다.
예시:
let program = crate::resolve_program("codex");
for strict in [false, true] {
// ...
let mut child = tokio::process::Command::new(&program);
// ...
}| ); | ||
|
|
||
| let mut child = tokio::process::Command::new(bin); | ||
| let mut child = tokio::process::Command::new(crate::resolve_program(bin)); |
There was a problem hiding this comment.
for strict in [false, true] 루프 내부에서 crate::resolve_program(bin)을 매번 호출하고 있습니다.
resolve_program은 PATH 환경 변수의 디렉토리들을 검색하는 디스크 I/O 작업을 수반하므로, 루프 내부에서 반복 호출하는 것은 비효율적입니다.
루프 외부에서 미리 경로를 resolve한 뒤 루프 내부에서 재사용하도록 개선하는 것을 권장합니다.
예시:
let program = crate::resolve_program(bin);
for strict in [false, true] {
// ...
let mut child = tokio::process::Command::new(&program);
// ...
}|
Gemini 리뷰 2건 반영 (commit fe17704). reviewers/{codex,claude}.rs 의 |
PR #96 Gemini 리뷰 2건 (medium): reviewers/{codex,claude}.rs 의 `for strict in [false, true]` 루프 안에서 `resolve_program` 을 매번 호출 (PATH 디스크 I/O 반복). 루프 밖에서 1회 resolve 후 `&program` 재사용. 검증: cargo fmt --check + clippy -D warnings clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Issue #92 (cakel, Windows 10): `secall wiki update --backend codex` 가 "program not found" 로 실패. `where codex` 는 codex.cmd 를 찾는데도 spawn 실패. 원인: codex 는 npm 설치라 `codex.cmd` 배치 래퍼. `Command::new("codex")` 는 Windows 에서 PATHEXT 미적용 → `codex.exe` 만 찾고 `.cmd` 못 찾음. 반면 `command_exists` 는 `where.exe` 외부 호출이라 통과 → "존재하는데 spawn 실패" 불일치. Fix: - `which` crate (workspace dep) 도입. - `lib.rs`: `resolve_program(cmd) -> PathBuf` 추가 (PATHEXT 적용 경로 resolve). `command_exists` 도 which 기반 재구현 (where.exe/which 외부 호출 제거 → spawn 과 동일 탐색 규칙). - spawn 5곳 (`wiki/{codex,claude}`, `wiki/reviewers/{codex,claude}`, `search/query_expand`) 을 `Command::new(resolve_program(X))` 로. Rust 1.77+ 가 .cmd 풀경로를 cmd.exe 경유로 안전 실행. 검증: - cargo fmt --check / clippy -D warnings: clean - cargo test -p secall-core --lib: 426 passed (command_exists 회귀 3건 포함) -⚠️ Windows 실제 spawn 은 개발 환경(macOS) 에서 검증 불가 — cakel 검증 요청 예정. macOS/Linux 는 which 가 확장자 없는 실행파일 그대로 resolve → 회귀 없음. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR #96 Gemini 리뷰 2건 (medium): reviewers/{codex,claude}.rs 의 `for strict in [false, true]` 루프 안에서 `resolve_program` 을 매번 호출 (PATH 디스크 I/O 반복). 루프 밖에서 1회 resolve 후 `&program` 재사용. 검증: cargo fmt --check + clippy -D warnings clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fe17704 to
b0d2cff
Compare
Summary
Issue #92 (cakel, Windows 10):
secall wiki update --backend codex가Error: program not found로 실패.where codex는codex.cmd를 찾고 codex 자체도 동작하는데 secall 만 실패.원인
C:\Users\User\AppData\Roaming\npm\codex.cmd(배치 래퍼).std::process::Command::new("codex")는 Windows 에서 PATHEXT 미적용 →codex.exe만 시도,.cmd못 찾음.command_exists는where.exe외부 호출이라.cmd를 찾아 통과 → "존재하는데 spawn 실패" 불일치.Fix
whichcrate (workspace dep) 도입 — Windows PATHEXT (.CMD/.EXE/.BAT) 적용.lib.rs:resolve_program(cmd) -> PathBuf추가 +command_exists를 which 기반 재구현 (외부 프로세스 호출 제거, spawn 과 동일 탐색 규칙).Command::new(resolve_program(X))로 변경. Rust 1.77+ 가.cmd풀경로를 cmd.exe 경유로 안전 실행.wiki/codex.rswiki/claude.rswiki/reviewers/codex.rswiki/reviewers/claude.rs(run_review_cli)search/query_expand.rsTest plan
cargo fmt --all -- --checkcleancargo clippy --workspace --all-targets -- -D warningscleancargo test -p secall-core --lib426 passed (command_exists 회귀 3건 포함)which가 확장자 없는 실행파일 그대로 resolve → 회귀 없음.Risk
whichresolve 실패 시 입력 문자열 그대로 fallback → 기존 동작 유지.Closes #92
🤖 Generated with Claude Code