# 듀얼코치 파일럿 사용설명서

이 문서는 운영자가 시스템의 경계와 상태를 이해하기 위한 **비실행 요약본**입니다. 명령, API 호출 순서, 파일 편집법, 장애 복구 절차는 이 문서에 복사하지 않습니다. 실행이 필요할 때는 [프로필의 정본 `PILOT_RUNBOOK.md`](file:///home/cube/.hermes/profiles/physique-coach/workspace/checkin_cli/PILOT_RUNBOOK.md)만 사용합니다.

- 정본 버전: `2026-07-26.23` (`dual-coach-gate-d-r23`)
- 정본 canonical contract SHA-256: `sha256:fc1fdfa0e228ad15458037b246245b540d5c5c27a67cd29ab0d1c834e7e2e952`
- Hash region: canonical profile `PILOT_RUNBOOK.md`의 `<!-- BEGIN CANONICAL EXECUTABLE CONTRACT -->`와 `<!-- END CANONICAL EXECUTABLE CONTRACT -->` 사이 UTF-8 바이트(마커 줄 제외, 본문 LF 포함)이며 마커 앞 metadata는 제외합니다.
- 이 문서는 정본의 내용을 요약할 뿐이며, 실제 Telegram Gate-D나 실제 고객 활성화가 완료됐다는 뜻이 아닙니다.

## 1. 듀얼코치의 역할

고객은 등록된 공간에서 체크인을 제출하고, 트레이너는 별도로 등록된 공간에서 세션을 기록합니다. 시스템은 기록을 근거로 운영자 검토용 초안을 만들 뿐입니다. 운영자가 최신 초안을 확인하고 승인한 뒤 별도로 전송해야 고객에게 전달됩니다. AI가 고객에게 임의로 직접 전송하는 경로는 없습니다.

고객·트레이너·운영자의 데이터와 Telegram 공간은 정확한 주소와 고객 범위로 분리합니다. 이벤트 수정은 과거 기록을 덮지 않고 새 수정 기록으로 남깁니다. 안전 신호나 동의 부재가 있으면 일반 코칭을 멈추고 운영자에게 제한된 사유와 전문가 상담 안내만 알립니다.

## 2. 지금 지켜야 할 상태

- 실제 고객은 승인된 수동 Gate-D와 별도 출시 승인이 끝나기 전까지 비활성·무전송이어야 합니다.
- 자동화 검증 결과는 실제 Telegram 계정, 토큰, 공급자 영수증, 수동 리허설을 증명하지 않습니다.
- 파일럿 자동 일정은 시작일을 포함한 KST 28일입니다. 29일째는 자동 작업이 없으며, 갱신 결제는 일정 연장이 아닙니다.
- 오류·오래된 카드·손상된 장부·결과 불명은 모두 중지 사유입니다. 추측으로 고치거나 재전송하지 않습니다.

## 3. Topic 59 운영자 화면

Topic 59의 `(chat_id, topic_id)` 공간은 호스트가 모든 Telegram 업데이트 종류에 대해 먼저 예약합니다. 정확히 설정된 review 운영자 full triple만 운영자 서비스로 들어가며, 같은 공간의 다른 사용자는 거절되고 고객·트레이너·일반 모델 경로로 넘어가지 않습니다.

화면의 유일한 시작 버튼은 **`적응형 영양 검토`**이며, 동일 처리기를 사용하는 정해진 명령 별칭도 있습니다. 호스트가 현재 활성화된 적격 테스트 고객과 KST 평가일을 결정합니다. 고객 선택이 없거나 둘 이상으로 모호하면 화면은 중지 상태를 보여 줍니다.

운영자 화면은 선택·생성·조회·메모 수정·보류·해제·승인·활성화·전송 권한 켜기/끄기·전송·조정·뒤로가기만 제공합니다. 원시 목적지, 임의 숫자, 고객 파일 경로, 직접 digest, 일반 append, REPL은 입력할 수 없습니다. 모든 카드는 현재 revision/digest/state와 opaque 증거만 보여 줍니다.

### review 운영자와 canonical owner

Topic 59에서 인증하는 review identity는 ingress 표면입니다. 감사와 lifecycle actor는 별도로 갱신된 canonical owner full triple입니다. 두 주소가 달라도 정상이며, 어느 하나를 다른 하나로 대신하지 않습니다. 모든 변경 직전에 권한·registry·동의·활성화·artifact·epoch를 다시 확인하고, 확인 뒤 값이 바뀌면 변경 또는 공급자 호출을 중지합니다.

### 사용자 메시지 정본

아래 세 형식은 고객·코치·운영자에게 보여 주는 문구의 기준입니다. 실제 수치와 판단은 저장된 최신 확정 기록에서 채우며, 제목·문단 순서·빈 줄·불릿 구조를 유지합니다. 내부 상태명이나 영문 reason code만 단독으로 노출하지 않습니다.

메시지는 `코드 판단 → 최코치 코칭 → 사실·안전 검증 → 윤문 → 최종 불변조건 검증 → 운영자 승인 → 고객 전달` 순서로 생성합니다. 코드가 먼저 저장된 최신 확정 기록으로 사실·수치·날짜·결정·행동·후속 확인 시점·안전 상태·승인 및 전달 상태를 고정합니다. 최코치는 이 잠긴 입력만 사용해 상태의 의미, 판단 이유, 고객이 집중할 점을 코칭 문장으로 작성하며, 결정이나 계획을 바꿀 수 없습니다.

최코치 출력이 검증을 통과한 뒤에만 별도의 윤문 단계가 설명 문장의 번역투, 기계적인 병렬 표현, 반복되는 종결어미와 호흡을 다듬습니다. 제목, 사실 불릿, 모든 수치와 날짜, 판단, 행동 목록, 후속 확인 시점, 안전·승인·전달 상태, 문단 순서는 두 LLM 모두 변경할 수 없습니다. 최코치 출력이 검증에 실패하면 아래 코드 정본으로 복귀하고, 윤문 출력이 실패하면 검증된 최코치 문장으로 복귀합니다. 재시도로 새로운 내용을 만들지 않습니다.

한국어 문체 지침은 MIT 라이선스의 [epoko77-ai/im-not-ai](https://github.com/epoko77-ai/im-not-ai)가 정리한 번역투·기계적 병렬·종결어미 반복 방지 원칙을 참고했습니다. 해당 프로젝트의 실행 스킬이나 소스 코드를 런타임 의존성으로 포함하지 않습니다.

#### 최코치 근거 기반 코칭 계약

최코치 코칭은 일반적인 LLM 상식이 아니라 정제된 공개자료 지식 레이어를 사용합니다. 원자료 983건, canonical 출처 933개, 중복 정리 후 761개는 검색·감사 근거로 보존하고, 런타임 코칭에는 안전 검토를 통과한 승인 원칙 150개만 사용합니다. 격리된 주장, 개인 시합 수치, 약물·호르몬, 극단적 수분·염분 조작은 검색 결과와 실행 지침에서 제외합니다.

처리 순서는 다음과 같이 고정합니다.

1. 코드는 고객·트레이너의 최신 확정 기록에서 목표, 추세, 순응도, 운동 수행, 회복, 누락·충돌, 안전 신호와 허용 결정을 계산해 잠급니다.
2. 현재 상황을 목표와 문제 유형으로 분류하고, 승인 원칙에서 관련 근거만 3~5개 검색합니다. 원문 전체를 프롬프트에 넣거나 원문 수치를 개인 처방으로 복사하지 않습니다.
3. 검증된 고객 기억에서 이전 약속, 실제 결과, 반복 패턴, 최근 조정과 반응만 가져옵니다. 원문 대화 전체나 추정 성향은 기억으로 사용하지 않습니다.
4. 상황별 플레이북이 먼저 확인할 근거, 허용 가능한 조정, 조정 금지 조건과 다음 확인 시점을 제한합니다.
5. 최코치는 `관찰 → 이전 흐름과 비교 → 원인 가설 → 이번 판단 → 고객 행동 → 다음 확인 기준` 순서로 코칭 설명을 작성합니다. 한 번에 1~2개 가설만 다루고, 근거가 부족하면 단정하지 않습니다.
6. 사실·안전 검증은 최코치가 사용한 원칙, 고객 기억과 플레이북이 실제 입력에 존재하는지 확인합니다. 새로운 사실·수치·결정·행동·확인 시점 또는 약화된 안전 문구가 있으면 결과 전체를 폐기합니다.
7. 윤문은 검증된 설명의 말투, 호흡, 줄바꿈과 반복 표현만 다듬습니다. 최종 불변조건 검증을 통과한 현재 revision만 운영자가 승인하고 전달할 수 있습니다.

각 코칭 revision에는 고객에게 노출하지 않는 근거 영수증을 남깁니다. 영수증에는 코드 결정 근거, 사용한 승인 원칙과 출처 클러스터, 플레이북 버전, 사용한 고객 기억, 제외된 위험 영역, 최코치·윤문 검증 결과를 기록합니다. 원문 체크인, 고객 메시지, 개인정보, 비밀값은 기록하지 않습니다.

#### 일간 체크인

```text
오늘 체크인 완료

- 체중: 78.6kg
- 섭취: 2,675kcal
- 탄수화물 335g · 단백질 160g · 지방 75g
- 운동: 웨이트 70분 · RPE 7
- 수면: 7.3시간 · 수면 질 4/5
- 컨디션: 4/5
- 소화: 정상

오늘은 운동일 목표에 가깝게 섭취했고 단백질도 충분했습니다.
체중 증가 속도도 현재 린매스업 목표 범위 안에 있습니다.

오늘 할 일

- 현재 식사량 유지
- 수분 2.8L 이상 유지
- 내일 아침 같은 조건으로 체중 측정
```

#### 주간 체크인

```text
이번 주 린매스업 리포트

- 최근 7일 평균 체중: 78.47kg
- 이전 7일 평균 체중: 78.34kg
- 주간 변화: +0.16%
- 목표 범위: +0.10~+0.25%

체중은 린매스업 목표 범위 안에서 안정적으로 증가했습니다.
현재 속도라면 불필요한 체지방 증가 위험은 높지 않습니다.

이번 주 판단: 유지

- 기준 섭취량: 2,600kcal 유지
- 단백질: 하루 160g 유지
- 운동일에는 탄수화물을 운동 전후에 우선 배치
- 다음 주에도 같은 조건으로 체중 추세 확인

급격한 증량이나 정체가 없어 이번 주에는 칼로리를 변경하지 않습니다.
```

#### 적응형 영양 운영자 검토

```text
적응형 영양 검토 · 린매스업

가상 테스트 고객 · 2026-07-27
최근 7일 평균 78.47kg · 이전 7일 평균 78.34kg
주간 체중 변화 +0.16%

목표: 주당 +0.10~+0.25%
현재 판단: 체중 증가 속도는 목표 범위

권장안

- 2,600kcal 유지
- 탄수화물 320g
- 단백질 160g
- 지방 75g

주간 탄수화물 배분

- 고탄수화물일: 2,795kcal · 탄수화물 370g · 단백질 160g · 지방 75g
- 중탄수화물일: 2,599kcal · 탄수화물 321g · 단백질 160g · 지방 75g
- 저탄수화물일: 2,459kcal · 탄수화물 286g · 단백질 160g · 지방 75g

이번 주 배치

- 월 저탄수화물
- 화 고탄수화물
- 수 중탄수화물
- 목 저탄수화물
- 금 고탄수화물
- 토 중탄수화물
- 일 저탄수화물

검토 필요

같은 날짜의 수정 전·후 식사 기록이 함께 감지되어 순응도를 확정하지 못했습니다.
최신 확정 기록을 기준으로 다시 계산해야 합니다.

고객에게는 아직 전달되지 않았습니다.

```

적응형 카드에는 `기준 매크로 → 저·중·고 탄수화물 목표 → 요일별 배치`를 한 세트로 표시합니다. 주간 총섭취량을 유지하면서 운동 부하에 따라 배분만 바꾸는 경우에도 이 세 항목을 생략하지 않습니다. 기준 열량과 매크로 환산 열량의 작은 반올림 차이는 내부 정규화 근거를 남기되, 모델이 임의 수치로 보정하지 않습니다.

운영자 버튼은 상태에 맞는 행동만 보여 줍니다. 검토가 필요하면 `최신 기록으로 다시 계산`, `현 설정 유지 승인`, `보류`, `상세 근거 보기`처럼 다음 행동을 한국어로 명확히 표시합니다.
## 4. 안전한 전송 상태

성공 문구는 `delivered`와 `sent_audited`가 모두 있을 때만 사용합니다.

- 성공: **`고객 전송과 감사 기록이 완료되었습니다.`**
- 중복 조작: **`이미 처리된 전송입니다.`**
- 결과 불명: **`전송 결과를 확인할 수 없습니다. 다시 보내지 마세요. 조정이 필요합니다.`**
- 영수증은 있으나 감사 기록이 미완료: **`고객 전송 영수증은 확인됐습니다. 재전송하지 말고 감사 기록을 복구해 주세요.`**

결과 불명과 감사 대기 상태는 재시도 금지의 terminal 상태입니다. 영수증이 이미 있으면 공급자를 다시 부르지 않고 장부만 조정합니다. 영수증이 없으면 추측한 message ID를 넣지 않고 운영자에게 사고로 올립니다.
장부에서 `reservation-started`는 영수증 없는 immutable 예약 row, `consumed`는 예약 소비 row, `receipt-started`는 공급자 `message_id`/영수증을 담은 immutable provider receipt row입니다. `receipt-started`는 한 번의 공급자 호출 결과를 보존하는 상태이지 두 번째 공급자 호출·재시도가 아닙니다. 따라서 P2는 `reservation-started → consumed → receipt-started → delivered → sent_audited`, P4는 조정 전 `reservation-started → consumed → receipt-started → delivered → audit_pending`, 조정 후 `sent_audited` 추가로 읽습니다.

## 5. 예약 일정과 재시작

예약 전송은 immutable 목적지·본문·KST 날짜와 reservation을 먼저 남긴 뒤 공급자를 최대 한 번만 호출합니다. 새 장부와 함께 구형 `.claim` tombstone을 보존하여 구버전이 다시 보내지 못하게 합니다.

시작 fence가 `ready`가 아니거나, tombstone만 있고 새 장부가 없거나, 새 장부만 있고 tombstone이 없거나, legacy claim이 결과 불명인 경우 스케줄러는 시작하지 않습니다. cutover 동안 기존 claim은 삭제하지 않고 보수적으로 `unknown`으로 이관합니다. 재시작은 기존 영수증을 조정할 수 있지만 blind retry는 허용하지 않습니다. 이 원칙의 순서와 증거 형식은 정본 §5와 §7을 따릅니다.

## 6. 읽기 전용 preflight

정본의 typed preflight는 구성, Topic 59 review triple, private mode와 symlink, 별도 테스트 프로필·봇, 세 주체의 구분, 현재 KST 창, 승인 artifact, canonical reconciliation, 모든 delivery flag, schedule/transition 장부를 **읽기만** 확인합니다. 반환값은 boolean·bounded count·digest·epoch뿐이며 계정·비밀·고객·동의·활성화·전송·메시지를 만들지 않습니다.

하나라도 누락·오래됨·충돌·손상이면 테스트를 시작하지 않습니다. preflight 통과는 사람이 계정·토큰·토픽을 준비했거나 수동 Gate-D를 수행했다는 증거가 아닙니다.

## 7. P2–P6 자동 증거의 읽는 법

각 시나리오는 이전 시나리오의 revision을 재사용하지 않는 새 child revision이며, 별도로 승인·활성화합니다. 카드에는 `테스트 전용`, 고객 label, KST day, revision, state를 표시하고 증거에는 opaque ID만 남깁니다.

| 시나리오 | 장부 결과 | 공급자 호출 | 운영자 화면 |
|---|---|---:|---|
| P2 성공 | `reservation-started → consumed → receipt-started → delivered → sent_audited` 정확히 5개. receipt-started는 두 번째 호출이 아닌 불변 영수증 row | 총 1회. 중복 탭은 추가 0회 | 완료 문구, 두 번째 탭은 이미 처리됨 |
| P3 timeout/잘못된 영수증 | `reservation-started → consumed → delivery_unknown` 정확히 3개. receipt/delivered/audit 없음 | 총 1회. 재시도 추가 0회 | 결과 불명·재전송 금지 |
| P4 공급자 성공·감사 실패 | 조정 전 `reservation-started → consumed → receipt-started → delivered → audit_pending` 5개, 조정 때 `sent_audited` 1개 추가. receipt-started는 두 번째 호출이 아닌 불변 영수증 row | 총 1회. 조정 추가 0회 | 영수증 확인·감사 복구 필요, 이후 완료 |
| P5 예약 뒤 delivery revoke | `reservation-started → delivery_unknown` 정확히 2개, 사유 `delivery_revoked_after_reservation`; consumed/receipt/delivered/audit 없음 | 0회 | 결과 불명·재전송 금지 |
| P6 예약 뒤 owner 변경 | `reservation-started → delivery_unknown` 정확히 2개, 사유 `owner_changed_after_reservation`; consumed/receipt/delivered/audit 없음 | 0회 | 결과 불명·재전송 금지 |

P5와 P6의 barrier는 자동 transport 시험용 주입점일 뿐 production 메뉴나 실제 Telegram에서 재현한다고 주장하지 않습니다. 각 행 뒤에는 장부와 호출 수를 대조하고 delivery를 끄며, 마지막에는 overlay를 되돌리고 테스트 고객을 비활성화하고 scheduler/Gateway를 멈춘 뒤 불변 증거를 보존합니다.

## 8. 안전 신호와 즉시 중지

흉통·실신·호흡 곤란 같은 긴급 신호, 통증·질환, 섭식 위험, 약물, 극단적 조작 목표가 하나라도 있거나 동의가 없으면 일반 초안과 고객 전송을 만들지 않습니다. 운영자에게 이유와 제한된 referral guidance를 알리며, 고객용 draft 버튼·request token·provider 호출은 0이어야 합니다.

전송 오류, owner 변경, 동의 철회, 토픽 혼선, 장부 손상, 운영 기간 종료 때도 같은 원칙으로 scheduler와 Gateway를 멈추고 delivery를 persisted false로 만들며, 고객을 비활성화하고, append-only 증거를 보존한 뒤 정본의 recovery 순서로 처리합니다. 기록을 지우거나 덮어써서 성공처럼 꾸미지 않습니다.

## 9. 파일럿 종료와 인간이 해야 할 일

28일 창이 끝나면 마지막 작업과 pending 영수증을 확인하고, adaptive delivery를 끄고, 테스트 고객을 비활성화하고, scheduler/Gateway를 멈추고, overlay를 rollback하고, 보존·삭제·백업 정책에 따라 처리합니다. 새로운 범위와 사람의 승인이 없으면 재개하지 않습니다.

다음은 자동화하지 않는 인간 작업입니다.

1. 별도 Telegram 테스트 계정·그룹·토픽과 테스트 봇 준비
2. 봇/provider/operator 비밀값을 승인된 secret storage에 입력·교체
3. 고객 동의·등록·활성화·보존/삭제 문서의 private 승인
4. 실제 Telegram에서 수동 Gate-D 리허설과 private opaque 증거 수집
5. 실제 고객 활성화·adaptive delivery·최종 rollout 승인
6. 법무/데이터 소유자의 삭제·보존 만료·백업 purge 결정

자동 P2–P6 결과나 preflight 통과를 수동 Gate-D 완료 또는 실제 고객 출시 승인으로 표시하지 않습니다.
