Files
hanarang-rails/.plans/OVERVIEW.md
이랑이 565a2960e2 docs(design): transport 추상화 + 트리거 3종 + opt-in 원칙 확정
- design/transports.md — DiscordTransport (v1) / GatewayHttpTransport (v2) / MockTransport
  Rails invoke payload를 HTML 주석으로 감싸 디스코드 전송 (자기야는 자연어만 봄)
- design/triggers.md — opt-in 3종:
  1. /rails start 슬래시 커맨드
  2. 하랑이 제안 → 사용자 승인
  3. Gitea webhook → 자동 배포 진입
- OVERVIEW.md — scope에 opt-in 원칙 + 일상대화 Out of Scope 명시 + 문서 링크 9개로 확장

결정: 자기야 승인 — 2026-04-10 확인
- DiscordTransport 를 v1 기본 transport 로 채택
- 자매 자연어 포스팅은 그대로 유지 (가시성)
- gateway HTTP API 는 v2 에서 스펙 확인 후 전환

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:04:43 +09:00

6.7 KiB
Raw Permalink Blame History

hanarang-rails — OVERVIEW

4자매가 달릴 결정론적 레일

목표 (Goal)

4자매 AI(하랑 / 나랑 / 다랑 / 이랑) 파이프라인을 사용자 중재 없이 자동으로 완주시킨다.

  • 입력: 사용자 요청 한 줄 ("X 프로젝트 기획해줘")
  • 출력: 배포 검증 완료 + 최종 승인 요청
  • 사람 개입: 최초 요청 + 에스컬레이션 + 배포 승인 — 그 외 전부 자동

왜 재작성?

hanarang-harness권고 기반 파이프라인이었다. 자매들이 레일을 벗어나도 막을 수단이 없었고, 결과적으로 사용자가 계속 중재자로 개입해야 했다. 상세한 실패 모드는 failure-audit.md 참조.

핵심 증상 한 줄: "자매가 하네스 skill 을 안 타고 본인이 처리한다."

범위 (Scope)

핵심 원칙: Rails 는 opt-in

Rails 는 4자매의 일상 대화를 가로채지 않는다. 명시적 트리거 에서만 활성화된다. 트리거는 3종류:

  1. Slash command (/rails start ...)
  2. 하랑이 제안 후 사용자 승인
  3. Gitea webhook (자동 배포)

상세: design/triggers.md

In Scope

  • 4자매 역할: 하랑(Planner) / 나랑(Generator) / 다랑(Evaluator/QA) / 이랑(Infra/Deploy)
  • XState 기반 결정론적 오케스트레이터
  • Sprint Contract (Zod schema + validator)
  • Skill 강제 진입 (hook 기반 bypass 차단, project 모드 한정)
  • 상태 전이 기반 자매 핸드오프
  • SisterTransport 추상화 (DiscordTransport v1, GatewayHttpTransport 후속)
  • 재시도 / 타임아웃 / 에스컬레이션
  • QA 체크리스트 runtime
  • 디스코드 이중 채널: 자매 자연어 대화 (가시성) + rails payload 마커 (제어) + rails 상태 마커 (조감도)
  • Gitea webhook receiver (자동 배포 진입)
  • SQLite 기반 상태 영속화
  • 기존 hanarang-harness 자산 마이그레이션 (scaffold, install, agents md)

Out of Scope

  • 4자매 일상 대화 — 기존 방식 그대로 유지. Rails 는 관여하지 않음
  • OpenClaw 런타임 자체의 수정
  • 자매 모델 자체 학습 / 파인튜닝
  • 디스코드 봇 기능 확장 (파이프라인 외 기능)
  • GitHub 연동 (Gitea 전용)
  • 멘션 기반 자매 간 핸드오프 (구 하네스 경로. 제거 대상 — SPRINT-007)

성공 기준 (Definition of Done)

  1. End-to-end 자동화

    • "X 프로젝트 기획해줘" 한 줄로 사용자 개입 0회 에서 배포 검증까지 도달한다
    • 중간에 사용자가 멘션되는 경우는 에스컬레이션 뿐이다
  2. 결정성 (Determinism)

    • 동일 입력 → 동일 파이프라인 전이 (상태 머신 테스트 100% pass)
    • 같은 시나리오를 10번 반복 실행 시 핸드오프 실패 0건
  3. Skill 강제 진입

    • 자매가 hanarang-rails skill 을 우회하려 하면 hook 이 감지하고 차단한다
    • 차단 이벤트가 로그에 구조화되어 남는다
  4. DoD 강제

    • build 통과 = 완료 시나리오가 거부된다
    • 실기동 검증 결과가 structured result 로 contract 를 통과해야만 cc:완료 로 전이한다
  5. 타임아웃 복원력

    • 자매 응답 없음 30초 → 자동 재시도 1회
    • 3회 실패 → 사용자 에스컬레이션
    • request-timed-out 로 파이프라인이 좀비가 되는 사례 0건
  6. QA 강제

    • 다랑이가 체크리스트를 전부 채우지 않으면 PASS 판정을 낼 수 없다
    • QA 결과가 artifact 로 저장되고 추후 조회 가능
  7. 관찰 가능성 (Observability)

    • 모든 상태 전이가 SQLite state_transitions 테이블에 기록된다
    • rails status 명령으로 현재 상태 + 과거 전이 이력을 조회할 수 있다
    • pino 로그가 pipeline-id 로 grouped
  8. 마이그레이션 경로

    • 기존 hanarang-harness 사용자(=나봄하랑)가 수동 작업 없이 rails migrate 로 옮길 수 있다
    • 기존 scaffold.sh, install.sh --role 동작이 하위 호환 유지되거나 대체재가 제공된다

비기능 요구사항 (NFR)

항목 기준
기동 시간 rails start 후 2초 이내 ready
메모리 idle 시 < 100MB, 동시 4자매 spawn 시 < 500MB
디스크 SQLite DB 100 MB 이하 (90일 retention)
로그 스프린트당 평균 1MB 이하 (구조화 압축 후)
재시도 exponential backoff (1s, 2s, 4s, 최대 30s)
타임아웃 자매 응답 기본 30s, 설정 가능

레일 메타포 (왜 hanarang-rails?)

4자매는 레일 위의 열차다. 지금까지는 레일이 없어서 자매가 제멋대로 방향을 정했다. hanarang-rails 는:

  • 레일 = XState FSM: 갈 수 있는 경로를 물리적으로 제한
  • 신호등 = Sprint Contract: 다음 역으로 갈 조건
  • = 자매 작업 단계 (Plan / Impl / QA / Deploy)
  • 차단봉 = Skill 강제 진입 hook
  • 긴급 정차 버튼 = 에스컬레이션 policy
  • 중앙 통제소 = SQLite orchestrator state

사용자(자기야)는 출발 버튼만 누르고, 긴급 상황에서만 호출된다.

타임라인 / 마일스톤

스프린트 기반으로 진행. 날짜 예측은 하지 않는다.

  • M0: 스펙 확정 + Sprint 000 완료 (계획/감사/프로젝트 세팅)
  • M1: Sprint 001003 완료 — "레일이 깔림" (스켈레톤 + 강제 + 계약)
  • M2: Sprint 004006 완료 — "열차가 달림" (핸드오프 + 복원력 + QA)
  • M3: Sprint 007 완료 — "이전이 끝남" (마이그레이션 + 실서비스 투입)

관련 문서

참고

  • 후계 대상: hanarang/openclaw-harness
  • 4자매 인프라: 메모리 project_hanarang.md
  • OpenClaw vs Claude Code: 4자매는 OpenClaw 런타임, 이 레포는 Claude Code 세션으로 개발