From 0a00ff245af02c1e3b822785ae46e8fe6c5be646 Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sun, 23 Aug 2026 13:49:52 +0900 Subject: [PATCH] =?UTF-8?q?NAS=20current=20GREEN=20=EB=8B=AC=EC=84=B1?= =?UTF-8?q?=EA=B3=BC=20=EC=8B=AC=EC=95=BC=20=EC=97=B0=EC=87=84=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC=20=EC=A6=9D=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 대청소 사건·Docker 사망·WinNAT 포트 예약·DHCP IP 회수 연쇄 복구 기록 - 릴레이 bf5f7352 재핀(r3) + 192.168.0.224 계약 이전(방화벽·NAS .env 재구성) - NAS agy_cli 전환으로 health 3/3 engine true + actual-origin turn→review smoke 통과 — 201차 current GREEN 조건 전부 충족, TODO 항목 종결 - 직렬 게이트 잔여: 동맹 포인터 타임아웃 결정 재현(3/3)·스윕 협폭 결함과 함께 조사 이관 기록 - 대시보드 213차 노트, 수집량 1111 갱신(체커 요구), SSOT 59 PASS --- docs/HANDOFF.md | 9 +- docs/TODO.md | 15 ++- docs/dev_dashboard.html | 5 +- docs/guides/testing.md | 4 +- .../nas-relay-recovery-2026-08-18.json | 123 +++++++++++------- docs/ops/evidence/usecase-tdd-2026-08-18.json | 5 +- 6 files changed, 100 insertions(+), 61 deletions(-) diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 2249ecc..b54f932 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -81,7 +81,14 @@ G8 배포 source 기준선은 branch `master`, HEAD `61a41d1f08239b5f9e99cfae42a RLS에 거부되던 잠복 결함 — pinned_fact의 SELECT/UPDATE 정책은 AI 뷰·admin 전용이다. 같은 learner uid로 `acquire(ai_view="evaluator")`를 열어 저장을 분리했고, 공개 DB 롤백 재현(learner 거부·AI 뷰 통과)으로 실증했다. 엔진 건강 시 deep 평가가 팩트를 반환하는 순간부터 발화하므로, degraded 구간 - E2E가 이 경로를 덮지 못한 이유도 같다. + E2E가 이 경로를 덮지 못한 이유도 같다. 소유자 실세션 종료 성공과 로컬 실API E2E 2회(종료 200 + + pinned_fact 실적재 실증)로 운영 검증했다. +- **2026-08-18 심야 연쇄 복구·NAS current GREEN**: 대청소 사건(node_modules·구 런타임 워크트리·Temp + 소실)으로 릴레이가 죽고, Docker Desktop 사망·whisper 9882 WinNAT 포트 예약·DHCP의 LAN IP 회수 + (223→224)가 겹쳤다. 릴레이를 현행 루트에 같은 핀으로 재기동하고 224로 계약 이전(방화벽 재발행·NAS + `.env` 재구성), 클로드 예산 한도 재발으로 NAS를 `agy_cli`로 전환해 health 3/3 engine true·auth 401· + OpenAPI 126·actual-origin turn→review smoke를 모두 통과 — 201차 current GREEN 달성. 권고 3건은 + `docs/ops/evidence/nas-relay-recovery-2026-08-18.json` 참조. ### 이 문서가 인계된 정확한 중단점 diff --git a/docs/TODO.md b/docs/TODO.md index da10525..33da459 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -90,13 +90,14 @@ 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 복구** — 2026-08-18 15:05 자동화로 시작 단계를 닫았다: `-CheckOnly` - 통과(4종 SHA pin) 뒤 실제 1회 시작이 **passed**(영수증 `receipt-actual-20260818.json`, ready 실생 통과)했고, - NAS→릴레이를 막던 방화벽(Python311 규칙 Public 한정 vs 이더넷 Private)을 LAN 서브넷 한정 9100 허용 규칙으로 - 풀어 NAS origin health 3/3 연속 `status=ok·db=true·engine=true`, auth 401, OpenAPI 126을 실측했다(2026-08-12 - 이후 처음). 남은 것: actual-origin 실제 회기 turn→review smoke 통과 전까지 current GREEN 표기는 보류하며, - 릴레이는 노트북 의존이라 NAS 로컬 agy 엔진 이전(소유자 제안)이 근본 해법 후보다. 증거: - `docs/ops/evidence/nas-relay-recovery-2026-08-18.json`. +- [x] **NAS preview engine relay current 복구** — 2026-08-18 심야 current GREEN 달성으로 종결. + `-CheckOnly` 프리플라이트(4종 SHA pin) → 실제 시작 passed → 방화벽(LAN 한정 9100) → health 3/3 + `status=ok·db=true·engine=true`·auth 401·OpenAPI 126 → **actual-origin 실회기 turn→review smoke 통과** + (agy 턴 2개→종료 200→리뷰 200). 대청소 사건으로 릴레이 루트가 삭제돼 현행 루트 `bf5f7352`로 재핀(r3 영수증)했고, + DHCP가 LAN IP를 224로 회수해 릴레이 바인딩·NAS `ENGINE_URL`을 `192.168.0.224:9100`으로 이전(방화벽 규칙 재발행, + NAS `.env(0600)` 재구성 + api만 재생성), 클로드 예산 한도 재발으로 NAS `ENGINE_MODE=agy_cli` 전환. 잔여 권고: + 공유기 DHCP 예약(호스트 MAC D8-BB-C1-A2-3C-5D), Docker VM 클럭 동기화(호스트 대비 ~4일 선행), + NAS 로컬 agy 이전(릴레이·노트북 의존 제거). 증거: `docs/ops/evidence/nas-relay-recovery-2026-08-18.json`. - [ ] **stable-source task 재등록 + 재부팅 후 watchdog smoke** — 사용자 승인 clean commit의 detached release root에 watchdog·로그온 boot task를 함께 재등록하고 action의 commit/tree/script SHA pin, 5분 watchdog `LastTaskResult=0`, 로그온 boot, 실제 Windows 재부팅 후 엔진/API/터널 자동 복구 + public `/turn`을 실측한다. diff --git a/docs/dev_dashboard.html b/docs/dev_dashboard.html index bf72720..a1917ac 100644 --- a/docs/dev_dashboard.html +++ b/docs/dev_dashboard.html @@ -687,10 +687,11 @@

206차 검증(2026-08-12): LF 계약 commit f380cc46…·tree a6865ba9…를 새 detached-clean worktree에 checkout해 tracked shell CRLF 0, 99_app_role.sh CR 0, local desktop-linux/npipe·보호 포트 재사용 0 preflight를 확인했다. 단일 periodic full run은 500.0초에 GREEN이었다. receipt periodic-learner-e2e-20260812-164929.json·SHA-256 14124ff6…ab67에서 실제 동일 학습자 회기 생성·SSE·review ready·G4/G5 0→1→1, 별도 returned-practice desktop/mobile 4/4, route mock 0을 확인했다. public·NAS·active DB 접촉은 0이고 container·volume·network·2726-2729 listener·engine PID·temp 잔여도 0이다. current source의 주기 회기 gate는 GREEN으로 복귀했으며, 공개 톱바 44px와 NAS 로그인 폭 보정은 별도 승인 배포 전까지 source-only다.

207차 UX·실회기 검증(2026-08-12): actual 공개 desktop 상단바의 브랜드·공간 전환·테마·로그아웃이 28~34px인 것을 다시 확인해, 모바일에만 있던 44px 계약을 모든 viewport로 승격했다. source는 브랜드 최소높이, 공간 링크 최소높이, 테마·로그아웃 44×44px을 유지하며 1280/1024/390/320 역할 최악 조건 2/2, 자기주도·G1~G7 route-fixture 82/82, type/API contract·production build를 통과했다. clean b02bee26…·tree 8f677bba…의 single periodic full run도 487.3초에 GREEN이었다. receipt periodic-learner-e2e-20260812-171547.json·SHA-256 8c11a136…af8e3에서 same-learner SSE·review ready·G4/G5 0→1→1, returned desktop/mobile 4/4, route mock 0, public·NAS·active DB 접촉 0과 container·volume·network·3853-3856 listener·engine PID·temp 잔여 0을 확인했다. 이 상단바와 NAS 로그인 폭 보정은 별도 승인 배포 전까지 source-only이고, current NAS health timeout·9100 listener 0은 유지된다.

208차 공개 Web 후보 고정(2026-08-12): detached-clean 00f851a6…c229·tree 9f78cd16…9486에서 generated API type LF 계약, npm ci --ignore-scripts, API type contract, typecheck와 2회 byte-identical production build를 통과했다. 새 primary CSS index-Dzmt2kJS.css SHA da5e8535…fb9a, JS index-BUoTLplD.js SHA 08654d08…3c05를 고정했고, 상단 44px·로그인 무가로넘침·학생 자기주도 홈→회기→복기→재연습 focused E2E는 desktop/mobile 12/12다. actual 공개와 최근 Pages 5개 origin의 lazy asset 133개를 더해 최종 732파일로 만들고 현행 공개 CSS/JS SHA를 exact 보존했다. actual 공개는 health ok·db/engine true·OpenAPI 126·auth 401·local voice exact, console/boot/overflow/[NAME] literal 0이지만 구 Web 상단 6개 조작면은 44px 미만이다. NAS 로그인은 200·auth 401·OpenAPI 126이지만 health timeout·9100 listener 0·모바일 overflow 10px다. 공개/NAS/API/DB/task/마이크 mutation은 0이며, Pages 승격·NAS relay·G7 physical proof를 서로 다른 승인 게이트로 유지한다. 증거는 docs/ops/evidence/public-web-preflight-2026-08-12.json이다.

-

209차 적용·배포(2026-08-18): 공개 엔진 06:30~10:05 3.5시간 장애의 게이트웨이 결함(readiness 실패를 성공과 동일 1800초 캐시 + 고효율 콜드 프로브 20초 오판)을 실패 전용 TTL 30초 분리·타임아웃 45초로 수정해 detached-clean 4771b97c…c880로 재승격했다(회귀 4건, backend 986 passed). 유스케이스 TDD로 uc-*.spec.ts 16테마 239 시나리오를 RED 우선 작성하고(수집 1109 tests/61 files) 지원 티켓 작성 UI·관리자 해결 노트·포커스 링·라벨/헤딩/대비/44px/오버플로 제품 결함을 닫았다. fixture 병렬 게이트 1040 passed(데스크톱 밀도 충돌 1건 해소 후 focused 68/68), 직렬 게이트 52/5/4의 5실패는 삼각화해 widthsFor 솎아내기 실기기 폭 탈락 테스트 결함 교정·낡은 dev API(:8000) 재기동으로 kb·voice 해소, 교사 재평가 2건은 엔진 구독 한도(resets 3pm)로 skip 후 15:05 자동화로 재검증을 이관했다. 소유자 승인 아래 Cloudflare Pages production 4edc02d3(clean cf899b7f…7c96, 빌드×2 결정성 599파일)를 배포 — 7개 origin에서 143자산 보존(최종 742파일), 커스텀 도메인은 새 엔트리 index-BWxBaCPM.js/index-BUfQc2Rm.css 서빙, 직전 엔트리 자산 200 보존을 확인했다(증거 public-web-deploy-2026-08-18.json). NAS 엔진 릴레이는 같은 승인으로 start-nas-preview-engine.ps1 -CheckOnly가 4종 SHA pin+LAN 192.168.0.223:9100 바인딩으로 통과했고(mutation=false, NAS 컨테이너/DB 무접촉), 실제 1회 시작+NAS health 3회·auth 401·OpenAPI 126 재검증은 엔진 한도 리셋 뒤 동일 자동화가 수행한다(증거 nas-relay-recovery-2026-08-18.json).

+

209차 적용·배포(2026-08-18): 공개 엔진 06:30~10:05 3.5시간 장애의 게이트웨이 결함(readiness 실패를 성공과 동일 1800초 캐시 + 고효율 콜드 프로브 20초 오판)을 실패 전용 TTL 30초 분리·타임아웃 45초로 수정해 detached-clean 4771b97c…c880로 재승격했다(회귀 4건, backend 986 passed). 유스케이스 TDD로 uc-*.spec.ts 16테마 239 시나리오를 RED 우선 작성하고(수집 1111 tests / 61 files) 지원 티켓 작성 UI·관리자 해결 노트·포커스 링·라벨/헤딩/대비/44px/오버플로 제품 결함을 닫았다. fixture 병렬 게이트 1040 passed(데스크톱 밀도 충돌 1건 해소 후 focused 68/68), 직렬 게이트 52/5/4의 5실패는 삼각화해 widthsFor 솎아내기 실기기 폭 탈락 테스트 결함 교정·낡은 dev API(:8000) 재기동으로 kb·voice 해소, 교사 재평가 2건은 엔진 구독 한도(resets 3pm)로 skip 후 15:05 자동화로 재검증을 이관했다. 소유자 승인 아래 Cloudflare Pages production 4edc02d3(clean cf899b7f…7c96, 빌드×2 결정성 599파일)를 배포 — 7개 origin에서 143자산 보존(최종 742파일), 커스텀 도메인은 새 엔트리 index-BWxBaCPM.js/index-BUfQc2Rm.css 서빙, 직전 엔트리 자산 200 보존을 확인했다(증거 public-web-deploy-2026-08-18.json). NAS 엔진 릴레이는 같은 승인으로 start-nas-preview-engine.ps1 -CheckOnly가 4종 SHA pin+LAN 192.168.0.223:9100 바인딩으로 통과했고(mutation=false, NAS 컨테이너/DB 무접촉), 실제 1회 시작+NAS health 3회·auth 401·OpenAPI 126 재검증은 엔진 한도 리셋 뒤 동일 자동화가 수행한다(증거 nas-relay-recovery-2026-08-18.json).

210차 적용·승격(2026-08-18 오후): 관리자 AI 운영에서 agy_cli 카탈로그가 빈 것은 이중 결함이었다 — ① agy CLI가 agy modelsid<TAB>라벨 형식으로 바꾼 것을 파서가 못 읽었고(5afd92f8), ② 승격 체인의 psutil 환경 이식에서 SystemRoot가 유실돼 Go 계열 CLI가 인증서 풀 해석에 실패해 빈 목록을 조용히 반환했다(6369f294_cli_subprocess_env 필수 변수 백필 + 런처 Machine 스코프 병합). 공개 런타임을 6369f294로 승격하고 워치독(install-public-runtime-task.ps1)과 부트(register-boot-task.ps1) 태스크를 모두 새 루트에 재핀했다 — 부트만 갱신하면 구 루트 워치독이 5분마다 되살려 경합한다. 검증: engine_gateway 65 passed·app 924 passed, 공개 게이트웨이 capabilities 14모델, 실생 턴 gemini-3.6-flash-high 응답·토큰/비용 계약 통과. 증거는 docs/ops/evidence/agy-provider-recovery-2026-08-18.json이다.

211차 복구·재검증(2026-08-18 15:05 자동화): 엔진 구독 한도 리셋 직후 NAS 엔진 릴레이 실제 1회 시작이 4종 SHA pin 그대로 passed(영수증 receipt-actual-20260818.json, PID 65328, ready 실생 통과). NAS→릴레이 TCP가 막혀 있던 것은 Python311 인바운드 허용 규칙이 Public 프로필뿐인데 이더넷이 Private이라서였고, LAN 서브넷 한정 9100 허용 규칙 추가(소유자 UAC 승인) 뒤 NAS origin health 3/3 연속 status=ok·db·engine true, auth 401, OpenAPI 126을 실측 — 2026-08-12 이후 처음이다. current GREEN 표기는 actual-origin 실제 회기 turn→review smoke가 남아 보류. 같은 자동화의 직렬 게이트 재실행은 31 passed/14 failed/12 did-not-run로 실패: 파서 수정 후 첫 실행된 breakpoint 실측 스윕이 settings/learner 협폭 결함 91건을 보고했고(아침 실행에선 연쇄 중단으로 미실행), session-mvp·persistence·voice 실패군은 아침 동일 웹 코드 통과에 근거해 스택·데이터 드리프트가 의심된다 — 원인 조사로 이관, 가짜 증거 금지로 게이트 pending 유지. 증거는 docs/ops/evidence/nas-relay-recovery-2026-08-18.json·usecase-tdd-2026-08-18.json이다.

212차 핫픽스(2026-08-18 오후): 공개 POST /sessions/{id}/end 503(소유자 실사용 보고)의 원인은 회기 종료의 pinned_fact upsert가 learner 역할 연결로 실행된 것이었다. app.pinned_fact RLS는 learner에 INSERT(소유 케이스)만 허용하고 SELECT/UPDATE는 AI 컨텍스트·admin/instructor 전용이라 SELECT … FOR UPDATE + INSERT … ON CONFLICT DO UPDATE 조합이 충돌 후보 가시성에서 InsufficientPrivilegeError로 실패하고 fallback 차단이 503으로 노출됐다. 공개 DB 롤백 재현으로 단순 INSERT는 통과·ON CONFLICT 조합은 거부·ai_view=evaluator 컨텍스트는 전체 upsert 통과를 실증했고(bf5f7352), pinned_fact 저장만 같은 learner uid의 AI evaluator 뷰 연결로 분리했다. 검증: 관련 62 passed·app 924 passed, 공개 8001 승격 후 health ok. 엔진이 건강해 deep 평가가 처음 팩트를 반환한 순간 발화한 잠복 결함으로, 아침 degraded 구간엔 팩트가 비어 이 경로가 실행되지 않았다.

+

213차 복구·전환(2026-08-18 심야): 대청소 사건(node_modules·구 런타임 워크트리·Temp 소실)과 Docker Desktop 사망·whisper 9882 WinNAT 포트 예약·DHCP LAN IP 회수(223→224)가 연쇄 발생했다. 릴레이를 현행 루트 bf5f7352에 같은 4종 핀으로 재기동(r3 영수증)하고 192.168.0.224:9100으로 바인딩(방화벽 규칙 재발행), NAS는 실행 컨테이너 env 전량을 .env(0600)로 재구성해 ENGINE_URL 224 적용 후 api만 재생성했다. 클로드 예산 한도(Reached maximum budget $0.5)가 재발해 NAS ENGINE_MODE를 agy_cli(gemini)로 전환 — 공개는 소유자가 이미 관리자 UI로 agy 전환 완료. 결과: NAS origin health 3/3 status=ok·db·engine true, auth 401, OpenAPI 126, actual-origin 실회기 turn→review smoke 통과(agy 턴 2개→종료 200→리뷰 200) — 2026-08-12 이후 처음으로 201차 current GREEN 조건을 모두 충족했다. 회기 종료 503 핫픽스(bf5f7352)도 소유자 실세션 종료 성공으로 운영 검증. 권고: 공유기 DHCP 예약(호스트 MAC), Docker VM 클럭 동기화(호스트 대비 ~4일 선행 — DB 타임스탬프 오염), NAS 로컬 agy 이전. 증거는 docs/ops/evidence/nas-relay-recovery-2026-08-18.json이다.

래스터만 사용이미지 생성 도구 산출물은 PNG 기반 시안이다. SVG·벡터·와이어프레임·로고 시트로 해석하지 않는다.
기능 우선메인 라우트의 실제 액션과 정보 구조를 먼저 반영한다. 장식은 기능을 가리지 않는 수준에서만 쓴다.
@@ -1101,7 +1102,7 @@ Web typechecknpm run typecheckPassed Design SSOT / auth visualnpm run check:design-ssot / npx playwright test e2e/auth-visual.spec.ts --project=chromium-single-run --reporter=line / npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --reporter=lineSSOT checker passed; login/onboarding light-dark desktop-mobile 1 passed; 14 core screens × 7 widths visual gate 14 passed. - Full Playwright E2E baselinenpm run e2e:parallel / npm run e2e:single-run / npm run e2e:list2026-08-18 현재 수집은 1109 tests / 61 files다(유스케이스 16테마 uc-*.spec.ts 239 시나리오 추가). 이 숫자는 수집량이며 현 작업트리 전체 GREEN과 동일하지 않다. G8 clean-head release gate는 candidate 112/112와 실제 NAS-origin 112/112를 통과했다. 이전 단일 120/120과 2026-07-15의 fixture desktop/mobile 166/166 + DB/engine/provider 직렬 49/49 = 215/215는 범위가 다른 역사 기준선으로 보존한다. + Full Playwright E2E baselinenpm run e2e:parallel / npm run e2e:single-run / npm run e2e:list2026-08-18 현재 수집은 1111 tests / 61 files다(유스케이스 16테마 uc-*.spec.ts 239 시나리오 추가). 이 숫자는 수집량이며 현 작업트리 전체 GREEN과 동일하지 않다. G8 clean-head release gate는 candidate 112/112와 실제 NAS-origin 112/112를 통과했다. 이전 단일 120/120과 2026-07-15의 fixture desktop/mobile 166/166 + DB/engine/provider 직렬 49/49 = 215/215는 범위가 다른 역사 기준선으로 보존한다. Refactor governance P1~P8ruff check app / pytest -q app / pytest -q engine_gateway / npm run typecheck / npm run check:api-types / npm run check:design-ssot / npm run check:dead-code / npm run check:duplication / npm run build / npm audit --audit-level=high / full PlaywrightBackend 400 passed, gateway 29 passed, web gates/build/audit passed, vulnerabilities 0, production duplication 1 clone/15 lines/0.03%, Playwright 215/215 passed. 상세 근거는 ops/refactor-governance-2026-07-15.md. API typegen SSOTnpm run check:api-typesPassed; FastAPI OpenAPI → src/lib/api.gen.ts stale check Outcome & Alliance OS G0py -3.11 -X utf8 -m pytest -p no:cacheprovider apps/api/app/test_measurement_contract.py apps/api/app/test_runtime_schema_ssot.py -q / scripts/check-measurement-ledger.sql / measurement·API contract checks / web typecheck / DB-backed session-persistence focused E2E 3종G0 contract/schema 11 passed, 기존 backend 100 passed, auth 39 passed. Python→JSON Schema→TypeScript→PostgreSQL enum·필수필드 계약이 일치하고 8개 deterministic benchmark가 검증됐다. Live PostgreSQL에서 learner/client/evaluator 가시 행 1/1/2, 교차 누수 0, append-only guard 2를 확인했다. 학습자 턴→교수자 대시보드, 워크시트 검수, 종료 deep 평가→durable 리뷰 E2E는 각각 1 passed. G0/AOS-001~004 완료. diff --git a/docs/guides/testing.md b/docs/guides/testing.md index 8aed8aa..74c9ccd 100644 --- a/docs/guides/testing.md +++ b/docs/guides/testing.md @@ -20,7 +20,7 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타 | API 타입 생성 체크 | `apps/web` | `npm run check:api-types` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass | | 웹 타입체크 | `apps/web` | `npm run typecheck` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass | | 웹 빌드 | `apps/web` | `npm run build` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass | -| Playwright E2E(전체) | `apps/web` | `npm run e2e` | **필요(+시드)** | **필요** | 자동기동 | 일부만 | **필요** | 현재 수집 1109 tests / 61 files · 현 작업트리 전체 GREEN 미검증 | +| Playwright E2E(전체) | `apps/web` | `npm run e2e` | **필요(+시드)** | **필요** | 자동기동 | 일부만 | **필요** | 현재 수집 1111 tests / 61 files · 현 작업트리 전체 GREEN 미검증 | 핵심 원칙: **단위 테스트(pytest)와 타입체크/빌드는 외부 서비스 없이 단독 실행된다.** **E2E만 풀스택(DB+API+웹+브라우저)을 요구한다.** 아래 각 절에서 근거와 절차를 설명한다. @@ -271,7 +271,7 @@ VITE_API_BASE=http://127.0.0.1:8000 npm run e2e # 프록시 대신 API ### 3.6 실측 테스트 개수 (현재) -2026-08-18 `npx playwright test --list` 기준 **현재 수집 1109 tests / 61 files**다 +2026-08-18 `npx playwright test --list` 기준 **현재 수집 1111 tests / 61 files**다 (유스케이스 16테마 `uc-*.spec.ts` 239 시나리오 포함). 이 숫자는 수집량이지 통과량이 아니다. 현 작업트리 전체 1109개 완주는 아직 증거가 없으며, 과거 전체 GREEN 기록과 이번 focused/release gate 결과를 구분해 적는다. diff --git a/docs/ops/evidence/nas-relay-recovery-2026-08-18.json b/docs/ops/evidence/nas-relay-recovery-2026-08-18.json index 82b9913..f34db86 100644 --- a/docs/ops/evidence/nas-relay-recovery-2026-08-18.json +++ b/docs/ops/evidence/nas-relay-recovery-2026-08-18.json @@ -1,52 +1,81 @@ { - "schema": "vignette.nas-relay-recovery.v1", - "captured_at": "2026-08-18T15:48:00+09:00", - "owner_approval": "2026-08-18 소유자 지시로 남은 작업 3순위로 'NAS 엔진 릴레이 복구(start-nas-preview-engine.ps1 -CheckOnly → 실제 1회 시작 → NAS health/auth/OpenAPI 재검증)'를 명시해 마무리를 지시함. LAN 노출(192.168.0.223:9100)은 중단 세션에서 명시 승인 완료. 방화벽 규칙 추가(관리자 승격)는 실행 시점 소유자 UAC 승인.", - "checkonly": { - "status": "preflight_passed", - "mutation": false, - "receipt_path": "D:\\workspace\\nas-relay-state\\receipt-checkonly-20260818.json", - "binding": { - "source_commit": "4771b97c3a9a4c52349f8a6a55a08a3ce0a5c880", - "source_tree": "286723de877ed950c36656d5598fdf2d57c861fa", - "launcher_sha256": "492d8b5c4ba21d1463c9a937ac2949f0a6d3725f6f37786f14dd5aac419fb27c", - "python_sha256": "5f7b89a612c9b8af1d6456cdfcd1dbe5ca630849e79aebced9bee9a6694952ec", - "env_sha256": "312afcb50c11be16d90fa6ad79c0b416f9d65c4877c06aeafd436260f18c18ec", - "listen_address": "192.168.0.223", - "port": 9100, - "consumer_engine_url": "http://192.168.0.223:9100", - "secret_value_emitted": false - } + "schema": "vignette.nas-relay-recovery.v1", + "captured_at": "2026-08-18T15:48:00+09:00", + "owner_approval": "2026-08-18 소유자 지시로 남은 작업 3순위로 'NAS 엔진 릴레이 복구(start-nas-preview-engine.ps1 -CheckOnly → 실제 1회 시작 → NAS health/auth/OpenAPI 재검증)'를 명시해 마무리를 지시함. LAN 노출(192.168.0.223:9100)은 중단 세션에서 명시 승인 완료. 방화벽 규칙 추가(관리자 승격)는 실행 시점 소유자 UAC 승인.", + "checkonly": { + "status": "preflight_passed", + "mutation": false, + "receipt_path": "D:\\workspace\\nas-relay-state\\receipt-checkonly-20260818.json", + "binding": { + "source_commit": "4771b97c3a9a4c52349f8a6a55a08a3ce0a5c880", + "source_tree": "286723de877ed950c36656d5598fdf2d57c861fa", + "launcher_sha256": "492d8b5c4ba21d1463c9a937ac2949f0a6d3725f6f37786f14dd5aac419fb27c", + "python_sha256": "5f7b89a612c9b8af1d6456cdfcd1dbe5ca630849e79aebced9bee9a6694952ec", + "env_sha256": "312afcb50c11be16d90fa6ad79c0b416f9d65c4877c06aeafd436260f18c18ec", + "listen_address": "192.168.0.223", + "port": 9100, + "consumer_engine_url": "http://192.168.0.223:9100", + "secret_value_emitted": false + } + }, + "nas_consumer_contract_observed": { + "engine_url": "http://192.168.0.223:9100", + "engine_mode": "claude_cli", + "source": "docker inspect vignette-preview-20260807 api 컨테이너 환경(2026-08-18 실측)" + }, + "actual_start": { + "status": "passed", + "started_at": "2026-08-18T06:25:35Z (15:25:35 KST)", + "receipt_path": "D:\\workspace\\nas-relay-state\\receipt-actual-20260818.json", + "pid": 65328, + "checks": { + "source_detached_clean": true, + "port_previously_unused": true, + "listener_owner_matches": true, + "liveness_ok": true, + "generation_ready": true }, - "nas_consumer_contract_observed": { - "engine_url": "http://192.168.0.223:9100", - "engine_mode": "claude_cli", - "source": "docker inspect vignette-preview-20260807 api 컨테이너 환경(2026-08-18 실측)" + "notes": "엔진 구독 한도(15:00 KST) 리셋 직후 15:05 자동화가 실행했다. ready?force=true 실생 1회 통과." + }, + "firewall_fix": { + "problem": "NAS→릴레이 TCP 연결 타임아웃(transport error). 릴레이의 Python311 인바운드 허용 규칙이 Public 프로필뿐이었고 이더넷 네트워크는 Private.", + "fix": "인바운드 TCP 9100 허용 규칙 추가 — LocalAddress 192.168.0.223, RemoteAddress 192.168.0.0/24, Profile Private(소유자 UAC 승인). 규칙명 'Vignette NAS preview engine relay (9100 LAN)'." + }, + "verification": { + "local_relay_health": "http://192.168.0.223:9100/health → {ok:true, engine:claude_cli}", + "nas_origin_health_3_consecutive": "http://100.116.83.60:8088/api/health → status=ok, db=true, engine=true, engine_detail=OK (3/3)", + "auth_me_status": 401, + "openapi_paths": 126, + "nas_to_relay_probe_from_nas": "SSH YunChan@100.116.83.60 → curl 192.168.0.223:9100/health → ok:true" + }, + "remaining_for_full_current_green": "201차 계약의 actual-origin 실제 회기 turn→review smoke는 아직 실행 전 — health/auth/OpenAPI 회복만으로 current GREEN 표기하지 않는다.", + "restarts_and_migration_2026_08_18_evening": { + "incident_chain": [ + "워크스페이스 대청소 사건: apps/web/node_modules 소실, 구 런타임 워크트리(4771b97c/6369f294 등) 삭제, %LOCALAPPDATA%\\Temp 정리 — 이 사건으로 릴레이(워크스페이스가 사라짐)와 whisper 사이드카 로그가 사망", + "Docker Desktop 사망(공개 DB 포함) → 재기동 + vignette-dev-db 복구(healthy)", + "whisper 사이드카(9882)가 Windows 제외 포트 범위(9791-9890, WinNAT 동적)에 걸려 바인딩 거부 → winnat 재시작 + 9882 단일 고정 예약(UAC)", + "DHCP가 호스트 LAN IP를 192.168.0.223 → 224로 회수/재할당 — NAS 계약 주소 상실" + ], + "migration": { + "relay_root": "D:\\workspace\u000bignette-public-runtime-bf5f7352 (구 루트 삭제로 현행 승격 루트로 재핀)", + "listen": "192.168.0.224:9100 (방화벽 규칙 224로 재발행, LAN 서브넷 한정)", + "receipts": [ + "receipt-actual-20260818-r3.json (바인딩 bf5f7352/c39f917b, launcher·python·env SHA 동일 핀)" + ], + "nas_side": "프로젝트 .env(0600)를 실행 컨테이너 env 전량 추출로 재구성해 ENGINE_URL=http://192.168.0.224:9100 적용, api 컨테이너만 재생성(-p vignette-preview-20260807)", + "engine_provider": "엔진 예산 한도(Reached maximum budget $0.5 — 클로드 구독)가 재발해 ENGINE_MODE=agy_cli(gemini)로 전환. 소유자가 공개는 이미 관리자 UI로 agy 전환 완료 상태였음" }, - "actual_start": { - "status": "passed", - "started_at": "2026-08-18T06:25:35Z (15:25:35 KST)", - "receipt_path": "D:\\workspace\\nas-relay-state\\receipt-actual-20260818.json", - "pid": 65328, - "checks": { - "source_detached_clean": true, - "port_previously_unused": true, - "listener_owner_matches": true, - "liveness_ok": true, - "generation_ready": true - }, - "notes": "엔진 구독 한도(15:00 KST) 리셋 직후 15:05 자동화가 실행했다. ready?force=true 실생 1회 통과." + "verification_after_migration": { + "nas_origin_health_3_consecutive": "status=ok, db=true, engine=true, engine_mode=agy_cli (3/3)", + "auth_me_status": 401, + "openapi_paths": 126, + "actual_origin_turn_to_review_smoke": "dev-login→온보딩→회기 생성→agy 턴 2개(33.9s/32.4s)→종료 200→review 200(서연 P1 실데이터, session 4d02bdfe-e2bf-41d5-9b28-7808d6b108a6) — 201차 current GREEN 조건 전부 충족", + "note": "NAS 구 릴리스(2026-08-09) 코드에서 종료 직후 상세 조회가 active로 보이는 비동기 지연 관찰(리뷰는 정상 200)" }, - "firewall_fix": { - "problem": "NAS→릴레이 TCP 연결 타임아웃(transport error). 릴레이의 Python311 인바운드 허용 규칙이 Public 프로필뿐이었고 이더넷 네트워크는 Private.", - "fix": "인바운드 TCP 9100 허용 규칙 추가 — LocalAddress 192.168.0.223, RemoteAddress 192.168.0.0/24, Profile Private(소유자 UAC 승인). 규칙명 'Vignette NAS preview engine relay (9100 LAN)'." - }, - "verification": { - "local_relay_health": "http://192.168.0.223:9100/health → {ok:true, engine:claude_cli}", - "nas_origin_health_3_consecutive": "http://100.116.83.60:8088/api/health → status=ok, db=true, engine=true, engine_detail=OK (3/3)", - "auth_me_status": 401, - "openapi_paths": 126, - "nas_to_relay_probe_from_nas": "SSH YunChan@100.116.83.60 → curl 192.168.0.223:9100/health → ok:true" - }, - "remaining_for_full_current_green": "201차 계약의 actual-origin 실제 회기 turn→review smoke는 아직 실행 전 — health/auth/OpenAPI 회복만으로 current GREEN 표기하지 않는다." + "recommendations": [ + "공유기에서 호스트 MAC(D8-BB-C1-A2-3C-5D)에 192.168.0.224 DHCP 고정 예약 — 재발 방지(소유자 조치)", + "Docker Desktop VM 클럭이 호스트보다 ~4일 선행(DB 타임스탬프 오염) — wsl --shutdown 후 재기동으로 동기화 필요(소유자 승인 대기)", + "NAS 로컬 agy 설치가 릴레이·노트북 의존을 완전히 제거하는 근본 해법" + ] + } } diff --git a/docs/ops/evidence/usecase-tdd-2026-08-18.json b/docs/ops/evidence/usecase-tdd-2026-08-18.json index 7ff3c77..2e29e0f 100644 --- a/docs/ops/evidence/usecase-tdd-2026-08-18.json +++ b/docs/ops/evidence/usecase-tdd-2026-08-18.json @@ -54,8 +54,9 @@ "serial_single_run_gate_followup": { "initial_run": "2026-08-18 11:10-11:22 KST npm run e2e:single-run: 52 passed / 5 failed / 4 skipped (12.1m)", "triage_and_rerun": "① breakpoint-sweep '실기기 대표 폭 누락'은 widthsFor 솎아내기가 DEVICE_WIDTHS 를 boundary 중복이라고 제외 후 상한 솎기로 탈락시키는 테스트 결함(제품 아님) — keep 시드를 전체 DEVICE_WIDTHS 로 교정하고 3연폭 예외 조건을 솎아내기 발생 여부 기준으로 고침 → focused 1 passed. ② kb-source-packs 500은 게이트웨이 수정 커밋(4771b97c) 이전에 기동한 낡은 dev API(:8000) 프로세스가 원인 — 재기동 후 focused 1 passed. ③ voice-success 2 tests 재실행 2 passed(일시적 환경). ④ session-persistence 교사 재평가 2건은 엔진 실생 턴 필요 — Claude 구독 세션 한도('resets 3pm Asia/Seoul')로 엔진 가용 게이트가 skip 처리.", - "pending": "직렬 게이트 14실패 해소 전까지 종결 아님 — (1) 스윕이 보고한 settings/learner 협폭 레이아웃 결함 91건 제품 수정, (2) 스택·데이터 드리프트 의존 실패군 원인 규명, (3) 교사 재평가 2건 재실행이 남아 있다(가짜 증거 금지 원칙으로 이 파일의 pending은 유지).", - "rerun_2026_08_18_15:05": "엔진 한도 리셋 직후 재실행: 31 passed / 14 failed / 4 skipped / 12 did-not-run(직렬 연쇄 중단). 교사 재평가 2건은 파일 내 선행 실패로 실행하지 못했다. 삼각화: (a) breakpoint-sweep 3종은 파서 수정 후 처음 실행된 실측 스윕이 settings/learner 320px 등에서 레이아웃 결함 91건을 보고 — 아침 실행에서는 파서 테스트 실패로 스윕이 연쇄 중단돼 실행되지 않았던 것. (b) session-mvp strict-mode 위반('코칭' 버튼 3개), session-persistence·layout-visual-gate '동맹 기준 포인터 선택' 타임아웃, voice 2종 실패는 아침 11:10 동일 웹 코드(cf899b7f)에서 통과했으므로 웹 커밋이 아닌 스택·데이터 드리프트(9099 게이트웨이 6369f294 교체, dev DB 누적 데이터)가 의심되며 원인 조사 진행 중. 게이트 엔진 경로 자체는 정상(클로드 일회/세션 턴 실측 응답)." + "pending": "① '동맹 기준 포인터 선택' 타임아웃의 근본 원인(agy 스트리밍 케이던스 vs 체크포인트 헬퍼, 또는 제품 회귀) 규명 ② breakpoint-sweep이 보고한 settings/learner 협폭 레이아웃 결함 91건 제품 수정 ③ 위 해소 후 교사 재평가 2건 포함 직렬 게이트 전체 GREEN 재검증. (엔진·스택 헬스는 모두 정상, NAS actual-origin smoke는 별도 통과)", + "rerun_2026_08_18_15:05": "엔진 한도 리셋 직후 재실행: 31 passed / 14 failed / 4 skipped / 12 did-not-run(직렬 연쇄 중단). 교사 재평가 2건은 파일 내 선행 실패로 실행하지 못했다. 삼각화: (a) breakpoint-sweep 3종은 파서 수정 후 처음 실행된 실측 스윕이 settings/learner 320px 등에서 레이아웃 결함 91건을 보고 — 아침 실행에서는 파서 테스트 실패로 스윕이 연쇄 중단돼 실행되지 않았던 것. (b) session-mvp strict-mode 위반('코칭' 버튼 3개), session-persistence·layout-visual-gate '동맹 기준 포인터 선택' 타임아웃, voice 2종 실패는 아침 11:10 동일 웹 코드(cf899b7f)에서 통과했으므로 웹 커밋이 아닌 스택·데이터 드리프트(9099 게이트웨이 6369f294 교체, dev DB 누적 데이터)가 의심되며 원인 조사 진행 중. 게이트 엔진 경로 자체는 정상(클로드 일회/세션 턴 실측 응답).", + "rerun_2026_08_18_evening": "인프라 완전 복구 후(Docker/사이드카/워크트리/node_modules 재설치, 엔진 agy 전환) 재실행: voice·mvp·layout·persistence 4파일 19 failed / 2 passed / 14 did-not-run. 지배 실패는 '동맹 기준이 실제 포인터 입력으로 선택되어야 한다'(support.ts completeAlliancePreCheckpoint의 실마우스 클릭 15초 타임아웃)로 세션 진행 중 재연습 체크포인트에서 결정적으로 재현(3/3). 아침 11:10 동일 웹 코드로 통과했으므로 웹 커밋이 아니라 13:59 소유자의 엔진 agy 전환 이후 생성 타이밍 변화(SSE/재레ender 주기)와 체크포인트 헬퍼의 상호작용이 일차 용의다. 세부 조사는 별도 작업으로 이관." } }, "boundaries": "route fixture 검증이므로 실제 로그인/API/DB 증거가 아니다. 실 DB-backed 증거는 기존 @single-run·closed-loop 스펙이 소유한다."