Skip to content

chore(hooks): 리다이렉션 순서 잔여 사이트 43곳 — 가드로 정확성은 보존, 메시지만 유출 (분류 완료·착수 보류) #1059

Description

@seoseo-ai

배경

cmd >> "$FILE" 2>/dev/null은 보기와 다르게 동작합니다. 셸은 리다이렉션을 좌→우로 적용하므로, 목적지를 열지 못하면 그 에러가 stderr가 막히기 전에 실제 stderr로 나갑니다. 명령의 종료 상태도 실패가 됩니다.

이 결함은 이번 라운드에서 네 번 독립적으로 발견됐고 모두 수정됐습니다:

PR 대상
#1054 start.sh _cmdline_is_project_bot
#1055 hook-common.sh log()
#1056 log() 복사본 6개
#1058 다중행 audit() 2개 + distill.sh 2줄 + lifecycle-common.sh 2곳 + backups-rotate

hook-common.test.sh의 감사가 log()/audit() 본문(단일행·다중행)에서의 재발을 막습니다.

이 이슈의 범위 — 남은 43곳

감사를 log/audit으로 의도적으로 좁게 잡았기 때문에, 같은 순서를 가진 나머지 사이트는 그대로 남아 있습니다. 다만 성격이 다릅니다.

핵심 차이: 이들은 전부 가드가 있습니다.

cmd > "$tmp" 2>/dev/null && mv "$tmp" "$dst"     # 열기 실패 시 mv 안 함 → 정확성 보존
cmd >> "$LEDGER" 2>/dev/null || true             # 실패 무시가 명시적
cmd > "$f" 2>/dev/null || rm -f "$f"             # 실패 시 정리
if cmd > "$tmp" 2>/dev/null; then ...            # 상태를 실제로 검사

기능적 결과는 옳고, 새는 것은 stderr 메시지뿐입니다. 이미 수정한 log/audit은 "조용하고 실패하지 않겠다"는 계약 자체를 깨뜨렸던 것과 대비됩니다.

파일별 분포 (main aebe40b 기준)

파일 건수 성격
hooks/skill-review/autoinstall.sh 10 || true / && / if 가드
hooks/load-memory.sh 6 핫패스 — 검색 레인 4 + 타이밍 플러시 + scan 레인
hooks/skill-review.sh 4 || true
hooks/distill/wiki-queue.sh 3 && mv
hooks/lib/autonomy-guard.sh 2 || exit 0 / if
scripts/ccc-skill-autosave.sh 3 && / if
기타 15개 파일 15 대부분 && mv 임시파일 패턴

(hook-common.sh 1건은 결함을 설명하는 주석이며 코드가 아닙니다.)

착수를 보류하는 이유

  1. 실익이 노이즈 제거뿐입니다. 정확성 회귀는 없습니다.
  2. 핫패스가 섞여 있습니다. load-memory.sh 6건은 모든 세션 시작의 크리티컬 패스이고, 그중 4건은 백그라운드 검색 레인입니다. 노이즈만을 위해 여길 편집하는 건 #1040에서 확인한 것과 같은 종류의 나쁜 거래입니다.
  3. 일괄 적용이 위험합니다. #1058이 실증했습니다 — lifecycle-common.sh는 append 실패가 함수의 정당한 실패 신호라 로거와 같은 || :를 붙였다면 그 자체가 회귀였습니다. 43곳도 사이트별 판단이 필요합니다.

착수 조건

실제 노이즈가 문제로 관측될 때 착수합니다. 구체적으로:

  • 훅 stderr 오염이 세션에서 보고되거나
  • cron 로그에 이 계열 메시지가 쌓이는 것이 확인되거나
  • 해당 파일을 다른 이유로 건드릴 때 편승

착수 시 원칙: 순서 수정은 어디서나 안전하지만, || : 추가는 계약이 명시적으로 best-effort인 곳에만. 상태를 소비하는 호출자가 있으면 절대 삼키지 말 것.

재현

grep -rnE '(^|[^0-9&2])>>?[[:space:]]+"[^"]+"[[:space:]]+2>/dev/null' \
  --include='*.sh' claude/hooks scripts | grep -v '\.test\.sh:'

기록 목적의 이슈입니다 (#1041 선례와 동일한 성격). 누군가 이 패턴을 다시 발견해 전수 조사를 반복하지 않도록 분류와 판단 근거를 남깁니다.

관련: #584, #1054, #1055, #1056, #1058

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions