Files
hanarang-rails/.plans/sprints/SPRINT-001-skeleton.md
이랑이 bac114d469 docs(plans): Sprint 000 — 전체 플랜 문서 세트 작성
- CLAUDE.md 를 .claude/rules/ 4파일로 분할 (project/stack/principles/workflow)
- Plans.md 루트 인덱스 (스프린트 목차 + 참조만)
- hooks/ pre/post-tool.sh 스켈레톤 (no-op, Sprint 002에서 구현)
- .plans/OVERVIEW.md — 목표/범위/성공기준 8개
- .plans/failure-audit.md — F1~F6 실패 감사 (증거 기반)
- .plans/design/ 6개 문서:
  * state-machine.md (XState v5 FSM 설계)
  * sprint-contract.md (Zod schema + validator)
  * skill-enforcement.md (4계층 방어)
  * handoff.md (상태 전이 기반 자매 통신)
  * retry-policy.md (backoff + escalation)
  * qa-template.md (체크리스트 runtime)
- .plans/sprints/ 8개 스프린트 명세 (SPRINT-000~007)
- .plans/migration/from-hanarang-harness.md (자산 매트릭스 + 단계별 가이드)

총 17개 문서, 약 2146 lines.

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

4.5 KiB

SPRINT-001 — 스켈레톤: XState FSM + orchestrator + CLI

목표: 결정론적 파이프라인의 뼈대를 세운다. XState 머신이 메모리에서 돌고, SQLite 에 상태가 저장되고, rails status CLI 로 조회 가능해야 한다.

Type

scaffold

Prerequisites

  • Sprint 000 완료
  • Node 22, pnpm 설치됨
  • .plans/design/state-machine.md 확정

Scope

  • package.json / tsconfig.json (strict + noUncheckedIndexedAccess)
  • Core 디렉토리 구조: src/orchestrator/, src/contract/, src/cli/, tests/
  • XState v5 머신 정의 (src/orchestrator/machine.ts)
  • Zod 이벤트/컨텍스트 스키마 (src/orchestrator/events.ts)
  • SQLite 스키마 + migration (src/orchestrator/store.ts)
  • citty CLI 뼈대 (rails <subcommand>)
  • rails start — 빈 파이프라인 시작
  • rails status — 현재 상태 표시
  • Vitest 테스트: 머신 상태 전이 단위 테스트 (성공 경로 1건 + 에러 경로 1건)

Non-Goals

  • 실제 자매 spawn (Sprint 004)
  • Sprint Contract validator (Sprint 003)
  • Skill enforcement hook 로직 (Sprint 002)
  • 재시도 policy 실구현 (Sprint 005)
  • QA runtime (Sprint 006)
  • 디스코드 브릿지 (Sprint 004 또는 별도)

Tasks

# 내용 DoD Depends Status
1.1 package.json + pnpm-lock.yaml + 의존성 설치 pnpm install 성공 cc:TODO
1.2 tsconfig.json strict + noUncheckedIndexedAccess pnpm tsc --noEmit 통과 1.1 cc:TODO
1.3 디렉토리 구조 생성 (src/, tests/, fixtures/) ls src/ 기대대로 1.1 cc:TODO
1.4 src/orchestrator/events.ts — Zod 이벤트 스키마 타입체크 통과 1.2 cc:TODO
1.5 src/orchestrator/context.ts — FSM context 타입 타입체크 통과 1.4 cc:TODO
1.6 src/orchestrator/machine.ts — XState v5 머신 (stub actor) createActor 성공 1.5 cc:TODO
1.7 src/orchestrator/store.ts — better-sqlite3 + 스키마 + prepared statements 테이블 4개 생성됨 1.1 cc:TODO
1.8 src/orchestrator/persist.ts — FSM snapshot ↔ SQLite 변환 snapshot round-trip 테스트 통과 1.6, 1.7 cc:TODO
1.9 src/cli/index.ts — citty 진입점 pnpm rails --help 출력 1.1 cc:TODO
1.10 src/cli/start.tsrails start <projectName> 파이프라인 생성, ULID 반환 1.9, 1.8 cc:TODO
1.11 src/cli/status.tsrails status [<id>] 현재 상태 표 출력 1.9, 1.8 cc:TODO
1.12 tests/machine.test.ts — 성공 경로 + 에러 경로 2개 이상 pass 1.6 cc:TODO
1.13 tests/store.test.ts — snapshot round-trip 1개 이상 pass 1.8 cc:TODO
1.14 src/logger.ts — pino 구조화 로거 + pipelineId 필드 로그 JSON 형식 확인 1.1 cc:TODO
1.15 src/env.ts — Zod 검증 env 환경변수 검증 실패 시 throw 1.1 cc:TODO
1.16 README 실행 방법 섹션 업데이트 ## 실행 방법 존재 cc:TODO

Definition of Done

자동 검증 (contract validator)

  • pnpm install exit 0
  • pnpm tsc --noEmit exit 0
  • pnpm test 전체 통과 (머신 + store 최소 3개)
  • pnpm rails --help exit 0 + 출력에 start, status 포함
  • pnpm rails start test-project → ULID 출력
  • pnpm rails status <id>idle 또는 planning 상태 표시
  • SQLite 파일 (data/rails.db) 생성 확인
  • package.json lockfile 이 pnpm-lock.yaml (yarn/npm 아님)

수동 검증 (다랑이 manual)

  • 아무 파일에도 console.* 호출 없음 (pino 사용)
  • 아무 파일에도 any 타입 없음 (Zod 경계 제외)
  • 모든 외부 입력에 Zod 검증 존재
  • 에러 처리에 Result / neverthrow 또는 명시적 try/catch + 재던지기
  • .claude/rules/stack.md 의 코딩 룰 전수 준수

환경 전제

  • node --version ≥ 22
  • pnpm --version ≥ 9
  • /home/erang/hanarang-rails/ 쓰기 권한

Risks

  • XState v5 + TypeScript strict + Zod 조합이 typegen 세팅 초기 삽질 가능 → 완화: fixture 예제 따라하기
  • better-sqlite3 네이티브 빌드 — Node 22 ABI 대응 필요 → 완화: @types/better-sqlite3 + build-from-source 옵션
  • FSM snapshot round-trip 테스트가 XState 내부 구현 의존 → 완화: public API (getPersistedSnapshot / restore) 만 사용

Exit Criteria

  • 모든 태스크 cc:완료
  • pnpm test 전부 pass
  • Plans.md 에서 SPRINT-001 Status 가 cc:완료 [hash]
  • feature 브랜치 머지됨 (PR + 다랑이 QA)