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
229 changes: 115 additions & 114 deletions spec/draft/DESIGN-v6.md

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions spec/draft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

## 핵심 변경 (v5 → v6)

- **Stagnation Detection**: 실패 횟수가 아니라 실패 패턴(SPINNING, OSCILLATION)을 감지하여 escalation 가속
- **LifecycleHook 분리**: on_done/on_fail/on_enter를 yaml script에서 `LifecycleHook` trait으로 분리. handler(작업)와 hook(반응) 관심사 분리. DataSource별 impl, workspace별 바인딩, lazy 로딩
- **Daemon = CPU**: yaml script 실행기 → 상태 머신 CPU. hook 트리거만, 실행 책임은 Hook impl이 소유
- **Stagnation Detection**: 실패 횟수가 아니라 실패 패턴(SPINNING, OSCILLATION)을 감지
- **Daemon 모듈 분리**: 단일 daemon.rs → Advancer + Executor + HitlService + StagnationDetector 모듈
- **Phase 전이 캡슐화**: `item.phase` 직접 대입 금지, `QueueItem::transit()` 메서드 강제
- **ItemContext 확장**: `source_data: serde_json::Value` 추가 — 새 DataSource 추가 시 코어 변경 0
Expand All @@ -26,11 +28,13 @@
|------|------|
| [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 가속 |
| [Evaluator](./concerns/evaluator.md) | **v6 신규** — Progressive Evaluation Pipeline, Evaluate before Execute |
| [Stagnation Detection](./concerns/stagnation.md) | **v6 신규** — 4가지 정체 패턴, 해시 기반 탐지 |
| [LifecycleHook](./concerns/lifecycle-hook.md) | **v6 신규** — 상태 전이 반응 trait, handler/hook 분리, lazy 로딩 |
| [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** + 품질 루프 |
| [Cron 엔진](./concerns/cron-engine.md) | 주기 실행 + 품질 루프 (evaluate는 Daemon tick으로 이동) |
| [CLI 레퍼런스](./concerns/cli-reference.md) | 3-layer SSOT + `belt context` + 전체 커맨드 트리 |
| [Cross-Platform](./concerns/cross-platform.md) | OS 추상화 (ShellExecutor, DaemonNotifier) |
| [Distribution](./concerns/distribution.md) | 배포 전략 |
Expand All @@ -44,14 +48,15 @@
|---|------|------|
| 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 → 사람 개입 |
| 03 | [이슈 파이프라인](./flows/03-issue-pipeline.md) | handlers 실행 → **stagnation detection** → evaluate → hook.on_done |
| 04 | [실패 복구와 HITL](./flows/04-failure-and-hitl.md) | **stagnation + lateral thinking** → escalation → hook 트리거 → 사람 개입 |
| 05 | [모니터링](./flows/05-monitoring.md) | TUI + CLI + /agent 시각화 + **stagnation 표시** |

## 이슈 매핑

| 이슈 | 주요 반영 문서 |
|------|-------------|
| 신규 LifecycleHook 분리 | lifecycle-hook.md, datasource.md, daemon.md, DESIGN |
| #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 |
Expand Down
46 changes: 20 additions & 26 deletions spec/draft/concerns/agent-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,24 @@
handler 전부 성공 → Completed
evaluate cron (force_trigger로 즉시 실행 가능):
for item in queue.get(Completed):
belt agent -p "아이템 {work_id}의 완료 여부를 판단해줘.
belt context {work_id} --json 으로 컨텍스트를 확인하고,
belt queue done {work_id} 또는 belt queue hitl {work_id} 를 실행해줘"
Evaluator (Daemon tick에서 Executor보다 먼저 실행):
Progressive Pipeline:
Stage 1: Mechanical (cargo test 등, 비용 0)
→ 실패 시 Retry (LLM 안 부름)
Stage 2: Semantic (LLM 1회, belt agent -p)
→ LLM이 belt context로 컨텍스트 조회 후 판정
│ LLM이 해당 아이템의 belt context로 컨텍스트 조회 후 CLI 도구로 결정:
├── Done → hook.on_done() 트리거
│ ├── hook 성공 → Done (worktree 정리)
│ └── hook 실패 → Failed (worktree 보존)
├── belt queue done $WORK_ID
│ → Daemon이 on_done script 실행
│ ├── script 성공 → Done (worktree 정리)
│ └── script 실패 → Failed (worktree 보존, 로그 기록)
└── belt queue hitl $WORK_ID --reason "..."
→ HITL 이벤트 생성 → 사람 대기 (worktree 보존)
└── HITL → HITL 이벤트 생성 → 사람 대기 (worktree 보존)
```

- evaluate cron: `interval 60s + force_trigger on Completed 전이`
- LLM이 JSON을 파싱하는 게 아니라, 직접 `belt queue done/hitl` CLI를 호출하여 상태를 전이한다
- Evaluator는 Daemon tick의 정규 단계. 상세: [Evaluator](./evaluator.md)
- SemanticStage에서 LLM이 `belt queue done/hitl` CLI를 직접 호출하여 상태를 전이한다
- 개별 판정 실패 시 해당 아이템만 Completed에 머물고, 다른 아이템 판정에 영향 없다
- `batch_size`로 한 tick에서 처리할 최대 아이템 수를 제한한다
- evaluate LLM 호출도 `daemon.max_concurrent` slot을 소비한다

---

Expand Down Expand Up @@ -187,14 +184,9 @@ v4 (15개) → v5 (3개):
### classify-policy.md 로딩 경로 및 해석 (R-CW-007)

`classify-policy.md`는 LLM 에이전트가 큐 아이템을 Done / HITL로 분류할 때
참조하는 정책 문서다. 두 가지 형태로 존재한다:

| 파일 | 위치 | 소비자 | 용도 |
|------|------|--------|------|
| `classify-policy.md` | `.claude/rules/` 하위 | LLM agent (system prompt) | 자연어 분류 기준 |
| `classify-policy.yaml` | workspace root | daemon evaluator | machine-readable 라우팅 규칙 |
참조하는 자연어 정책 문서다. `.claude/rules/` 하위에 위치하며, system prompt에 주입된다.

#### 로딩 경로 (classify-policy.md)
#### 로딩 경로

`agent::resolve_rules_dir` 함수가 아래 우선순위로 **디렉토리**를 탐색한다.
첫 번째로 존재하는 디렉토리 안의 **모든 `.md` 파일**이 로드된다.
Expand Down Expand Up @@ -231,14 +223,16 @@ Priority 3: $BELT_HOME/claw-workspace/.claude/rules/ (global, belt claw init)
| `belt hitl list --json` | HITL 목록 조회 | 대화형 세션 |
| `belt queue list --json` | 큐 목록 조회 | 대화형 세션 |

### evaluate cron과의 관계
### Evaluator와의 관계

evaluate cron은 내부적으로 각 Completed 아이템에 대해 `belt agent --workspace <path> -p "<prompt>"`를 호출한다. 이때:
Evaluator의 SemanticStage가 내부적으로 `belt agent -p`를 호출한다. 이때:
- **per-item**: 각 아이템에 대해 개별 프롬프트 발행 (v6 #722)
- LLM이 `belt context $WORK_ID`로 해당 아이템 정보를 조회
- 판단 후 `belt queue done/hitl` CLI를 직접 호출하여 상태 전이
- classify-policy.md의 state별 Done 조건이 판단 기준
- 개별 실패는 해당 아이템만 영향, `batch_size`로 tick당 처리 수 제한
- evaluate LLM 호출도 `daemon.max_concurrent` slot을 소비

상세: [Evaluator](./evaluator.md)

---

Expand Down
45 changes: 10 additions & 35 deletions spec/draft/concerns/cron-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

```
1. 인프라 유지 — hitl-timeout, log-cleanup, daily-report (결정적)
2. 품질 루프 — evaluate, gap-detection, knowledge-extract (LLM 사용)
2. 품질 루프 — gap-detection, knowledge-extract (LLM 사용)

※ evaluate는 Daemon tick 루프의 정규 단계로 이동. 상세: [Evaluator](./evaluator.md)
```

---
Expand Down Expand Up @@ -57,7 +59,6 @@ gap 발견 → DataSource에서 open 아이템 조회 (Pending/Ready/Running)

| Job | 주기 | 동작 |
|-----|------|------|
| evaluate | 60초 | 완료 아이템 분류 (**per-item**, Done or HITL) — `belt agent -p` |
| gap-detection | 1시간 | 스펙-코드 대조, gap 발견 시 이슈 생성 |
| knowledge-extract | 1시간 | merged PR 지식 추출 |

Expand All @@ -70,45 +71,19 @@ gap 발견 → DataSource에서 open 아이템 조회 (Pending/Ready/Running)

---

## Force Trigger (하이브리드 실행 모델)
## Force Trigger

evaluate는 **cron 주기 폴링 + force_trigger 즉시 실행**의 하이브리드 모델로 동작한다:
force_trigger는 cron job을 다음 tick에서 우선 실행하도록 스케줄링한다.

```
1. 주기 폴링: evaluate cron이 60초마다 Completed 아이템을 스캔
2. 즉시 실행: handler 성공 → Completed 전이 → force_trigger("evaluate")
→ last_run_at = NULL → 다음 tick(10초 이내)에서 즉시 실행
force_trigger(job_name):
job.last_run_at = NULL → 다음 tick에서 즉시 실행
```

- **force_trigger**는 동기적으로 evaluate를 실행하지 않는다. cron의 `last_run_at`을 리셋하여 다음 tick에서 우선 실행되도록 스케줄링한다.
- evaluate LLM 호출도 concurrency slot을 소비한다 (`daemon.max_concurrent`에 `active_evaluate_count`가 포함됨).
- 주기 폴링은 force_trigger가 누락된 경우(예: 프로세스 재시작)의 안전망 역할을 한다.

> handler 실패 시에는 force_trigger 없이 즉시 escalation 정책이 적용된다 (evaluate 불필요).

---

## 스크립트 구조 (v6 per-item evaluate, #722)

evaluate cron은 **per-work_id 단위**로 각 Completed 아이템에 대해 개별 LLM 판정을 실행한다.

```bash
#!/bin/bash
# Guard: Completed 상태 아이템 있을 때만
ITEMS=$(belt queue list --workspace "$WORKSPACE" --phase completed --json)
COUNT=$(echo "$ITEMS" | jq 'length')
if [ "$COUNT" = "0" ]; then exit 0; fi

# Per-item evaluate: 각 아이템에 대해 개별 판정
echo "$ITEMS" | jq -r '.[].work_id' | while read WORK_ID; do
belt agent --workspace "$WORKSPACE" -p \
"아이템 $WORK_ID 의 완료 여부를 판단해줘.
belt context $WORK_ID --json 으로 컨텍스트를 확인하고,
belt queue done $WORK_ID 또는 belt queue hitl $WORK_ID 를 실행해줘"
done
```
- 동기적으로 실행하지 않는다. cron의 `last_run_at`을 리셋할 뿐.
- gap-detection 등 품질 루프 job에 사용.

> **v5 대비 변경**: 이전에는 workspace 단위로 단일 프롬프트를 발행했다. v6에서는 각 아이템에 대해 context를 포함한 개별 프롬프트를 발행하여 세밀한 판정이 가능하다. `batch_size`로 한 tick에서 처리할 최대 아이템 수를 제한한다.
> **evaluate는 v6에서 Daemon tick 정규 단계로 이동**. Completed 아이템은 Evaluator가 다음 tick에서 Progressive Pipeline으로 판정한다. 상세: [Evaluator](./evaluator.md)

---

Expand Down
Loading
Loading