Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .claude/rules/spec-hierarchy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
paths:
- "spec/**/*.md"
---

# Spec 문서 계층 구조

Belt 스펙은 3계층으로 구성된다. 각 계층은 독자와 추상화 수준이 다르다.

## 계층 정의

| 계층 | 파일 | 독자 | 질문 | 추상화 수준 |
|------|------|------|------|-----------|
| **L1 — Design** | `DESIGN-v*.md` | 의사결정자, 아키텍트 | "이 시스템은 왜 이렇게 생겼는가?" | 가장 높음 |
| **L2 — Concern** | `concerns/*.md` | 구현자 | "이 관심사는 내부적으로 어떻게 동작하는가?" | 중간 |
| **L3 — Flow** | `flows/*.md` | 기획자, 사용자 | "사용자가 X를 하면 어떻게 되는가?" | 시나리오 |

## L1 — Design (설계 개요)

**포함**: 목표, Actor, 설계 철학, 전체 상태 흐름 다이어그램, 관심사 분리 테이블, OCP 확장점, trait 경계, 버전 간 변경 요약, 구현 순서

**금지**: 구체 구현 (CLI 이름, 라이브러리, SQL DDL, Rust 코드), 특정 외부 시스템의 프로토콜/인증 방식

**원칙**:
- trait 이름까지는 OK, 메서드 시그니처는 concern으로
- "무엇을 추상화하는가"는 OK, "어떻게 연동하는가"는 concern으로
- 다이어그램에 모듈/컴포넌트 이름은 OK, 내부 구현 흐름은 concern으로

## L2 — Concern (관심사별 상세)

**포함**: trait 시그니처, 의사코드, DB 스키마 (DDL), 도메인 enum 정의, 설정 yaml 상세, 알고리즘 상세, 수용 기준 체크리스트, 구체 구현 방식 (CLI subprocess, in-process 등)

**금지**: 사용자 시나리오 (flow로), 설계 철학 반복 (design 참조)

**원칙**:
- 구현자가 이 문서만 보고 구현할 수 있어야 한다
- 각 concern은 독립적 — 다른 concern을 읽지 않아도 이해 가능 (참조 링크는 제공)
- 수용 기준은 이 계층에 위치

## L3 — Flow (사용자 플로우)

**포함**: 시나리오별 단계, 사용자 행동 → 시스템 반응, TUI/CLI 출력 예시, 에러 시나리오

**금지**: 내부 구현 상세 (concern으로), trait/DB 스키마

**원칙**:
- "사용자가 X를 하면 Y가 보인다" 수준
- 내부 모듈이 어떻게 동작하는지는 concern 참조로 위임

## 정보가 중복될 때

동일 개념이 여러 계층에 등장하면:
- L1: 개념의 존재와 역할만 (1-2문장)
- L2: 상세 정의와 동작 방식
- L3: 사용자 관점에서의 경험

예시 — Stagnation Detection:
- L1 (DESIGN): "실패 패턴을 감지하고 사고를 전환하여 재시도한다" + 전체 흐름에서의 위치
- L2 (stagnation.md): SimilarityJudge trait, CompositeSimilarity, 알고리즘 상세, 페르소나 정의, 설정 yaml
- L3 (flow-04): "handler가 3회 실패하면 → stagnation 분석 → lateral plan이 주입된 retry → 사람에게 lateral report 포함된 HITL"
422 changes: 422 additions & 0 deletions spec/draft/DESIGN-v6.md

Large diffs are not rendered by default.

61 changes: 61 additions & 0 deletions spec/draft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Spec v6 Draft

> **Date**: 2026-04-04
> **Status**: Draft
> **구조**: 설계 개요 + 관심사별 상세 스펙 + 사용자 플로우

## 핵심 변경 (v5 → v6)

- **Stagnation Detection**: 실패 횟수가 아니라 실패 패턴(SPINNING, OSCILLATION)을 감지하여 escalation 가속
- **Daemon 모듈 분리**: 단일 daemon.rs → Advancer + Executor + HitlService + StagnationDetector 모듈
- **Phase 전이 캡슐화**: `item.phase` 직접 대입 금지, `QueueItem::transit()` 메서드 강제
- **ItemContext 확장**: `source_data: serde_json::Value` 추가 — 새 DataSource 추가 시 코어 변경 0
- **hitl_terminal_action 타입 안전**: `Option<String>` → `Option<EscalationAction>`
- **Dependency Gate DB 기반**: in-memory → DB 조회, 재시작 시 순서 보장
- **Evaluator per-item 판정**: workspace 배치 → per-work_id 개별 LLM 판정

## 설계 문서

- **[DESIGN-v6.md](./DESIGN-v6.md)** — 설계 철학 + 전체 구조 개요 (간결)

## 관심사별 상세 스펙 (concerns/)

"이 시스템은 내부적으로 어떻게 동작하지?" — 구현자 대상

| 문서 | 설명 |
|------|------|
| [QueuePhase 상태 머신](./concerns/queue-state-machine.md) | 8개 phase 전이, **전이 캡슐화**, worktree 생명주기, on_fail 조건 |
| [Daemon](./concerns/daemon.md) | **내부 모듈 구조**, 실행 루프, **DB dependency gate**, concurrency, graceful shutdown |
| [Stagnation Detection](./concerns/stagnation.md) | **v6 신규** — 4가지 정체 패턴, 해시 기반 탐지, escalation 가속 |
| [DataSource](./concerns/datasource.md) | 외부 시스템 추상화 trait + **source_data** + 워크플로우 yaml |
| [AgentRuntime](./concerns/agent-runtime.md) | LLM 실행 추상화 trait + Registry |
| [Agent 워크스페이스](./concerns/agent-workspace.md) | 대화형 에이전트 + **per-item evaluate** + slash command |
| [Cron 엔진](./concerns/cron-engine.md) | 주기 실행 + **per-item evaluate** + 품질 루프 |
| [CLI 레퍼런스](./concerns/cli-reference.md) | 3-layer SSOT + `belt context` + 전체 커맨드 트리 |
| [Cross-Platform](./concerns/cross-platform.md) | OS 추상화 (ShellExecutor, DaemonNotifier) |
| [Distribution](./concerns/distribution.md) | 배포 전략 |
| [Data Model](./concerns/data-model.md) | SQLite 스키마, **StagnationPattern enum**, **EscalationAction FromStr**, **source_data** |

## 사용자 플로우 (flows/)

"사용자가 X를 하면 어떻게 되지?" — 시나리오 기반, 기획자/사용자 대상

| # | Flow | 설명 |
|---|------|------|
| 01 | [온보딩](./flows/01-setup.md) | workspace 등록 → 컨벤션 부트스트랩 |
| 02 | [스펙 생명주기](./flows/02-spec-lifecycle.md) | 스펙 등록 → 이슈 분해 → 완료 판정 |
| 03 | [이슈 파이프라인](./flows/03-issue-pipeline.md) | handlers 실행 → **stagnation detection** → evaluate → on_done |
| 04 | [실패 복구와 HITL](./flows/04-failure-and-hitl.md) | **stagnation 가속** → escalation → on_fail → 사람 개입 |
| 05 | [모니터링](./flows/05-monitoring.md) | TUI + CLI + /agent 시각화 + **stagnation 표시** |

## 이슈 매핑

| 이슈 | 주요 반영 문서 |
|------|-------------|
| #723 Stagnation/Oscillation 탐지 | stagnation.md, daemon.md, data-model.md, flow-04, DESIGN |
| #717 Daemon 내부 모듈 분리 | daemon.md, DESIGN |
| #718 Phase 전이 캡슐화 | queue-state-machine.md, data-model.md, DESIGN |
| #719 ItemContext source_data | data-model.md, datasource.md |
| #720 hitl_terminal_action 타입 | data-model.md, flow-04 |
| #721 Dependency Gate DB 기반 | daemon.md |
| #722 Evaluator per-item 판정 | cron-engine.md, agent-workspace.md, daemon.md |
138 changes: 138 additions & 0 deletions spec/draft/concerns/agent-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# AgentRuntime — LLM 실행 추상화

> LLM 실행 시스템(Claude, Gemini, Codex, ...)을 추상화한다.
> 새 LLM 추가 = 새 AgentRuntime impl, 코어 변경 0 (OCP).

---

## trait 정의

```rust
#[async_trait]
pub trait AgentRuntime: Send + Sync {
fn name(&self) -> &str;
async fn invoke(&self, request: RuntimeRequest) -> RuntimeResponse;
fn capabilities(&self) -> RuntimeCapabilities;
}

pub struct RuntimeRequest {
pub working_dir: PathBuf,
pub prompt: String,
pub model: Option<String>,
pub system_prompt: Option<String>,
pub structured_output: Option<StructuredOutput>,
pub session_id: Option<String>,
}

pub struct RuntimeResponse {
pub exit_code: i32,
pub stdout: String,
pub stderr: String,
pub duration: Duration,
pub token_usage: Option<TokenUsage>,
pub session_id: Option<String>,
}
```

handler의 prompt 타입 액션이 실행될 때 AgentRuntime.invoke()를 경유한다. `working_dir`에는 worktree 경로가 설정된다.

### Token usage 기록

RuntimeResponse의 `token_usage`는 Daemon이 `token_usage` 테이블에 자동 저장한다 (work_id, workspace, runtime, model, input/output tokens, duration). `belt status`와 TUI Dashboard의 Runtime 패널에서 집계하여 표시한다.

---

## 의존성 방향

```
core/runtime.rs (trait + DTO)
↑ impl
infra/runtimes/
├── claude.rs
├── gemini.rs
├── codex.rs
└── custom.rs

core → infra 방향 의존 없음.
```

---

## 모델 결정 우선순위

```
1. RuntimeRequest.model ← 호출 시 명시 (최우선)
2. handler의 runtime/model ← DataSource state config
3. workspace yaml의 runtime 기본값
4. 런타임 내장 기본 모델
```

---

## core 옵션 → CLI 매핑

| core 옵션 | Claude | Gemini | Codex |
|-----------|--------|--------|-------|
| `model` | `--model <model>` | `-m <model>` | `-m <model>` |
| `system_prompt` | `--append-system-prompt` | prompt prepend | prompt prepend |
| `structured_output` | `--output-format json` + `--json-schema` | `--output-format json` | `--output-schema <file>` + `--json` |
| `working_dir` | `current_dir()` | `current_dir()` | `--cd <dir>` |
| `session_id` | `--resume <uuid>` | `--resume <id>` | `codex exec resume <id>` |

---

## RuntimeRegistry

```rust
pub struct RuntimeRegistry {
runtimes: HashMap<String, Arc<dyn AgentRuntime>>,
default_name: String,
}

impl RuntimeRegistry {
pub fn resolve(&self, name: &str) -> Arc<dyn AgentRuntime> {
self.runtimes.get(name)
.unwrap_or(&self.runtimes[&self.default_name])
.clone()
}
}
```

어떤 런타임을 사용할지는 workspace yaml의 handler에서 지정한다.

---

## 설정

```yaml
runtime:
default: claude
claude:
model: sonnet
gemini:
model: pro
```

---

## Handler에서의 사용

workspace yaml의 handler가 prompt 타입이면 AgentRuntime.invoke()를 경유:

```yaml
states:
analyze:
handlers:
- prompt: "이슈를 분석해줘"
runtime: claude # 이 handler는 Claude 사용
model: haiku # haiku 모델로
- prompt: "PR을 리뷰해줘"
runtime: gemini # 이 handler는 Gemini 사용
```

---

### 관련 문서

- [DESIGN-v5](../DESIGN-v5.md) — 전체 아키텍처
- [DataSource](./datasource.md) — handler에서 AgentRuntime 사용
Loading
Loading