diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index af80cbb..8f3fe32 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -47,9 +47,11 @@ G8 배포 source 기준선은 branch `master`, HEAD `61a41d1f08239b5f9e99cfae42a 모두 닫는 것**이다. G8은 종료됐고 G7 canonical checker exit 0이 없으면 `goal complete`를 호출하지 않는다. - current NAS 복구용 `scripts/start-nas-preview-engine.ps1`은 source-pinned fail-closed 계약으로 보강했다. detached-clean HEAD/tree, launcher·Python·env SHA, exact consumer URL, explicit LAN 승인, 외부 state/receipt, - listener owner와 generation readiness를 강제하고 loopback contract **8/8**을 통과했다. 실제 9100 listener, - NAS 설정·컨테이너·DB는 건드리지 않았다. 다음 mutation은 소유자 승인 뒤 단일 owner가 check-only→actual 1회→ - NAS health/auth/OpenAPI/assets/실회기 재검증 순서로만 수행한다. + listener owner와 generation readiness를 강제하고 loopback contract **8/8**을 통과했다. 2026-08-12에는 + detached-clean `f08e03de…f191`·tree `00275133…0abd`에서 exact `-CheckOnly`도 PASS했다. launcher/Python/env + SHA는 `492d8b5c…b27c`/`5f7b89a6…52ec`/`e53acedf…8a39`, `mutation=false`, listener `0→0`, runtime + state 생성 0이다. 실제 9100 listener, NAS 설정·컨테이너·DB는 건드리지 않았다. 다음 mutation은 소유자 승인 뒤 + 단일 owner가 actual 1회→NAS health/auth/OpenAPI/assets/실회기 재검증 순서로만 수행한다. - 최신 full disposable GREEN은 공통 톱바 44px 계약을 포함한 clean `b02bee26…`·tree `8f677bba…`의 `periodic-learner-e2e-20260812-171547.json`·SHA-256 `8c11a136…af8e3`이다. 487.3초에 동일 학습자 브라우저 회기 생성·SSE·review ready·G4/G5 `0→1→1`, 별도 returned desktop/mobile 4/4와 route mock 0을 @@ -761,7 +763,8 @@ NAS/public/DB mutation owner는 항상 한 에이전트만 둔다. 1. **G7 proof lane:** 완료된 clean public runtime과 무마이크 rehearsal을 기준선으로 보존하고, 장치 선택·명시 동의 뒤 3,120초 mic/runtime/topology 동시 캡처와 human pack·canonical checker를 닫는다. 2. **G8/NAS recovery lane:** 완료된 archive·images·rollback 증거는 보존한다. current relay는 source-pinned launcher - 8/8만 완료됐고 실제 9100은 0 listener다. 소유자 승인 전 mutation 0; 승인 뒤 check-only→actual 1회→NAS-origin 재검증. + 8/8과 detached-clean `f08e03de…f191` exact check-only까지 완료됐고 실제 9100은 0 listener다. 소유자 승인 전 + mutation 0; 승인 뒤 같은 source/tree·hash 결속으로 actual 1회→NAS-origin 재검증. 3. **E2E/SSOT lane:** local fixture, disposable DB browser, visual/accessibility, dashboard/TODO/backlog 정합을 읽기 전용으로 감사. 루트 에이전트는 각 lane의 증거 SHA와 실패 원인을 합쳐 게이트를 판정한다. 같은 blocker가 두 번 반복되면 세 번째 diff --git a/docs/TODO.md b/docs/TODO.md index 56447ef..d95d396 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -75,10 +75,11 @@ 워치독이 `unhealthy (1/3)` + 503 본문을 남겼다. NAS용 9100은 2026-08-12 listener 상실을 확인했다. current relay launcher는 detached-clean HEAD/tree, launcher·Python·env SHA, exact consumer URL, explicit LAN 승인, 외부 receipt/runtime, listener owner, - generation readiness와 실패 cleanup을 강제하도록 보강했고 contract 8/8을 통과했다. 실제 9100 시작은 - 소유자 승인 전 미실행이다. -- [ ] **NAS preview engine relay current 복구** — `scripts/start-nas-preview-engine.ps1 -CheckOnly`의 - `mutation=false`를 exact release에서 확인한 뒤, 승인된 단일 owner가 LAN listener를 1회 시작하고 NAS + generation readiness와 실패 cleanup을 강제하도록 보강했고 contract 8/8을 통과했다. detached-clean + `f08e03de…f191`·tree `00275133…0abd` exact `-CheckOnly`도 launcher/Python/env SHA 결속, + `mutation=false`, listener `0→0`, runtime state 0으로 PASS했다. 실제 9100 시작은 소유자 승인 전 미실행이다. +- [ ] **NAS preview engine relay current 복구** — 위 exact release와 검증 SHA를 그대로 사용해, 승인된 단일 owner가 + LAN listener를 1회 시작하고 NAS health 3/3·db/engine true, auth 401, OpenAPI 126·assets, actual-origin turn→review를 재검증한다. 실패 시 이번 실행 소유 PID/listener만 정리하고 자동 재시도하지 않는다. 2026-08-12 15:24 KST local health는 3회 타임아웃이므로 현재 NAS를 GREEN으로 표기하지 않는다. diff --git a/docs/dev_dashboard.html b/docs/dev_dashboard.html index d2b7e53..f7053be 100644 --- a/docs/dev_dashboard.html +++ b/docs/dev_dashboard.html @@ -678,7 +678,7 @@

199차 적용(2026-08-12): 실제 공개 학생 홈을 390×844·320×568에서 읽기 전용으로 확인해 부트 진단·console error·가로 overflow·literal PII placeholder는 0이고 핵심 학습 카드·탭·리뷰 CTA는 44px 이상임을 재확인했다. 반면 공통 톱바의 공간 전환 링크는 28px, 테마·로그아웃은 34px에 머물러 있던 P1을 발견했다. 소스는 720px 이하에서 워드마크 글자·사용자 칩을 접고 브랜드·공간 전환·테마·로그아웃 6개를 모두 44×44px로 고정했으며, 관리자 3역할 최악 조건 390/320 desktop/mobile 2/2, 학생 자기주도 홈→회기→리뷰→재연습 desktop/mobile 6/6, G1·G4·G5·G7 focused 50/50, 대시보드 10/10, type/API contract와 SSOT checker를 통과했다. clean HEAD 9687f186…c48b·tree be2fc4d2…749d7의 full disposable runner도 485.8초에 GREEN이었고 receipt periodic-learner-e2e-20260812-143426.json·SHA-256 501d2d7f…c557에서 same-learner SSE·review·G4/G5 0→1→1, returned desktop/mobile 4/4, route mock 0, public·NAS·active DB 접촉 0과 container·volume·network·listener·temp 잔여 0을 확인했다. 공개 앱에는 아직 이 변경을 배포하지 않았으므로 실제 공개 톱바는 별도 승인 배포 전까지 기존 크기이며, G7은 명시 동의 물리 마이크·독립 human pack·canonical checker exit 0 전까지 external GATE다.

200차 적용(2026-08-12): actual NAS 로그인 320/390 읽기 전용 관측에서 조작면·boot·console은 정상이지만 비-overlay 세로 scrollbar 환경의 100vw 두 선언이 10px 가로 넘침을 만드는 P1을 확인했다. auth/login shell을 scrollbar를 제외한 컨테이너 기준 100%로 바꾸고 320px stable-scrollbar OAuth fixture를 고정했다. 인증 desktop/mobile 2/2, 자기주도+G1·G4·G5·G7 56/56, 대시보드 10/10, G7 runner·checker·human/API 계약 110/110, type/API contract·Ruff·SSOT checker를 통과했다. 물리 soak standalone도 canonical 공통 3,000초를 보존하도록 production 기본·최소를 3,120초로 통일해 3,000초 요청을 장치 열거 전에 차단한다. clean HEAD 64e1b221…a4e·tree 2c687bac…30bf의 full disposable runner는 489.6초에 GREEN이었고 receipt periodic-learner-e2e-20260812-150209.json·SHA-256 a7b2f758…8071에서 same-learner SSE·review·G4/G5 0→1→1, returned desktop/mobile 4/4, route mock 0, public·NAS·active DB 접촉 0과 container·volume·network·listener·temp 잔여 0을 확인했다. 이 소스는 아직 공개/NAS에 배포하지 않았다.

201차 관측(2026-08-12): 읽기 전용 현재-state 대조에서 공개 앱은 health ok·db/engine true·OpenAPI 126·auth 401과 local_whisper/small·melotts/melotts-korean을 유지했지만, NAS 프리뷰는 3회 연속 status=degraded·db=true·engine=false였다. NAS의 DB·Web·proxy는 running이고 API는 restart 0인 채 unhealthy였다. 원인은 API의 고정 ENGINE_URL=http://192.168.0.223:9100 대상 listener 부재로 좁혔다. 현재 공개 엔진은 별도 loopback 127.0.0.1:9099에만 있어 공개 서비스는 영향받지 않는다. 과거 G8 clean-head NAS-origin 112/112와 실제 rollback receipt는 완료 증거로 보존하되, 현 NAS runtime은 DEGRADED · REVALIDATION으로 표시한다. 별도 승인 전에는 LAN 포트 노출·Scheduled Task 생성·컨테이너 재시작·배포를 하지 않는다. source-pinned·secret-bound relay를 복구한 뒤 health 3/3·auth 401·OpenAPI 126·assets·실제 NAS-origin 회기 smoke를 다시 통과해야 current GREEN으로 돌아간다.

-

202차 적용(2026-08-12): NAS relay 복구 스크립트를 기본 loopback·detached-clean HEAD/tree·launcher/Python/env SHA·exact consumer URL·명시 LAN 승인·외부 state/receipt로 fail-closed했다. wildcard·기존 listener 재사용·source 내부 또는 reparse-point 외부 경로를 거부하고, liveness 뒤 실제 provider /ready?force=true를 한 번만 호출한다. readiness/receipt 실패는 이번 실행이 소유한 PID/listener만 정리한다. Windows PowerShell parse, contract 8/8, Ruff·compile·diff-check를 통과했고 public 9099 listener는 1, NAS 9100 listener는 0을 유지했다. 같은 시각 public은 health ok·db/engine true·OpenAPI 126·auth 401·local voice exact였지만 NAS health는 3회 타임아웃했다. 실제 LAN relay·NAS/container/DB mutation은 소유자 승인 전 실행하지 않는다.

+

202차 적용·사전검증(2026-08-12): NAS relay 복구 스크립트를 기본 loopback·detached-clean HEAD/tree·launcher/Python/env SHA·exact consumer URL·명시 LAN 승인·외부 state/receipt로 fail-closed했다. wildcard·기존 listener 재사용·source 내부 또는 reparse-point 외부 경로를 거부하고, liveness 뒤 실제 provider /ready?force=true를 한 번만 호출한다. readiness/receipt 실패는 이번 실행이 소유한 PID/listener만 정리한다. Windows PowerShell parse, contract 8/8, Ruff·compile·diff-check를 통과했다. 이어 detached-clean f08e03de…f191·tree 00275133…0abd에서 exact -CheckOnly를 실행해 launcher/Python/env SHA 492d8b5c…b27c/5f7b89a6…52ec/e53acedf…8a39, mutation=false, 9100 listener 0→0, runtime state 생성 0을 확인했다. public 9099는 정상이고 NAS health는 타임아웃 상태다. 실제 LAN relay·NAS/container/DB mutation은 소유자 승인 전 실행하지 않는다.

203차 관측·보강(2026-08-12): detached-clean 94666192…의 periodic full run은 전용 engine ready를 통과한 뒤 app.ci_regression_dag_node가 준비되지 않은 disposable PostgreSQL health에서 실패해 브라우저 단계 전에 종료됐다. receipt periodic-learner-e2e-20260812-155929.json·SHA-256 1bd95e01…52a8은 FAILED이며 public·NAS·active DB 접촉 0과 container·volume·network·listener·temp 잔여 0을 확인했다. stack source는 마지막 GREEN 64e1b221…과 동일하지만 cleanup 전에 DB/API 로그를 영수증에 남기지 않아 정확한 환경/init 원인은 미확정이다. 같은 heartbeat에서 재시도하지 않았다. runner는 이제 cleanup 전에 compose ps와 db/api 로그 tail을 캡처하고 secret·email·UUID·민감 query를 제거하며 raw SHA만 결속한다. contract 14/14·Ruff·compile을 통과했다.

204차 적용(2026-08-12): actual NAS 로그인 390×844에서 innerWidth=390, document usable width 380, login root width 390으로 10px 가로 넘침이 계속 재현돼 200차의 100vw→100% 보정만으로는 부족함을 확인했다. auth/login 최상위 shell을 block auto-size와 max-inline-size:100%로 바꿔 classic scrollbar를 usable scrollport에서 이중 계산하지 않게 했다. route-mocked 학생 자기주도·G1~G5·G7 desktop/mobile 76/76, 인증 2/2, 대시보드 10/10, type/API contract·SSOT checker를 통과했다. 이 수정은 아직 공개/NAS에 배포하지 않았고, 현 NAS는 health 타임아웃·실제 화면 overflow 10px인 DEGRADED 상태다.

205차 진단·보강(2026-08-12): 진단과 로그인 폭 수정을 commit f97e7fad…·tree bdc83f24…의 새 detached-clean worktree에 고정해 periodic full runner를 한 번 실행했다. 전용 engine ready 뒤 disposable DB가 restart 127로 unhealthy가 돼 브라우저 전에 fail-closed했다. receipt periodic-learner-e2e-20260812-163742.json·SHA-256 ad403712…d840f의 cleanup 전 secret/PII-safe 로그가 99_app_role.sh#!/usr/bin/env bash\rNo such file or directory를 확정했다. Git blob은 LF지만 Windows core.autocrlf=true가 새 worktree를 CRLF로 만든 것이 원인이다. .gitattributes*.sh text eol=lf를 추가했다. public·NAS·active DB 접촉 0, container·volume·network·listener·temp 잔여 0이며, 같은 blocker가 두 번 반복돼 이번 heartbeat에서는 재실행하지 않는다. 다음 gate는 새 commit→새 detached checkout CR 0→preflight→single full run이다.

@@ -1174,7 +1174,7 @@ 격리 NAS 프리뷰 · 회기 E2E 자동화http://100.116.83.60:8088 / vignette-e2e 매시간 heartbeat / 배포 증거 / 기계 판독 증거current clean source HEAD 61a41d1f…6af·tree 87dec55d…3b77의 archive 4d15d055…119d4d를 전용 Compose 프로젝트·포트·네트워크·named volume에 승격했다. candidate 112/112와 실제 NAS-origin 112/112는 당시 통과했지만 영수증은 실 API/DB 22건과 route fixture 90건을 분리한다. 2026-08-12 현재는 health 3/3 degraded·db true·engine false이며, 고정 LAN engine relay listener 부재로 current runtime 재검증이 필요하다. 자동화는 공개/NAS 화면과 health를 읽기 전용으로 매시간 보여준다. material milestone의 동일 학습자 SSE→review→G4/G5 actual 폐루프는 clean HEAD/tree·전용 engine/DB/API/Web·보호 포트 거부·sentinel·exact cleanup runner가 소유한다. 1~3차는 하네스, 4차는 reload ledger hydration 제품 결함, 5차는 fixture 공유, 6차는 mobile success-state locator를 fail-closed했다. 7차 clean aa81af29…는 same-learner SSE·review·G4/G5 0→1→1과 별도 returned desktop/mobile 4/4, route mock 0, cleanup 0으로 첫 전체 GREEN을 만들었다. heartbeat는 최신 GREEN이 6시간 이상 오래됐거나 학생 runtime·회기 폐루프 material milestone이 바뀔 때만 full runner를 최대 1회 실행하고 실패 시 자동 재시도하지 않는다. G7 human intake·checker·template-only 변경은 G7 focused gate만 실행한다. release gate·NAS preflight·배포 SHA 변경 때만 프리뷰를 갱신한다. G7 외부 mic/provider/human 증거는 별도다. G7 외부 증거 3-artifact 동시 시간창 오케스트레이터scripts/run-g7-external-proof-window.py · 준비 문서soak·runtime·topology 세 캡처를 같은 host의 공통 3,000초 시간창으로 실행하고 checker까지 잇는다. 공개 배포·프로세스·source pin은 clean commit a73bcd24…와 fresh receipt 9f8d1941…로 완료했다. Cloudflare가 Python 기본 User-Agent를 403으로 거부하는 경계도 브라우저 호환 header와 회귀 4/4로 고정했다. 30초 rehearsal은 세 leg 7 samples를 모두 통과했으며 마이크를 열지 않았다. 남은 선행 조건: 사용자의 물리 장치 선택과 명시 동의, 독립 human voice-gain pack이다. G7 external GATE · 최종 감사 정정run-g7-external-proof-window.pycheck-g7-external-proof.py상태는 external GATE 유지. runner 프로세스 exit는 canonical checker exit 0·gate_closed=true에 결속되고, browser Origin과 API transport host는 별도 allowlist로 검증된다. 세 artifact 교집합은 ≥3000s + 120초 margin이고 Windows proof는 detached-clean HEAD/tree·tool SHA·psutil==6.1.1을 pin한다. 직접 물리 soak를 실행해도 production 기본·최소 3,120초를 강제하고 3,000초 요청은 장치를 열기 전에 차단한다. clean-source 배포와 무마이크 rehearsal은 완료했다. 남은 것은 물리 마이크 3,120초, 동시 runtime/topology, 독립 human pack을 합친 4-artifact 실증뿐이다. - G8 증거 DONE · current NAS DEGRADEDvignette-preview-20260807 · run-outcome-os-release-agent.py · start-nas-preview-engine.ps1배포·rollback 증거는 DONE, 현재 runtime은 재검증 중. active archive 4d15d055…119d4d, source HEAD/tree 61a41d1f…6af/87dec55d…3b77, API/Web d5021950…e4b1/9796c092…4b36 기준선은 보존한다. candidate 112/112와 actual NAS-origin 112/112, 당시 health ok·db/engine true·auth 401·OpenAPI 126을 통과했다. 2026-08-12 current는 engine relay listener 부재 뒤 degraded였고 15:24 KST health 3회가 타임아웃했다. source-pinned relay 계약 8/8은 통과했지만 실제 9100 listener는 0이다. fresh dump 36ec8748…24db8 1,097,100 bytes, TOC 1,738 / TABLE DATA 129와 previous active 6030a677…c611을 보존했다. release agent의 DB restore 비소유·image/Compose/active-state rollback 경계는 유지한다. + G8 증거 DONE · current NAS DEGRADEDvignette-preview-20260807 · run-outcome-os-release-agent.py · start-nas-preview-engine.ps1배포·rollback 증거는 DONE, 현재 runtime은 재검증 중. active archive 4d15d055…119d4d, source HEAD/tree 61a41d1f…6af/87dec55d…3b77, API/Web d5021950…e4b1/9796c092…4b36 기준선은 보존한다. candidate 112/112와 actual NAS-origin 112/112, 당시 health ok·db/engine true·auth 401·OpenAPI 126을 통과했다. 2026-08-12 current는 engine relay listener 부재 뒤 degraded였고 15:24 KST health 3회가 타임아웃했다. source-pinned relay 계약 8/8과 detached-clean f08e03de…f191 exact check-only는 PASS했지만 실제 9100 listener는 0이다. check-only는 mutation=false·listener 0→0·runtime state 0을 증명한다. fresh dump 36ec8748…24db8 1,097,100 bytes, TOC 1,738 / TABLE DATA 129와 previous active 6030a677…c611을 보존했다. release agent의 DB restore 비소유·image/Compose/active-state rollback 경계는 유지한다. 노트북 로컬 음성 스택 — faster-whisper STT + MeloTTS TTSscripts/local-whisper-stt-server.py · scripts/start-local-whisper-stt.ps1 · voice_stt_provider=local_whisper2026-08-08 소유자 결정으로 음성 양쪽을 노트북 상주 로컬 모델로 정했다. TTS는 처음 Higgs로 잡았으나 연구/비상업 라이선스라 config.py가 운영에서 차단하고 있었고 그 가드를 푸는 건 법적 판단이라, 상업 사용이 허용된 MeloTTS Korean(MIT)으로 바꿔 가드 자체를 불필요하게 만들었다. Kokoro-82M은 Apache 2.0이지만 공식 VOICES.md한국어가 없어 탈락했다. local Whisper는 현재 호스트의 cuDNN 부재를 반영해 small/cpu-int8를 운영 기본으로 고정했고, API health도 MeloTTS model을 실제 provider와 맞춰 보고한다. 합성 시드 8.72초에서 interim 9·final 5·word timestamp 12개, 한 글자 차이 전사를 확인했고 MeloTTS CPU RTF는 0.27~0.28, 합성음→local STT 왕복은 완전 일치했다. current 통합은 launcher/sidecar 80/80·G7 전체 166/166·API voice 71/71·API 전체 921·gateway 58을 통과했다. Higgs 운영 사용은 라이선스 가드가 남아 dev 전용이다. 비-secure origin 회기 리뷰 크래시 수정apps/web/src/lib/uuid.ts · apps/web/src/lib/sha256.ts · apps/web/e2e/insecure-context-uuid.spec.ts격리 NAS 프리뷰(평문 HTTP·비-localhost)에서 드러난 crypto.randomUUIDcrypto.subtle.digest secure-context 의존을 portable fallback으로 교체했다. source-only UUID/SHA 회귀 12/12와 secure/insecure exact digest 회귀를 통과했고, 최종 archive 4d15d055…119d4d의 actual NAS-origin 112/112로 배포 검증까지 닫았다. 공개 워치독 engine readiness 사각지대(해결)scripts/watch-public-runtime.ps1 · scripts/start-public-runtime.ps1 · apps/api/engine_gateway/gateway.py2026-08-07 22:0x KST 소유자 승인으로 9099를 재기동해 복구했다. 재기동 직후 /ready?force=true 200 ok:true·detail:OK, API 8001과 공개 api-vignette.chanpaca.net 모두 status:ok·engine:true·engine_detail:OK다. 원인은 16:06부터 상주한 9099 프로세스 하나였다(CLI·코드·cwd는 정상 — 동일 인자 직접 실행과 EngineSession 재현이 "OK"를 반환). 재발 방지 3건: (1) 워치독·기동 스크립트의 engine 판정을 /health(프로세스 liveness)에서 /ready(실제 생성)로 바꾸고 API 판정에 engine을 추가, shared secret 인스턴스용 토큰 헤더와 503 본문 로깅 포함. (2) 게이트웨이가 자식 claude -p의 stderr를 상시 드레인해(PIPE 미독 시 자식 블록도 차단) 실패 detail에 exit·stderr를 붙인다 — 실증: empty engine response (error: unknown option '--vignette-nonexistent-flag-xyz'). (3) 기동 시 게이트웨이 로그 회전, Stop-UvicornByPortName -like python* 추가(호출자 자기 자신 종료 방지). 검증: pytest engine_gateway 58/58, 워치독 -CheckOnly healthy 5/5, 장애 재현(9299·CLAUDE_BIN 부재)에서 /healthok:true로 통과하고 /ready는 503으로 검출되어 워치독이 unhealthy (1/3) + 503 본문을 남겼다. NAS용 9100(06:27 상주)은 실사용 세션 7개가 있어 미접촉이라 게이트웨이 stderr 개선은 다음 재기동 때 반영된다. diff --git a/docs/ops/backlog-2026-06-26.md b/docs/ops/backlog-2026-06-26.md index 022a863..47cc4e6 100644 --- a/docs/ops/backlog-2026-06-26.md +++ b/docs/ops/backlog-2026-06-26.md @@ -102,8 +102,9 @@ heartbeat(automation id `vignette-e2e`)는 ACTIVE이며 공개/NAS 화면·health는 읽기 전용으로 보여준다. NAS 112건은 실 API/DB 22와 route fixture 90으로 영수증에서 분리한다. 동일 학습자 SSE→review→G4/G5 actual 폐루프 runner의 clean HEAD/tree·보호 포트 거부·sentinel·exact cleanup과 unit 14/14는 완료됐다. 최초 세 full run은 하네스, 4차는 reload ledger hydration, 5차는 fixture 공유, 6차는 mobile success-state locator를 fail-closed했고 7차 clean `aa81af29…`가 첫 전체 GREEN을 만들었다. `94666192…`와 `f97e7fad…`의 DB init 실패는 두 번째 receipt 로그로 detached `99_app_role.sh` CRLF와 `bash\r` exit 127이 원인임을 확정했다. `.gitattributes`의 `*.sh text eol=lf`로 이를 닫았다. 공통 톱바 desktop/mobile 44px을 포함한 clean `b02bee26…`·tree `8f677bba…`의 최신 single full run은 487.3초 GREEN이다. receipt `periodic-learner-e2e-20260812-171547.json`·SHA-256 `8c11a136…af8e3`은 same-learner SSE·review·G4/G5 `0→1→1`, returned desktop/mobile 4/4, route mock 0, public/NAS/active DB 접촉 0과 cleanup 0을 증명한다. heartbeat는 이 GREEN이 6시간 이상 오래됐거나 material milestone이 바뀔 때만 다시 실행한다. release gate·NAS preflight·배포 SHA 변경 때만 프리뷰를 갱신한다. 2026-08-07 SHA `6030a677af7e87cbfabc422b553d108d53414fd3c446548734a13b036d35c611`의 localhost 108/108과 평문 origin UUID 24건 실패는 역사 기준선으로 보존한다. 실제 receipt-bound rollback은 같은 프리뷰에서 별도 helper로 두 번 실행해 종료했다([런북](./nas-preview-g8-rollback-proof-runbook.md), [기계 판독 증거](./evidence/nas-preview-g8-actual-rollback-2026-08-07.json)). 현재는 source HEAD/tree `61a41d1f…6af`/`87dec55d…3b77`의 active archive `4d15d055…119d4d`, exact API/Web `d5021950…e4b1`/`9796c092…4b36`이 실행 중이다. candidate 112/112와 실제 NAS-origin 112/112, health ok·db/engine true·auth 401·OpenAPI 126을 통과했고 fresh dump `36ec8748…24db8` 1,097,100 bytes·TOC 1,738/TABLE DATA 129와 previous `6030a677…c611`을 보존했다. 증거: [배포 증거](./nas-preview-deployment-evidence-2026-08-07.md), [브라우저 증거](./evidence/nas-preview-live-turn-2026-08-07.png). 위 health GREEN은 배포 당시 증거다. 2026-08-12 current NAS는 고정 LAN engine relay listener 상실로 degraded였고 15:24 KST local health 요청도 - 3회 타임아웃했다. source-pinned relay launcher와 loopback contract 8/8은 완료했지만 실제 9100 시작·NAS - origin 재검증은 소유자 승인 대기다. 명시 동의 물리 마이크와 독립 human voice-gain 증거도 아직 없으므로 + 3회 타임아웃했다. source-pinned relay launcher와 loopback contract 8/8에 더해 detached-clean + `f08e03de…f191`·tree `00275133…0abd` exact check-only도 `mutation=false`·listener `0→0`·runtime state 0으로 + PASS했다. 실제 9100 시작·NAS origin 재검증은 소유자 승인 대기다. 명시 동의 물리 마이크와 독립 human voice-gain 증거도 아직 없으므로 G7은 external GATE로 유지한다. - [ ] **claude_cli ↔ Anthropic API live 동일성** — provider 라우팅·Anthropic `/v1/models` 탐색·지원 추론 강도·관리자 fail-closed 저장 경로는 구현 완료. 남은 범위는 연구팀/기관 `ANTHROPIC_API_KEY`를 게이트웨이 호스트에 주입한 live 응답·계량·오류 표면화 비교다. Claude CLI·Codex CLI(Terra/Medium)·Agy CLI(Gemini 3.6 Flash/High)는 로컬 live probe를 통과했다. - [ ] **stable-source 재부팅 후 watchdog smoke** — watchdog·로그온 boot는 detached-clean `a73bcd24…` stable