# Handoff JSON 스키마 가이드 (v1.0)

## 목적

봇 간 작업 인계 시 **machine-readable evidence**를 표준화하여 silent corruption을 방지합니다.
다음 봇은 이 JSON을 직접 읽어 작업 컨텍스트를 복원하고, 어디서부터 이어받아야 하는지 파악합니다.

스키마 파일: `memory/specs/handoff-schema.json` (JSON Schema Draft 2020-12)

---

## 필드 표

| 필드 | 타입 | 필수 | 설명 | 예시 |
|------|------|------|------|------|
| `task_id` | string | ✅ | 작업 식별자 | `"task-2454"`, `"task-2454.1"` |
| `schema_version` | string | ✅ | 스키마 버전 (고정값 `"1.0"`) | `"1.0"` |
| `previous_bot` | string | ✅ | 이 핸드오프를 생성한 봇 ID | `"dev4"`, `"design"`, `"qc"` |
| `current_branch` | string | ✅ | 현재 작업 브랜치 전체 이름 | `"task/task-2454-dev4"` |
| `base_sha` | string | ✅ | 작업 시작 시점 origin/main HEAD SHA | `"f4151eeb"` |
| `head_sha` | string | ✅ | 핸드오프 시점 브랜치 HEAD SHA | `"a1b2c3d"` |
| `changed_paths` | array[string] | ✅ | origin/main 대비 변경 파일 목록 (상대 경로) | `["scripts/foo.py", "memory/specs/bar.md"]` |
| `allowed_paths` | array[string] | ✅ | 이 봇에게 허용된 경로 목록 | `["scripts/", "memory/specs/"]` |
| `forbidden_paths` | array[string] | ✅ | 이 봇에게 금지된 경로 목록 | `["scripts/start_task_guard.py"]` |
| `pending_work` | string | ⚡ | 잔여 작업 요약 (4000자 이하) | `"컴포넌트 A 스타일 미완성"` |
| `pending_work_path` | string | ⚡ | pending_work 4000자 초과 시 외부 파일 경로 | `"memory/handoffs/task-2454-pending.txt"` |
| `known_failures` | string | ⚡ | 알려진 실패/에러 요약 (4000자 이하) | `"CI lint 실패: line 42"` |
| `known_failures_path` | string | ⚡ | known_failures 4000자 초과 시 외부 파일 경로 | `"memory/handoffs/task-2454-failures.txt"` |
| `test_results` | object | ✅ | 테스트 결과 자유 형식 | `{"pytest": "passed", "ci": "pending"}` |
| `handoff_reason` | string | ✅ | 인계 사유 코드 (아래 참조) | `"interrupt"` |
| `created_at` | string | ✅ | 생성 시각 (ISO 8601 UTC) | `"2026-05-05T12:34:56Z"` |

> ⚡ = 상호 배타적 선택 필드. `pending_work` XOR `pending_work_path` (둘 다 없어도 됨, 둘 다 있으면 안 됨).
> 동일 규칙이 `known_failures` / `known_failures_path`에도 적용됩니다.

---

## 토큰 제한 정책

**4000자 제한**: `pending_work`와 `known_failures` 필드는 각각 최대 4000자입니다.

초과 시 자동 분리:
1. 내용을 `memory/handoffs/<task-id>-pending.txt` (또는 `-failures.txt`)에 저장
2. JSON에는 `pending_work_path` (또는 `known_failures_path`) 필드로 경로만 기록
3. `pending_work` (또는 `known_failures`) 인라인 필드는 제거

`create_handoff.py`가 이 분리를 자동으로 처리합니다.

---

## handoff_reason 의미

| 값 | 의미 |
|----|------|
| `interrupt` | 봇이 시간 초과 / 에러 / 컨텍스트 한계 등으로 중단. 다음 봇이 pending_work부터 이어받음 |
| `complete` | 작업 완료. 다음 단계(예: QC 검수, 머지) 담당 봇에게 인계 |
| `takeover_request` | 회장/아누가 명시적으로 봇 교체를 지시. 현 봇 즉시 작업 중단 |

---

## 사용 예시

### 예시 1: 정상 인계 (인라인 텍스트)

```json
{
  "task_id": "task-2454",
  "schema_version": "1.0",
  "previous_bot": "dev4",
  "current_branch": "task/task-2454-dev4",
  "base_sha": "f4151eeb",
  "head_sha": "a1b2c3d4",
  "changed_paths": [
    "memory/specs/handoff-schema.json",
    "memory/specs/handoff-schema.md",
    "scripts/create_handoff.py"
  ],
  "allowed_paths": ["memory/specs/", "scripts/"],
  "forbidden_paths": ["scripts/start_task_guard.py"],
  "pending_work": "test_results 자동 수집 로직 미구현. pytest 결과 파싱 추가 필요.",
  "known_failures": "없음",
  "test_results": {"py_compile": "pass", "schema_validate": "pass"},
  "handoff_reason": "complete",
  "created_at": "2026-05-05T12:34:56Z"
}
```

### 예시 2: 4000자 초과 시 path 분리

```json
{
  "task_id": "task-2454",
  "schema_version": "1.0",
  "previous_bot": "dev4",
  "current_branch": "task/task-2454-dev4",
  "base_sha": "f4151eeb",
  "head_sha": "a1b2c3d4",
  "changed_paths": ["memory/specs/handoff-schema.json"],
  "allowed_paths": [],
  "forbidden_paths": [],
  "pending_work_path": "memory/handoffs/task-2454-pending.txt",
  "known_failures_path": "memory/handoffs/task-2454-failures.txt",
  "test_results": {},
  "handoff_reason": "interrupt",
  "created_at": "2026-05-05T12:34:56Z"
}
```

---

## 검증 방법

```python
import json
import jsonschema

schema = json.load(open("memory/specs/handoff-schema.json"))
data = json.load(open("memory/handoffs/task-2454.json"))

jsonschema.validate(data, schema)
print("PASS")
```

또는 CLI:

```bash
python3 -c "
import json, jsonschema
s = json.load(open('memory/specs/handoff-schema.json'))
d = json.load(open('memory/handoffs/task-2454.json'))
jsonschema.validate(d, s)
print('PASS')
"
```

스키마 자체 유효성 검사:

```bash
python3 -c "
import json, jsonschema
jsonschema.Draft202012Validator.check_schema(
    json.load(open('memory/specs/handoff-schema.json'))
)
print('Schema OK')
"
```

---

## 버전 정책

- 현재 버전: `1.0` (semantic versioning)
- **하위 호환 변경** (선택 필드 추가 등): 마이너 버전 bump (예: 1.1) — `schema_version`은 유지
- **호환 깨짐 변경** (필수 필드 제거/타입 변경 등): 메이저 bump → `schema_version: "2.0"`으로 변경
- 구버전 JSON은 구버전 스키마로 검증해야 함. `schema_version` 필드로 버전 식별 가능.

---

## 생성 스크립트

`scripts/create_handoff.py`를 사용하면 git 정보 자동 수집 + 4000자 분리 + 스키마 검증을 자동으로 수행합니다.

```bash
./scripts/create_handoff.py \
  --task task-2454 \
  --reason complete \
  --pending "잔여 작업 요약" \
  --failures "알려진 실패 목록" \
  --bot dev4
```
