spec에서 첫 PR까지 — jira-agent 4일 구축 기록 (구축기 2편)

spec에서 첫 PR까지 — jira-agent 4일 구축 기록 (구축기 2편)

1편에서는 Jira에 티켓 하나 적으면 7분 만에 PR이 만들어지는 흐름을 보여줬다. 그 흐름을 만드는 데 사흘이 걸렸다. 5월 18일에 spec 결정 12개로 시작해서 5월 20일에 첫 운영 PR이 나오기까지다.

이 글에서는 그 사흘 동안 무엇을 결정했고, 어느 시점에 spec을 고쳤고, 어떻게 풀었는지를 기록한다. 비슷한 1인 자동화를 만들려는 사람에게 참고가 됐으면 한다.

누가 읽으면 좋은가

  • 1편을 보고 jira-agent 같은 자동화를 직접 만들어보고 싶은 1인 개발자
  • 4일 정도에 운영까지 올릴 만한 구축 흐름이 궁금한 사람
  • 여러 모듈을 의존성 그래프로 묶어 동시에 만드는 방법이 필요한 사람

한 줄로 요약하면, architect가 한 번에 계획을 다 짜지 못했고 운영 실측 결과로 두 번 다시 짰다. 그래서 4일이 걸렸다.

역할을 다섯으로 나눴다

5월 18일에 역할을 다섯으로 나눴다. 각자 무엇을 했는지는 본문에서 풀어쓴다.

  • architect — spec을 받아 구축 계획과 의존성 그래프를 그리는 역할
  • module-builder — 계획에 적힌 모듈을 하나씩 가져가 코드와 테스트를 같이 쓰는 역할
  • integration-qa — 빌더가 만든 모듈을 모아 테스트 전체를 돌리는 역할
  • fail-fast-reviewer — 예외를 삼키거나 빈 분기를 두는 식의 fail-fast 위반이 있는지 검증하는 역할
  • infra-setup — launchd 상주, secrets 권한, worktree 격리 같은 환경을 깔아두는 역할

이 다섯이 같은 4일 동안 동시에 돌아갔다. 시간 순서로 풀면 다음과 같다.

1일차 — 결정 12개와 모듈 22개

5월 18일에 처음 spec을 작성했다. 결정 12개와 다섯 섹션으로 구성된 설계 문서다. 경로는 docs/superpowers/specs/2026-05-18-jira-agent-pipeline-design.md.

핵심 결정은 다음과 같다.

  • 입력 = Jira description (마크다운 3섹션 강제: Target File / Acceptance Criteria / Test Examples)
  • 트리거 = JQL 5분 polling (webhook은 다음 단계 옵션)
  • LLM = Qwen3.6 35B 단일 backend 가정 (Ollama 로컬, 무료)
  • 격리 = 티켓별 git worktree
  • 안전망 = 세 가지 (loop_no_progress, fake_done_no_evidence, stale_blocker)

architect가 이 spec을 받아 모듈 22개로 쪼갠 구축 계획을 만들었다. 같은 날 module-builder가 모듈을 하나씩 가져가 코드와 테스트를 같이 작성했다. 저녁에는 M4 Mac Studio에 launchd plist를 올려 워커를 상주시켰고, infra-setup이 secrets 디렉토리에 chmod 600을 걸었다.

1일차 끝에 수동으로 E2E를 한 번 돌렸다. 액션 8단계가 처음부터 끝까지 동작했다.

2일차 — LLMBackend 추상화 추가, spec 1차 수정

5월 19일에 변화 두 가지가 같은 날 일어났다.

첫째, LLMBackend 추상화를 추가했다. 1일차 spec은 Qwen 하나만 쓴다는 가정이었는데, 운영 중에 backend를 바꿔야 할 일이 생길 수 있다는 게 명확해졌다. 단순 작업은 Qwen 무료로 충분하지만 복잡한 업무 로직에는 Claude나 Kimi 수준의 품질이 필요할 수 있다.

architect가 계획을 고쳐 LLMBackend 인터페이스를 추가했다. claude, qwen, kimi, kimi_cli 네 가지 backend를 받아 고정, 라운드로빈, 라벨 세 가지 방식으로 라우팅한다. module-builder는 이 인터페이스를 22개 모듈 중 일부에 통합했다.

둘째, 100-spec 배치 비교를 돌렸다. ci_fix 배치도 같이 돌려 backend별 성능을 측정했다. Qwen MoE(Mixture of Experts)가 속도와 비용에서, Kimi가 품질과 캐시 적중률에서, Claude가 안정성에서 각각 우위가 갈렸다. 운영 기본값은 Qwen으로 정했다.

저녁에 publish 버그를 포함해 결함 7건이 한꺼번에 드러났다. fail-fast-reviewer가 잡은 것도 있고 integration-qa 단계에서 잡힌 것도 있다. 통합 후 통과 개수가 720개에서 760개로 늘었다. 빌더 단위 테스트는 다 통과했는데 통합 단계에서 결함이 드러난 점이 이 날의 학습이다.

3일차 — 운영 실측으로 spec 확장 (다중 파일·동적 저장소)

5월 20일에 단순 함수에서 알고리즘까지 (난이도 L1~L5) 티켓 8개를 운영에서 실측으로 돌렸다. L1~L5는 작업 난이도로 단순 함수부터 알고리즘까지를 뜻한다. 결과는 greet, slugify, word_count, TokenBucket 같은 함수가 안정적으로 처리됐다.

여기서 두 가지가 명확해졌다.

  • 다중 파일 처리 필요 — Target File 하나만으로는 실제 작업이 안 풀린다. Related Files 섹션이 있어야 한다
  • 저장소 동적 지정 필요 — sandbox_repo 고정만으로는 다른 프로젝트에 못 쓴다. spec에 Repo 섹션을 받아 동적으로 clone해야 한다

architect가 spec을 확장한 새 계획을 짰다. 다중 파일과 저장소 동적 지정을 다루는 확장이라 새 모듈 9개를 추가로 만들어야 했다. spec_parser, config, queue, _safety, _base, branch_create, impl, monitor, worker 아홉 개다.

의존성 그래프로 묶으니 다섯 개 구축 그룹이 됐다. module-builder가 그룹별로 의존성 순서대로 동시에 진행했다. 신규 테스트 102개가 추가됐고 전부 통과했고 회귀는 0건이다.

액션 8단계 자체는 그대로다. 바뀐 건 spec_parser가 받는 입력 형식(Target / Related / Repo)과 impl이 다루는 범위뿐이다.

같은 날 — 첫 다중 파일 PR

spec 확장 구축이 끝난 직후 다중 파일 작업을 운영에서 처음 돌렸다. 티켓 본문은 다음과 같다.

## Target File
src/utils/version_bump.py

## Related Files
- src/utils/version_bump.py
- src/utils/_semver.py

## Acceptance Criteria
- _semver.py has parse_semver(version: str) -> tuple[int, int, int]
- version_bump.py has bump_version(version: str, kind: str) -> str
- bump_version("1.2.3", "patch") returns "1.2.4"
- bump_version with bad kind raises ValueError

워커가 처리한 결과는 PR #5다. version_bump.py 32줄, _semver.py 22줄, test_version_bump.py 30줄, 합쳐서 84줄. 1편에서 다룬 그 7분 PR이 이 다중 파일 티켓 처리 결과다.

사흘 작업으로 운영 첫 PR이 나왔다.

4일 내내 — 환경 설정

코드 작업과 함께 infra-setup이 4일에 걸쳐 진행됐다.

  • launchd plist (com.jason.jira-agent.worker)로 워커 상주
  • secrets 디렉토리 chmod 600 강제 (644면 워커가 안 뜨도록)
  • 티켓별 git worktree 분리 (~/.jira-agent/worktrees/{KEY})
  • PAT(Personal Access Token)을 ~/.jira-agent/secrets/github_pat에 평문으로 두고 회전은 수동
  • redact()로 PAT과 API key 패턴을 마스킹한 다음 Jira와 로그로 송신

이 영역은 fail-fast-reviewer가 잘 잡지 못한다. 같은 풀의 builder가 만든 코드를 같은 풀의 reviewer가 보는 구조라서, 환경 설정 결정 같은 부분은 사람이 직접 확인해야 했다.

역할 분담이 만든 효과

architect가 계획을 처음 짠 게 5/18, 두 번째 짠 게 5/20이다. 그 사이에 module-builder가 모듈 22개를 만들었고, integration-qa가 publish 버그 7건을 잡았고, fail-fast-reviewer가 일부 결함을 미리 거르고, infra-setup이 환경을 깔았다.

역할 분담의 진짜 효과는 architect 계획이 한 번에 끝나지 않아도 다음 단계가 그대로 굴러간다는 점이다. 1일차 spec이 그대로 갔다면 2일차 LLMBackend 추가와 3일차 spec 확장 계획이 한 사람한테 다 몰렸을 거고, 4일 안에 못 끝났을 가능성이 크다.

다만 한계도 같이 보였다. integration-qa가 잡은 결함은 빌더가 만든 단위 테스트로는 못 잡은 것들이었다. 같은 풀에서 나온 모델끼리 검증한다는 점이 이번 구축의 잠재 약점이다. 다른 모델 풀로 reviewer를 분리하는 게 다음 검증 영역이다.

한계

  • Qwen 품질은 L1~L6까지만 검증됐다. 다중 파일 사례가 가장 복잡한 케이스다. 더 깊은 비즈니스 로직은 아직 미검증이다.
  • Claude·Kimi 운영 전환은 안 해봤다. 100-spec 배치에서 한 번 비교만 했고 운영 기본값은 Qwen이다. 유료 backend 전환 시점이 시리즈 3편 주제다.
  • mDNS 의존이라 외부망에서 접근이 안 된다. webhook을 켜려면 Cloudflare Tunnel 같은 추가 인프라가 필요하다.

마무리

사흘 작업의 결과가 1편의 7분 PR이다. architect 계획을 1일차에 한 번, 3일차에 한 번 다시 짠 게 4일 안에 끝낼 수 있었던 핵심이다.

다음 글은 유료 backend 전환과 외부망 접근이다. Qwen 무료 backend의 한계가 어디서 풀리는지, mDNS 의존이 어떻게 빠지는지가 시리즈 3편 주제다.


참고


저자 — Jason 황재승

cd4761.blogspot.com에서 개발 자동화와 AI 도구 운영 기록을 쓴다. trend-scout 1년 운영. 8년 차 프론트엔드. 본 시리즈는 jira-agent 구축 기록 3편 중 2편이다.

태그: #jira #개발자동화 #PR자동화 #에이전트구축 #architect #moduleBuilder #로컬LLM #Qwen #시리즈

댓글

이 블로그의 인기 게시물

Claude Opus 4.7 출시 총정리 — 뭐가 달라졌고 지금 써야 하나

맥 스튜디오 M4 Max 128GB 로컬 LLM 4개 속도 비교 — gemma4·llama3.3·qwen3 실측

Claude Code로 블로그 발행 15분을 1줄로 — 해고 후 첫 자동화 경험