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>
5.5 KiB
Migration Guide
How to move from an existing agent pipeline (e.g., a Lobster-based
hanarang-harnessinstall) tohanarang-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 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
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
xhighthinking 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.
mkdir -p agents/
cp /path/to/archive/agents/*.md agents/
Review each file and remove anything that references:
xhighthinking 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:
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
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:
// 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
-
Smoke test with mock transport first:
rails run --mock test-project -r "hello world" rails statusThis exercises the full FSM without touching real agents.
-
Switch one stage at a time to discord:
agents: plan: transport: discord # flip this first implement: transport: mock # keep others on mock until plan is green -
Monitor escalations:
rails status <pipeline-id>Any unexpected escalation triggers discord alert (if configured).
-
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:
- Stop the old
bridge.shprocess(es). - Keep the archive as read-only reference.
- Remove any cron jobs or systemd units that referenced the old install.
Rollback
If rails fails badly:
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
DiscordTransportclass but does not auto-connect discord.js; you plug in a client via theDiscordPosterinterface. 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
manualResolvertorunQaTemplateto wire up a reviewer LLM.
Further reading
.plans/failure-audit.md— why rails exists (F1–F6).plans/design/— architecture docsdocs/operations.md— day-to-day operations guide