[개발 깨알 상식_Tips] / ClawSweeper: AI 이슈 정리 봇은 review와 apply를 분리해 high-confidence 제안만 닫기.md

ClawSweeper: AI 이슈 정리 봇은 review와 apply를 분리해 high-confidence 제안만 닫기

조회

2026년 4월 27일 | 개발 깨알 상식_Tips


ClawSweeper README에서 내가 제일 먼저 붙잡은 문장은 conservative maintenance bot 이었다. AI가 이슈를 얼마나 빨리 읽는지보다, 잘못 닫았을 때 얼마나 덜 망가뜨리는지를 먼저 설계한 도구라는 뜻이기 때문이다. 최근 에이전트 글들을 보다 보면 모델 성능이나 자동화 범위 쪽으로 시선이 쉽게 쏠리는데, 이 저장소는 반대로 닫기 권한을 늦게 열고 근거를 오래 남기는 구조를 전면에 둔다. 나는 이 점이 꽤 좋았다.

README 대시보드를 읽어 보면 open issue와 PR이 7천 개를 넘는 큰 큐를 다루면서도, close 제안 비율은 아주 낮게 유지한다. 즉 이 시스템의 핵심은 "많이 닫기"가 아니라 잘못 닫지 않기다. 이 차이가 중요하다. 실무에서 진짜 무서운 건 backlog가 느리게 줄어드는 일이 아니라, 봇이 maintainer가 아직 봐야 할 항목을 성급하게 정리해 버리는 일이다.

ClawSweeper review/apply 분리 다이어그램

ClawSweeper가 실제로 강조하는 것은 빠른 자동 close보다 review와 apply를 분리한 보수적 운영이다.

review lane에서 끝내는 것

ClawSweeper workflow에서 눈에 띄는 문장은 이것이다. review shards are proposal-only. 리뷰 단계는 closeReason, confidence, evidence를 만들고 durable review comment를 동기화할 수는 있지만, 그 자리에서 바로 닫지 않는다. 나는 이 한 줄이 AI 운영에서 꽤 큰 분기점이라고 본다. 판단을 생성하는 단계와 저장소 상태를 바꾸는 단계를 분리하면, 중간에 사람이 결과를 읽을 틈이 생기고, 시스템도 "판단 로그"를 남길 수 있다.

workflow_dispatch:
  inputs:
    apply_existing:
      description: "Apply existing proposed close decisions without rerunning Codex; skips items changed since review"
      default: "false"

이 입력 하나만으로도 설계 철학이 보인다. 리뷰를 다시 돌리면서 바로 mutate하지 않고, 이미 만들어 둔 제안을 나중에 별도 lane에서 적용한다. 그리고 그 사이에 item이 바뀌었으면 그냥 건너뛴다. AI가 똑똑하냐보다 결정을 내린 시점과 실행 시점 사이의 차이를 어떻게 다루느냐가 더 중요하다는 이야기다.

apply lane을 따로 두면 좋아지는 세 가지

첫째, high-confidence gate를 걸 수 있다. ClawSweeper decision schema는 decision, closeReason, confidence, evidence를 강제한다. "닫아도 될 것 같다" 같은 자유 텍스트로 끝내지 않고, 최소한 왜 그렇게 봤는지 구조화된 표면을 남긴다.

둘째, changed-since-review 체크가 가능하다. sample report에는 item_snapshot_hash가 남고, workflow 설명에도 changed since review를 명시한다. 리뷰할 때 본 상태와 지금 상태가 다르면, 그 제안은 곧바로 stale이 된다. 이건 issue triage뿐 아니라 코드 리뷰 자동화에도 그대로 가져갈 수 있는 감각이다.

셋째, protected surface를 명시적으로 뺄 수 있다. 구현 코드를 보면 protected label 집합을 따로 둔다. security, beta-blocker, release-blocker, maintainer 같은 라벨이 붙은 항목이나 maintainer-authored item은 자동 close 대상에서 빠진다. 나는 이런 예외 규칙이 prompt 본문 안에만 있으면 잘 안 믿는다. 실행 코드의 분기문으로 박혀 있어야 진짜 guardrail이 된다.

const PROTECTED_LABELS = new Set([
  "security",
  "beta-blocker",
  "release-blocker",
  "maintainer",
]);

여기에 audit trail이 붙으면 훨씬 단단해진다. sample report를 보면 item_snapshot_hash, fixedSha, fixedRelease, review_comment_sha256, action_taken 같은 필드를 남긴다. 나는 이런 메타데이터가 사소해 보이지 않는다. 실제로 문제가 생기면 "이 봇이 왜 이 항목을 닫았는가"보다 먼저 "어느 시점의 어떤 상태를 보고 닫았는가"를 확인하게 되기 때문이다. snapshot과 근거가 남아 있으면 사후 복기 속도가 달라진다.

{
  "decision": "close",
  "closeReason": "implemented_on_main",
  "confidence": "high",
  "evidence": [ ... ],
  "fixedSha": "...",
  "closeComment": "..."
}

중요한 건 JSON을 예쁘게 만드는 일이 아니다. 결정, 확신도, 근거, 고정된 식별자를 한 세트로 남겨 두는 것이다. 이 네 가지가 있어야 사람이 나중에 다시 읽을 수 있고, 봇이 틀렸을 때도 어디서 미끄러졌는지 짚을 수 있다.

내가 바로 가져가고 싶은 구현 조각

비슷한 봇을 붙일 때 나는 기능보다 운영 표면부터 따라 할 것 같다.

1. review 산출물을 markdown 파일로 남긴다. item별 파일이 있으면 나중에 "왜 닫았지?"를 역추적하기 쉽다.

2. schema로 출력 필드를 고정한다. closeReason, confidence, evidence, fixedSha 정도는 최소 필수다.

3. apply는 schedule이나 manual dispatch로 늦게 연다. hot intake는 자주 돌려도, 실제 close는 별도 cadence로 더 조심스럽게 처리하는 편이 낫다.

4. maintainer / security / release 계열 라벨은 코드에서 하드 블록한다. 이건 설명 문장보다 조건문이 더 믿을 만하다.

# 비슷한 구조를 GitHub Actions에 붙일 때의 시작 예시

gh workflow run sweep.yml -f hot_intake=true
gh workflow run sweep.yml -f apply_existing=true -f item_numbers=1234

명령도 이렇게 나누는 쪽이 마음이 편하다. review는 넓게, apply는 좁게. 이 리듬이 있어야 AI가 backlog를 건드리는 날에도 저장소가 덜 불안하다.

결국 중요한 건 닫는 속도보다 닫기 권한의 모양

ClawSweeper를 보면서 내가 제일 크게 배운 건 AI에게 무엇을 시킬지보다 언제까지는 시키지 않을지를 먼저 정해야 한다는 점이었다. proposal-only 리뷰, changed-since-review skip, protected labels, durable comment, audit trail 같은 장치들은 전부 같은 방향을 가리킨다. 판단은 빨리 만들어도 되고, 변경은 천천히 적용해도 된다. 오히려 그 편이 오래 간다.

원문은 ClawSweeper 저장소, workflow 파일, decision schema, sample report를 같이 보면 흐름이 한 번에 잡힌다. 나처럼 AI 유지보수 봇을 볼 때 성능보다 운영 감각을 먼저 보는 사람이라면, 이 저장소는 꽤 재미있게 읽힐 것이다.

조금 과장하면, 이런 도구에서 중요한 건 자동화 엔진보다 닫기 버튼 앞에 세워 둔 문지기들이다. 그 문지기들을 프롬프트가 아니라 workflow, schema, protected label, snapshot 기록으로 박아 두는 쪽이 결국 오래 버틴다.

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.