자기야 발견: 다랑이 review 결과에 "코드가 끊긴다" 가 반복 등장. 다랑이의 실제 review 메시지를 확인해 보니 narang 이 만든 todo-debug-mode.html 의 <script> 가 `const form = document.getElementById(` 에서 잘려서 반복 round 마다 같은 잘림 지점을 지적했음. 원인 추적: - narang junior 의 LLM 출력 원본 (junior-01-*.md) 은 깔끔하게 </html> 로 종료. LLM 자체는 멀쩡. - spawn.ts buildSuccessResult 의 summary slice(0, 2000) 가 1차로 자름 - 그 위 aggregated slice(0, 6000) 가 0차로 자름 - runner extractStageText 의 review issues slice(0, 2000) 도 추가 한도 - LLM-emit reason 도 spawn.ts parseReviewVerdict 에서 1000/800 자로 잘림 todo HTML 한 파일이 5KB 정도 되니 6000 자 한도에서 3분의 1 잘려나감 → darang 은 결과적으로 절반짜리 코드를 받음 → 영원히 REQUEST_CHANGES. 수정 (모두 LLM context 200k+ 안에서 안전한 한도): - spawn.ts aggregated: 6_000 → 64_000 - spawn.ts buildSuccessResult.summary: 2_000 → 64_000 - spawn.ts parseReviewVerdict reason: 1_000 → 16_000 - spawn.ts parseDeployVerdict reason: 800/1000 → 16_000 - runner.ts extractStageText review issues: 2_000 → 32_000 검증: 다음 실행에서 darang 이 동일한 잘림 지점을 지적하지 않으면 OK.
hanarang-rails
4 자매가 달릴 결정론적 레일 — HaNaRang Rails
사용자는 출발 버튼만 누른다. 나머지는 자매들이 자동으로 달린다.
hanarang-rails 는 4 개의 AI "자매" 에이전트 (하랑 / 나랑 / 다랑 / 이랑) 가 하나의 요청을 받아 기획 → 구현 → 리뷰 → 배포를 자동으로 완주하는 결정론적 파이프라인 오케스트레이터다. 전임자 hanarang-harness 가 권고 기반이라 자매들이 중간에 길을 잃던 문제를, XState 유한 상태 기계 (FSM) 와 Sprint Contract 로 물리적으로 강제한다.
- 처음 보는 사람을 위한 완전 가이드:
docs/GUIDE.md/docs/GUIDE.pdf - 설계 문서:
.plans/design/ - 스프린트 명세:
.plans/sprints/ - 실패 감사 (F1–F6):
.plans/failure-audit.md
한 문단 요약
사용자가 "todo 앱 만들어 줘" 한 줄을 던지면, rails 오케스트레이터가 하랑이 (기획) → 나랑이 (구현) → 다랑이 (리뷰) → 이랑이 (배포) 순서로 파이프라인을 돌린다. 각 자매는 내부에서 부장/수석/선임/신입 4 단계 계층으로 태스크를 쪼개서 병렬 실행하고, 만들어낸 코드 파일은 자동으로 Gitea 에 public repo 로 push 되어 즉시 접근 가능한 URL 로 바뀐다. 대시보드에서는 이 모든 과정이 실시간으로 트리 형태로 보인다.
왜 다시 만들었는가
hanarang-harness 에서 4 개월 운영하며 발견한 6 가지 고질 실패 모드:
| 코드 | 증상 | 원인 |
|---|---|---|
| F1 | 하네스 skill bypass — 자매가 혼자 worker 스폰 | skill 진입 강제 없음 |
| F2 | DoD 자동 강제 실패 — build 통과 = 완료로 판정 |
sprint contract / validator 없음 |
| F3 | QA 단계 누락 — 사용자가 수동으로 다랑이 호출 | 자동 라우팅 없음 |
| F4 | 핸드오프 멘션 불안정 — 잘못된 자매 호출 | 분기가 LLM 판단에 의존 |
| F5 | 중간 끊김 — request-timed-out 반복 |
재시도/에스컬레이션 정책 없음 |
| F6 | 환경 검증 누락 — "Docker 없음" 으로 skip 허용 | 환경 전제 검사 없음 |
본질 한 줄: "자매가 하네스를 안 타고 본인이 처리한다."
6 가지 설계 원칙 (하드 룰)
- 강제 > 권고 — 모든 파이프라인 전이는 코드로 강제한다.
- 결정론적 FSM — 자매 간 핸드오프는 XState 상태 전이다.
- Sprint Contract = 불변 계약 — DoD 를 Zod 스키마로 정의, validator 가 pass/fail 판정.
- Skill 강제 진입 — skill bypass 를 hook 이 감지해 차단.
- QA 체크리스트 의무 — 다랑이가 체크박스 전부 채워야 PASS.
- 환경 검증 선행 — 실기동 검증 환경 없으면 스프린트 시작 자체를 거부.
아키텍처 개요
사용자 (Discord / Dashboard Web)
│
▼
┌─────────────────────────────┐
│ hanarang-dashboard │ Next.js 16 + NestJS
│ /rails, /office, /sisters │
└────────────┬────────────────┘
│ HTTP
▼
┌─────────────────────────────┐
│ hanarang-rails orchestrator │ XState + Prisma + MariaDB
│ FSM ─ Contract ─ Hierarchy │
└────────────┬────────────────┘
│ HTTP invoke
┌──────────┼──────────┬──────────┐
▼ ▼ ▼ ▼
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│하랑 │ │나랑 │ │다랑 │ │이랑 │ sister-agent × 4 LXC
│plan │ │impl │ │review│ │deploy│
└──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘
└─────────┴─ openclaw CLI ────┘ (LLM: gpt-5.4 등)
│
▼
┌───────────────┐
│ Gitea SSOT │ git.nabomhalang.co.kr
│ (auto-push) │ public repo per pipeline
└───────────────┘
기술 스택
| 레이어 | 선택 |
|---|---|
| 런타임 | Node 22 + TypeScript strict |
| 상태 머신 | XState v5 |
| 스키마 | Zod |
| DB | MariaDB (Prisma) |
| 프로세스 | execa + AbortController |
| CLI | citty |
| 로그 | pino |
| 테스트 | Vitest |
| 프론트엔드 (대시보드) | Next.js 16 + styled-components |
| 백엔드 (대시보드) | NestJS + Socket.IO |
상태
- v0.1.0 — Sprint 000~007 완료. FSM / Contract / QA / Migration 코어. 105 테스트 통과.
- v0.1.1 — 실 LLM 통합 (OpenClaw infer), 4 계층 재귀 스폰, 파일 추출, Gitea auto-push, deploy URL.
- v0.1.2 — 대시보드 아티팩트 뷰, FileViewerModal (MD 파일 클릭 → 모달).
- v0.1.3 — LLM 제공자 어댑터 (OpenAI / Anthropic / Ollama / OpenClaw / mock), in-process 단일 프로세스 모드, docker-compose, Gitea 호스트 완전 외부화, 외부 배포 친화 .env.example.
빠른 시작 (Docker, 5 분)
가장 짧은 경로. 로컬에 docker 와 docker compose 만 있으면 된다.
git clone https://git.nabomhalang.co.kr/hanarang/hanarang-rails.git
cd hanarang-rails
cp .env.example .env
# .env 에서 LLM_PROVIDER=mock 으로 시작 (또는 openai/anthropic/ollama)
docker compose up --build
# → http://localhost:18800/health 확인
# 다른 터미널
curl -X POST http://localhost:18800/pipelines/start \
-H 'content-type: application/json' \
-d '{"project":"hello","requirements":"Say hi"}'
이게 끝. MariaDB + rails + sister-agent 4 개가 한 컨테이너 안에서 in-process 모드 로 돈다. 자세한 설정 옵션 (실제 LLM 키 연결, 네이티브 설치, 분산 토폴로지, 대시보드) 은 docs/LOCAL-SETUP.md 참조.
배포 토폴로지
| 모드 | 설명 | 파일 |
|---|---|---|
| in-process | 모든 것을 하나의 Node 프로세스에서. 로컬 개발 기본값 | docker-compose.yml · rails.config.local.yaml |
| http 분산 | rails + 4 개 독립 sister-agent 컨테이너. 운영 토폴로지 | docker-compose.full.yml · rails.config.distributed.yaml |
| mock | FSM 만 검증 (LLM/파일/push 없음) | RAILS_TRANSPORT=mock 또는 rails run --mock |
LLM 제공자
어댑터가 있어 다음 중 하나를 선택할 수 있다. .env 의 LLM_PROVIDER 로 지정:
mock— API 키 없이 결정론 스켈레톤만 확인 (기본값)openai— OpenAI / OpenRouter / Azure OpenAI / OpenAI-호환 로컬 서버anthropic— Anthropic Messages APIollama— 로컬 Ollama 서버openclaw— hanarang 내부 전용 런타임
CLI 서브커맨드
| 명령 | 용도 |
|---|---|
rails start |
파이프라인 생성 |
rails run [--mock] |
E2E 실행 |
rails status [id] |
상태 조회 + 타임라인 |
rails resume <id> |
escalated → idle 재개 |
rails abort <id> |
강제 종료 |
rails contract generate/freeze/validate/show |
Sprint Contract 관리 |
rails qa run/show/templates |
QA 템플릿 실행 |
rails skill-context create/show/clear |
Skill 강제 진입 |
rails skill-trace show/blocked |
도구 사용 감사 로그 |
rails doctor |
환경 헬스체크 |
rails scaffold |
신규 프로젝트 .plans/ 생성 |
rails migrate from-hanarang-harness <path> |
레거시 하네스 스캔 |
rails serve |
오케스트레이터 HTTP 서버 |
HTTP API (orchestrator, 18800)
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /health |
헬스체크 |
| GET | /pipelines?limit=N |
파이프라인 리스트 |
| GET | /pipelines/:id |
파이프라인 상세 |
| POST | /pipelines/start |
새 파이프라인 실행 |
| POST | /pipelines/:id/abort |
강제 종료 |
| GET | /api/pipelines/:id/sub-tasks |
SubTask 트리 |
| GET | /api/sub-tasks/:id |
서브태스크 상세 |
| GET | /api/transitions |
상태 전이 이력 |
| GET | /api/escalations |
에스컬레이션 큐 |
문서
docs/LOCAL-SETUP.md— 30 분 퀵스타트 (본인 환경에서 처음 돌려 보기)docs/GUIDE.md— 완전 가이드 (전 구간 해설, 처음 보는 사람용)docs/GUIDE.pdf— 위 문서의 PDF 버전docs/migration-guide.md— 레거시 → rails 이전 가이드docs/operations.md— 운영 가이드 (PM2, 로그, DB)docs/discord-setup.md— Discord 봇 연동 + marker 프로토콜.plans/OVERVIEW.md— 프로젝트 전체 개요.plans/failure-audit.md— F1–F6 실패 감사.plans/design/— 설계 문서 9 종.plans/sprints/— 스프린트 상세
라이선스
MIT — 나봄하랑 / hanarang