# G1 동맹 펄스 실통합 증거 — 2026-08-06 ## 결론 G1 동맹 펄스의 최신 코드 경로를 별도 API 프로세스에서 실제 HTTP와 PostgreSQL로 끝까지 검증했다. 학습자 자기평가 잠금 전후 공개 순서, 두 독립 에이전트의 3축 측정, 동일 코호트 교수자 열람, 교수자 재평정의 append-only supersession이 모두 통과했다. ## 2026-08-07 실제 pre → mid → post 확장 검증 최신 소스 API `8128`에서 실제 새 회기를 만들고 회기 전·첫 왕복 뒤·종료 뒤 세 checkpoint를 한 흐름으로 검증했다. 기계 판독 증거는 `docs/ops/evidence/alliance-pulse-pre-mid-post-live-2026-08-07.json`에 보존한다. | checkpoint | 실제 결과 | |---|---| | pre | 첫 발화 전 잠금, 축어록 부재를 점수로 추정하지 않고 `degraded / insufficient_transcript`; 학습자 3축은 보존하고 외부 두 관점은 무점수 | | mid | 실제 counselor/client turn UUID 2개를 근거로 `ready`, 3관점 × 3축 공개 | | post | DB `ended_at`이 기록된 뒤 생성, `awaiting_agents → ready`, 3관점 × 3축 공개 | post pulse는 최초 `202 / idempotent_replay=false`, 동일 payload 재전송은 같은 ID와 `idempotent_replay=true`, 변경 payload는 `409`였다. 다른 학습자와 교차 cohort 교수자는 `404`, 동일 cohort 교수자는 열람 가능했고 교수자 2회 평정은 3축 모두 append-only supersession으로 연결됐다. post 원장은 self assessment 1행, ready model-run 2행, measurement event 15행이며 prompt bundle은 `1.2.0`이다. 이 실행 전에 두 실제 경계 결함도 수정하고 회귀를 추가했다. - 정상적인 pre fail-closed 결과인 `degraded + insufficient_transcript`를 거부하던 `ck_alliance_pulse_terminal_state`와 audit status-event 제약을 바로잡고 실제 dev DB에 재적용했다. - PostgreSQL `READ COMMITTED`에서 pulse 상태 조회와 event 조회 사이에 agent 커밋이 끼면 한 HTTP 응답 안에서 상태는 `awaiting_agents`인데 외부 관점만 먼저 보일 수 있었다. 첫 pulse 조회에서 공개된 ID 집합을 고정해 같은 응답의 reveal 경계를 일관되게 만들었다. - 구조화 출력 실패는 성공으로 대체하지 않으며 최대 3회까지 동일 근거·스키마로 재시도하고 각 실패 시도를 model-run provenance로 보존한다. 최신 focused G1 계약 묶음은 `43 passed`, Ruff는 통과했다. 물리 마이크나 실제 사용자 로그인은 사용하지 않았다. - API: `http://127.0.0.1:8004` — prompt `1.2.0` 최신 코드로 별도 기동 - PostgreSQL: `vignette-dev-db`, host port `55432` - 엔진: `127.0.0.1:9099`, `claude_cli` - 표준 persona/cohort: `P1`, `e2e-hanshin` - 성공 회기: `8854fd64-2e63-45da-a97f-30e7ba8de1f2` - 성공 pulse: `d85212f3-b9e1-4c73-8809-d34d7b473371` - fixture 정책: `dev:e2e` 식별자를 삭제하지 않고 내구 저장소에 보존 기존 `8002`·`8003` 프로세스는 최신 prompt 변경 전에 기동됐으므로 최종 증거에서 제외했다. 아래 결과는 `PROMPT_BUNDLE_VERSION=1.2.0` 코드를 로드한 `8004`에서 얻었다. ## 재현 명령 ```powershell $env:PYTHONUTF8='1' py -3.11 -X utf8 scripts/smoke-alliance-pulse-api.py ` --api-base-url http://127.0.0.1:8004 ` --expected-prompt-version 1.2.0 ` --request-timeout 180 ` --poll-timeout 360 ``` 스크립트는 쿠키, 이메일, 데이터베이스 접속 문자열, 축어록 원문을 출력하지 않는다. 출력은 회기/pulse 식별자와 상태·개수 증거만 포함한다. ## HTTP 증거 | 게이트 | 실제 결과 | |---|---| | health | API `ok`, DB `true`, engine `true` | | 자기평가 잠금 | `POST .../alliance-pulses` → `202` | | 최초 read model | `awaiting_agents`, 외부 관점 0개, 학습자 `goal/task/bond`만 3개 | | terminal reveal | 25.266초, `ready` | | 학습자 terminal read | 3관점 × 3축 = 9개 | | 동일 코호트 교수자 GET | 성공, 학습자 terminal read와 동일 | | 교수자 평정 1차/2차 | `201`, `201` | | 교수자 최신 read | 4관점 × 3축 = 12개 | `awaiting_agents`로 읽히는 모든 poll에서 `client_agent_report`와 `independent_observer`가 노출되지 않는 것도 함께 단언했다. 즉 최종 결과가 먼저 계산됐더라도 학습자 자기평가 잠금 이전 또는 비동기 완료 이전에는 외부 점수를 볼 수 없다. ## PostgreSQL 원장 증거 | 원장 계약 | 실제 결과 | |---|---| | pulse 상태 이력 | `awaiting_agents → ready` | | 시간 순서 | `created_at ≤ learner_locked_at ≤ revealed_at ≤ updated_at` | | self assessment | 1행, `goal/task/bond` 정확히 3축 | | model run | 총 2행, terminal ready 2행 | | prompt provenance | 전 행 bundle `1.2.0`, prompt/evidence hash 존재 | | learner event | 3행 | | client-agent event | 3행 | | independent-observer event | 3행 | | supervisor event | 6행 — 1차 3행 + 2차 3행 | | supervisor supersedes | 2차 평정 3행이 1차 각 축을 각각 참조 | | measurement event 합계 | 15행 | 최신 live 실행은 두 관점 모두 첫 시도에 성공했다. 재시도 경계는 별도 실증도 함께 보존한다. - prompt `1.2.0` 합성 gold calibration에서 `oas-g0-007`의 엔진 오류와 `oas-g0-008`의 필수 rationale 누락이 각각 두 번째 시도에 회복됐고, 이전 실패 model-run id와 error code가 결과 snapshot에 남았다. - prompt `1.1.0` live 실행(`8003`, 회기 `55389bd3-8ea2-4c9d-a625-a71fbb63d431`)에서도 client 1차 validation error → 2차 ready, evaluator 1차 ready의 3개 model-run 원장을 확인했다. 따라서 정상 첫 시도와 실제 retry 모두에서 terminal run만 측정 이벤트에 연결되고 실패 시도는 덮어쓰지 않는 계약이 검증됐다. ## 자동 단언 범위 재현 스크립트 `scripts/smoke-alliance-pulse-api.py`는 다음 조건 중 하나라도 어긋나면 비정상 종료한다. - 첫 read가 `awaiting_agents`가 아니거나 외부 관점이 보임 - terminal 상태가 `ready`가 아니거나 3관점 × 3축이 아님 - 교수자가 같은 코호트 회기를 읽지 못함 - 두 번의 교수자 평정 뒤 최신 read가 4관점 × 3축이 아님 - DB 시간 순서, 상태 감사 이력, event 개수, model-run hash/version이 어긋남 - retry attempt가 관점별로 1부터 연속되지 않음 - 두 번째 교수자 평정의 `supersedes_id`가 3축 중 하나라도 빠짐