# Agent Reliability Live Demo

> **AI가 문서를 읽고, 사람의 승인을 받은 뒤, 실패와 재시도 속에서도 같은 업무를 한 번만 기록하도록 만든 실동작 데모입니다.**

이 저장소는 Upstage Solar 기반 문서 구조화와 검증된 workflow 제어층을 연결합니다. LLM은 문서에서 항목을 읽는 역할만 맡고, 상태 전이·필수값 검사·사람 승인·checkpoint·재시도·중복 방지는 결정론적인 코드가 맡습니다.

![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-275be8)
![Core tests](https://img.shields.io/badge/core%20tests-432%20PASS-25b890)
![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux-14233f)

## 30초 요약

- **입력:** 개인정보가 없는 합성 지출 문서
- **LLM 역할:** 공급자·청구번호·금액·날짜·요청자·목적을 strict JSON으로 추출
- **통제층 역할:** 누락값 검사, 사람 승인, SQLite checkpoint, 재시도, idempotency
- **데모 포인트:** 저장 후 응답이 사라져 같은 요청을 다시 보내도 실제 기록은 1회
- **검증 범위:** 고유 시험 432개, 권위 검증 14/14, 플랫폼 행 10/10, exact-final 24/24

## 화면에서 확인할 수 있는 것

1. 문서를 분석하면 외부 기록을 실행하지 않고 `APPROVAL_PENDING`에서 멈춥니다.
2. 사용자가 승인하면 새 runtime이 SQLite checkpoint를 읽어 이어서 실행합니다.
3. `저장 전 일시 오류`를 고르면 안전하게 재시도합니다.
4. `저장 후 응답 유실`을 고르면 이미 저장된 결과를 재사용합니다.
5. 같은 실행 요청을 다시 보내도 `실제 기록 횟수 1`, `중복 기록 0`을 유지합니다.

## 아키텍처

```mermaid
flowchart LR
    A[합성 지출 문서] --> B[Upstage Solar Pro 3]
    B -->|strict JSON| C[Schema + Policy Gate]
    C -->|누락 또는 위험| X[Fail closed]
    C --> D[사람 승인 대기]
    D -->|승인 증거| E[Checkpoint Resume]
    E --> F[Idempotent Tool]
    F -->|응답 유실·재시도| G[Persisted Result Reuse]
    G --> H[Independent Verifier]
```

LLM 출력은 실행 권한이 아닙니다. 허용된 schema를 통과한 데이터만 정책 게이트로 들어가고, 실제 변경은 승인 증거와 고정된 인자가 일치할 때만 수행됩니다.

## 공개 웹과 Windows 로컬 실행

가장 쉬운 체험 방법은 공개 웹주소를 여는 것입니다. 설치, CMD 실행, 개인 키 입력이 필요 없습니다.

https://upstage-solar-reliability-demo-20260718.pages.dev/

Windows 로컬 패키지를 사용할 때만 `UPSTAGE_SOLAR_LOCAL_DEMO_WINDOWS.zip`의 압축을 먼저 완전히 풀고, 최상위 폴더의 `START_HERE_UPSTAGE_LIVE_DEMO.cmd`를 더블클릭한 뒤 Upstage Studio의 `Secret key`를 한 번 붙여넣습니다.

- 실제 Solar Pro 3 호출
- 문서 구조화 결과 검증
- 승인 전 외부 기록 0회 확인
- 사람 승인과 SQLite checkpoint 재개
- 저장 후 응답 유실 fault 주입
- 동일 요청 replay 후 기록 1회·중복 0회 확인
- `evidence/LIVE_PROVIDER_E2E_RECEIPT.json` 생성
- Secret key가 빠진 새 제출 ZIP과 SHA-256 자동 생성
- 최종 ZIP·PDF·PASS 영수증을 Windows `Downloads` 폴더에 자동 저장
- 완료된 결과 화면을 기본 브라우저로 자동 열기

Secret key는 PowerShell의 보안 입력으로 받아 현재 프로세스 메모리에서만 사용하고, 종료 시 환경변수에서 제거합니다. HTML·JavaScript·SQLite·영수증·ZIP·명령 기록에는 저장하지 않습니다.

로컬 실행 요구사항은 Python 3.11 이상입니다. Secret key 전체를 복사할 수 없다면 Upstage Console에서 전용 키를 새로 만든 뒤 붙여넣습니다.

### 개발자용 수동 실행

다른 운영체제에서 화면만 확인할 때 사용하는 선택 경로입니다.

```bash
python run_demo.py
```

브라우저에서 <http://127.0.0.1:8765>를 엽니다. API 키가 없으면 **샘플 모드**로 명확하게 표시됩니다.

Docker로 화면만 실행할 수도 있습니다.

```bash
docker build -f Dockerfile.demo -t agent-reliability-demo .
docker run --rm -p 127.0.0.1:8765:8765 agent-reliability-demo
```

### 다른 운영체제에서 실제 Solar 연결

1. [Upstage Console API Keys](https://console.upstage.ai/api-keys?api=chat)에서 본인 키를 생성합니다.
2. 키를 코드나 브라우저에 넣지 말고 서버 환경변수로만 설정합니다.
3. 서버를 다시 실행합니다.

macOS/Linux:

```bash
export UPSTAGE_API_KEY="본인_키"
python run_demo.py
```

Windows PowerShell:

```powershell
$env:UPSTAGE_API_KEY="본인_키"
python run_demo.py
```

선택 환경변수:

```text
UPSTAGE_MODEL=solar-pro3
UPSTAGE_BASE_URL=https://api.upstage.ai/v1
DEMO_HOST=127.0.0.1
DEMO_PORT=8765
DEMO_DATA_DIR=.demo-data
```

API 키는 server-side `Authorization: Bearer ...` 헤더에만 사용됩니다. 초기 패키지 제작 환경에는 신청자 소유 키가 없었으며, Windows 자동 실행이 완료되면 별도 live receipt가 생성되어 이 초기 상태를 대체합니다.

## 90초 데모 순서

1. 기본 합성 문서를 그대로 두고 `저장 후 응답 유실`을 선택합니다.
2. `문서 분석 시작`을 눌러 Solar 구조화 결과와 `승인 대기` 상태를 보여줍니다.
3. “승인 전에는 외부 기록이 0회”라는 점을 설명합니다.
4. `승인하고 새 실행기에서 재개`를 누릅니다.
5. 완료 카드에서 `실제 기록 1`, `중복 0`, `기존 결과 재사용 1 이상`을 확인합니다.
6. `같은 실행 요청 다시 보내기`를 눌러 실제 기록이 여전히 1회임을 보여줍니다.

핵심 설명 한 문장:

> 모델의 성능만 보여주는 데모가 아니라, 모델이 틀리거나 시스템이 실패해도 업무 사고로 번지지 않게 만드는 실행 제어층을 보여줍니다.

## 포트폴리오 PDF 다시 만들기

PDF는 제출 ZIP에 이미 포함돼 있습니다. 내용을 바꿔 다시 만들 때만 선택 의존성을 설치합니다.

```bash
python -m pip install -r requirements-portfolio.txt
python scripts/build_portfolio_pdf.py
```

한글 Noto Sans KR 폰트와 OFL 라이선스는 `assets/fonts/`에 함께 들어 있습니다.

## 테스트

데모 계층의 빠른 시험:

```bash
python -m unittest -v demo_tests.test_demo
python scripts/http_smoke_test.py
```

검증된 core의 전체 고유 시험 432개는 정상 host 또는 PID namespace가 일관된 validation container에서 실행합니다.

```bash
python scripts/process_environment_preflight.py
docker build -t agent-reliability-core .
docker run --rm --init agent-reliability-core python run_all.py --tests-only
```

일반 Windows host에서는 `python run_all.py --tests-only`를 직접 사용할 수 있습니다. 반면 Python이 보는 PID와 `/proc` PID가 다른 외부 sandbox 안에서는 detached-child cleanup 판정이 유효하지 않습니다. 이 경우 시험을 skip해 PASS로 만들지 말고 정상 host/container에서 다시 실행해야 합니다. 자세한 기록은 [`evidence/AUTHORING_ENVIRONMENT_NOTE.md`](evidence/AUTHORING_ENVIRONMENT_NOTE.md)에 있습니다.

시험은 정상 흐름 외에도 승인 경계, schema 거부, retry budget, checkpoint 복구, idempotency, timeout, signal, stall, orphan/zombie cleanup, source/evidence binding을 포함합니다.

## 검증 결과

| 검증 항목 | 결과 | 뜻 |
|---|---:|---|
| 고유 시험 | **432/432 PASS** | manifest와 실제 발견 시험이 정확히 일치 |
| Authority | **14/14 PASS** | 기준 환경·실패 주입·독립 검증 완료 |
| Platform | **10/10 PASS** | Linux/Windows, Python 3.11/3.12/3.13 cold/warm |
| Exact-final | **24/24 PASS** | 최종 후보 고정 후 깨끗한 재실행 |
| Matrix testcase 실행 | **20,736** | 432 × 24행 |
| 실패·오류·누락·중복·예상외 | **각 0** | compact receipt 기준 |
| orphan·zombie | **각 0** | 각 행 cleanup 검증 기준 |
| Rollback/Reapply | **420 → 432 PASS** | 기준선 복원 후 변경 재적용 검증 |

기계 판독용 요약은 [`evidence/technical_validation_summary.json`](evidence/technical_validation_summary.json)에 있습니다.

중요한 범위 구분:

- 위 432/14/10/24 결과는 **봉인된 reliability core**에 대한 기술 검증입니다.
- 이후 추가한 Solar adapter·웹 화면·키 1회 자동 실행기는 별도의 10개 unit/contract test와 HTTP smoke test로 검증했습니다.
- 라이브 Solar end-to-end는 공개 배포 영수증으로 확인합니다. 로컬 재검증이 필요할 때는 압축을 푼 패키지의 `START_HERE_UPSTAGE_LIVE_DEMO.cmd`에서 본인 Secret key를 입력합니다.

## 실패를 어떻게 안전하게 처리하나

| 상황 | 안전 동작 |
|---|---|
| 필수값 누락 | 실행하지 않고 `NEEDS_INFORMATION` 종료 |
| 승인 없음 | `APPROVAL_PENDING`에서 정지, 외부 기록 0 |
| 저장 전 일시 오류 | 제한된 budget 안에서 재시도 |
| 저장 후 응답 유실 | persisted result 조회 후 재사용 |
| 같은 요청 재전송 | 같은 idempotency key로 기존 결과 반환 |
| 프로세스 중단 | SQLite checkpoint에서 새 runtime이 재개 |
| schema 외 필드 | fail-closed로 provider output 거부 |

## 보안과 개인정보

- 샘플은 전부 합성 데이터이며 실제 계정·고객·결제 시스템과 연결되지 않습니다.
- 원문은 demo metadata에 저장하지 않고 SHA-256만 남깁니다.
- 서버는 loopback(`127.0.0.1`)에만 bind합니다.
- 요청 크기 제한, strict endpoint schema, CSP, frame 차단, no-store header를 적용했습니다.
- 저장 대상은 mock business state입니다. 실제 송금·결제·금융 판단을 하지 않습니다.
- 제출 ZIP에는 API 키, `.env`, runtime DB, raw 기술 증거를 넣지 않습니다.

## 정직한 한계

- 합성 문서와 로컬 mock tool을 사용한 포트폴리오 데모입니다.
- idempotency 계약을 검증하지만 분산 시스템의 exactly-once를 주장하지 않습니다.
- 432개 기술 검증은 실제 운영환경 전체의 안전성을 보장하지 않습니다.
- 공급자 품질·latency·rate limit은 실제 키를 사용한 별도 통합 확인이 필요합니다.
- 이 저장소는 능력과 검증 방식을 보여주는 산출물이며 채용 합격을 보장하지 않습니다.

## 프로젝트 구조

```text
demo/                  Solar adapter, service, HTTP server, responsive UI
demo_tests/            live adapter contract + workflow demo tests
src/reliability_core/  state machine, policy, checkpoint, tools, evaluator
tests/                 432-test technical validation suite
evidence/              sanitized validation summary
scripts/               smoke test, validation and packaging helpers
docs/                  interview and submission guides
run_demo.py             local demo entrypoint
run_all.py              sealed core test entrypoint
```

## Agent GYM 직무와 연결되는 지점

이 프로젝트는 “좋은 답을 생성하는가”만 평가하지 않습니다. agent가 실제 도구를 사용할 때 필요한 환경 설계, 평가 기준, 실패 주입, 재현 가능한 evidence, 사람 승인, 회귀 방지를 하나의 작은 시스템으로 묶었습니다. 즉, 모델·환경·평가·운영 안전을 함께 다루는 Agent GYM형 역량을 보여주기 위한 프로젝트입니다.

## 공식 참고

- [Upstage Console – Chat API Key](https://console.upstage.ai/api-keys?api=chat)
- [Upstage API Pricing](https://www.upstage.ai/ko/pricing/api)
- [Upstage Agent GYM 채용 공고](https://careers.upstage.ai/ko/o/194880)

## 라이선스와 제출 범위

채용 포트폴리오 검토용 예제입니다. 공개 저장소로 전환하기 전에는 저장소 소유자 정보, 라이선스, 연락처를 본인 기준으로 확정해야 합니다.
