Files
hanarang-rails/docs/migration-guide.md
이랑이 2cadb3e0df feat(sprint-007): 마이그레이션 도구 + 운영 문서 + v0.1.0 릴리즈 준비
Sprint 007 전체 구현 — 마지막 스프린트. 프로젝트 완성:

CLI:
- rails doctor — 환경 헬스체크 (Node/pnpm/git/env/프로젝트 파일)
- rails scaffold [dir] — 신규 프로젝트 .plans/ 구조 생성
- rails migrate from-hanarang-harness <path> — 레거시 아카이브 스캐너
  agents/scripts/workflows 분류 (portable vs deprecated)
  xhigh 참조 경고 등 위험 패턴 감지

Docs (신규 3종):
- docs/migration-guide.md — 레거시 하네스 → rails 단계별 이전 가이드
- docs/operations.md — PM2, health check, 트러블슈팅, DB 유지보수
- docs/discord-setup.md — 봇 생성, DiscordPoster 구현 예시,
  marker 프로토콜 완전 명세

README 대폭 업데이트:
- v0.1.0 상태 선언
- 빠른 시작 가이드
- CLI 13 서브커맨드 목록
- 문서 링크

Tests (4 신규, 105 total pass):
- 마이그레이션 스캐너 (agents/scripts/workflows 감지)
- node_modules/.git 제외
- 빈 아카이브 처리
- scaffold 디렉토리 구조 검증

검증: tsc --noEmit ✓ | vitest 105/105 ✓ | build ✓
       rails doctor → 정상 출력 ✓
       rails --help → 13 subcommands ✓

마감 상태:
- F1~F6 모든 실패 모드 코어에서 해결
- 7 스프린트 완료 (000: 계획, 001~006: 코어, 007: 릴리즈)
- 105 테스트, 19 문서 (.plans/) + 3 운영 문서 (docs/)

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

181 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Migration Guide
> How to move from an existing agent pipeline (e.g., a Lobster-based `hanarang-harness` install) to `hanarang-rails`.
## Summary
`hanarang-rails` replaces the legacy "권고 기반" pipeline with a **deterministic, contract-enforced** one. The migration is safe: nothing in the archive is deleted, and rails can run side-by-side until you cut over.
## Before you start
- **Back up the old install.** Keep the archive read-only; don't delete it.
- **Install rails on a neutral host** — ideally the same machine that holds the SSOT repository, not one of the agent workers.
- **Confirm Node 22+ and pnpm are available** via `rails doctor`.
## Step 0 — Install rails
```bash
bash install.sh --dir /path/to/hanarang-rails --repo <your-rails-repo-url>
cd /path/to/hanarang-rails
cp .env.example .env # fill DATABASE_URL, DISCORD_TOKEN, etc.
pnpm prisma migrate deploy
pnpm rails doctor
```
## Step 1 — Scan the archive
```bash
rails migrate from-hanarang-harness /path/to/hanarang-harness-archive
```
This reports:
- Agents (md files) — candidates to port
- Scripts — portable vs deprecated (bridge.sh is deprecated)
- Workflows — Lobster files are flagged as deprecated
- Warnings — e.g., any `xhigh` thinking tier reference (forbidden)
No files are modified. Review the report and decide.
## Step 2 — Bring over agent definitions
Copy the agent markdown files you want to keep into the rails `agents/` directory. Rails does not prescribe a naming scheme; `rails.config.yaml` maps **stage****agent**, so you can keep role-specific personas.
```bash
mkdir -p agents/
cp /path/to/archive/agents/*.md agents/
```
Review each file and remove anything that references:
- `xhigh` thinking tier (forbidden in rails — causes infinite waits)
- Mention-based handoff instructions
- Direct discord bot behavior (rails now posts on their behalf)
## Step 3 — Port scaffolding
The legacy `scaffold.sh` is now `rails scaffold`:
```bash
rails scaffold /path/to/new-project --name my-project
```
This creates `.plans/` with the standard directory structure (`design/`, `sprints/`, `migration/`) plus a root `Plans.md`.
## Step 4 — Wire `rails.config.yaml`
```yaml
pipeline:
stages: [plan, implement, review, deploy]
agents:
plan:
role: plan
displayName: Planner
transport: discord
channelId: ${PLAN_CHANNEL}
timeoutMs: 30000
implement:
role: implement
displayName: Generator
transport: discord
channelId: ${IMPL_CHANNEL}
timeoutMs: 60000
review:
role: review
displayName: Evaluator
transport: discord
channelId: ${REVIEW_CHANNEL}
timeoutMs: 30000
deploy:
role: deploy
displayName: Deploy
transport: local
timeoutMs: 60000
discord:
enabled: true
railsToken: ${RAILS_DISCORD_TOKEN}
guildId: ${DISCORD_GUILD_ID}
pipelineChannelId: ${PIPELINE_THREAD_PARENT}
```
All secrets live in `.env`. The config file uses `${VAR}` interpolation — no token bytes in the repo.
## Step 5 — Update agent runtimes
Each agent host (e.g., a sister container) needs one change to its message handler:
```js
// Pseudocode — plug into your agent's discord event handler
onDiscordMessage(msg) {
if (msg.content.includes("<!-- rails:invoke v1 -->")) {
const req = extractJsonBlock(msg.content, "rails:invoke");
// Structured pipeline mode — LLM 우회
const result = await handleRailsInvoke(req);
await postResultMarker(msg.channel, result);
return;
}
// Otherwise: existing free-form conversation path
llmRespond(msg);
}
```
See `docs/discord-setup.md` for the full marker format.
## Step 6 — Cutover
1. **Smoke test with mock transport** first:
```bash
rails run --mock test-project -r "hello world"
rails status
```
This exercises the full FSM without touching real agents.
2. **Switch one stage at a time to discord**:
```yaml
agents:
plan:
transport: discord # flip this first
implement:
transport: mock # keep others on mock until plan is green
```
3. **Monitor escalations**:
```bash
rails status <pipeline-id>
```
Any unexpected escalation triggers discord alert (if configured).
4. **Disable legacy mention-based handoff** on the old agents once all stages run through rails.
## Step 7 — Decommission legacy bridge
After rails handles 100% of traffic:
1. Stop the old `bridge.sh` process(es).
2. Keep the archive as read-only reference.
3. Remove any cron jobs or systemd units that referenced the old install.
## Rollback
If rails fails badly:
```bash
rails abort <pipeline-id> # stop the misbehaving pipeline
pm2 stop hanarang-rails # stop the orchestrator
# Start the legacy bridge again if it's still present
```
The SSOT repository is untouched — both systems write to the same Gitea.
## Known limitations (v0.1.0)
- **Discord bot wiring requires an operator task.** Rails ships the `DiscordTransport` class but does not auto-connect discord.js; you plug in a client via the `DiscordPoster` interface. A default implementation will ship in v0.2.0.
- **Gitea webhook receiver** is scaffolded but not yet exposed as an HTTP endpoint in `rails serve` — tracked for v0.2.0.
- **Manual QA checks** are stubbed (SKIPPED by default). Provide a `manualResolver` to `runQaTemplate` to wire up a reviewer LLM.
## Further reading
- [`.plans/failure-audit.md`](../.plans/failure-audit.md) — why rails exists (F1F6)
- [`.plans/design/`](../.plans/design/) — architecture docs
- `docs/operations.md` — day-to-day operations guide