Files
hanarang-rails/rails.config.example.yaml
이랑이 fcd2e56129 feat(sprint-004): 4-agent handoff engine — Transport 추상화 + runner + Discord marker
Sprint 004 핵심 구현 — F3 (QA 자동 라우팅 누락) + F4 (핸드오프 불안정) 해결:

Config (범용):
- src/config/schema.ts — Zod RailsConfig (pipeline/agents/discord)
- src/config/loader.ts — YAML + 환경변수 interpolation (${VAR})
- rails.config.example.yaml — 샘플 설정

Handoff:
- src/handoff/message.ts — HandoffMessage discriminated union (plan/implement/review/deploy)
- src/handoff/transport.ts — SisterTransport 인터페이스
- src/handoff/mock-transport.ts — 시나리오 override 가능한 mock
- src/handoff/discord-transport.ts — encodeInvokeMarker / decodeResultMarker
  (HTML 주석 + json 블록 — 자매는 LLM 우회 파서로 처리)
  DiscordPoster 인터페이스 주입으로 discord.js 와 독립 테스트 가능

Orchestrator:
- src/orchestrator/runner.ts — runPipeline E2E
  state → stage 매핑 → transport.invoke → HandoffMessage → FSM 이벤트
  타임아웃/에러는 ERROR 이벤트로 변환해 FSM 에 위임

CLI:
- rails run <project> [-r requirements] [-c config.yaml] [--mock]

Tests (16 신규, 57 total pass):
- HandoffMessage discriminated union 검증
- MockTransport 기본/오버라이드 시나리오
- Discord marker encode/decode round-trip
- DiscordTransport with fake poster
- Config loader YAML + 환경변수 interpolation

검증: tsc --noEmit ✓ | vitest 57/57 ✓ | build ✓ | rails run --help ✓

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

45 lines
856 B
YAML

# hanarang-rails sample configuration.
# Copy to rails.config.yaml and tune for your environment.
pipeline:
stages:
- plan
- implement
- review
- deploy
agents:
plan:
role: plan
displayName: Planner
transport: mock # or discord, local
channelId: "" # discord channel id for this agent
timeoutMs: 30000
implement:
role: implement
displayName: Generator
transport: mock
channelId: ""
timeoutMs: 60000
review:
role: review
displayName: Evaluator
transport: mock
channelId: ""
timeoutMs: 30000
deploy:
role: deploy
displayName: Deploy
transport: mock
channelId: ""
timeoutMs: 30000
discord:
enabled: false
railsToken: ${RAILS_DISCORD_TOKEN}
guildId: ${DISCORD_GUILD_ID}
pipelineChannelId: ${DISCORD_PIPELINE_CHANNEL_ID}