docs: 2026-09-08 실배포 및 TDD 불변식 검증 결과 문서 현행화

This commit is contained in:
Yun Chan 2026-09-09 05:42:05 +09:00
parent d9bb5b3697
commit aa951c6c4a
4 changed files with 37 additions and 12 deletions

View file

@ -1,16 +1,21 @@
# Vignette 현행 인수인계 # Vignette 현행 인수인계
> 기준일: 2026-09-07 KST > 기준일: 2026-09-09 KST
> 상태·결정의 SSOT는 [`dev_dashboard.html`](./dev_dashboard.html)이다. 이 문서는 다음 실행 순서와 금지 경계만 요약한다. > 상태·결정의 SSOT는 [`dev_dashboard.html`](./dev_dashboard.html)이다. 이 문서는 다음 실행 순서와 금지 경계만 요약한다.
> 2026-08-18 이전 상세 기록은 [정리 전 HANDOFF 원문](./archive/project-cleanup-2026-09-07/HANDOFF-before-cleanup.md)에 보존했다. > 2026-08-18 이전 상세 기록은 [정리 전 HANDOFF 원문](./archive/project-cleanup-2026-09-07/HANDOFF-before-cleanup.md)에 보존했다.
## 현재 기준 ## 현재 기준
2026-09-01 당시 Forgejo master `dce85620`을 NAS `vignette-prod`에 배포했다. migration 20/21/22를 온라인 적용했고, 공개 health·OpenAPI·`/auth/me`·dev-login 경계와 소유자 실계정의 새 사례→턴→리뷰 폐루프를 확인했다. 일일 검증형 DB 백업 sidecar의 첫 실행도 그날 성공했다. 이는 당시 증거이며 오늘의 live 상태를 뜻하지 않는다. 2026-09-08 Forgejo master `a0311c59` (배포 문서 포함 `d9bb5b36`)를 NAS `vignette-prod` 및 Cloudflare Pages에 정식 실배포했다. 사전 DB 덤프(`/volume1/docker/vignette-prod/backups/pre-deploy-a0311c59-.dump`, 12MB) 및 `env.nas` 백업을 생성한 뒤 NAS 컨테이너(API `sha256:8b1ed23d1d24...`, Web `sha256:5c34139d8b56...`)를 교체·기동했다. Cloudflare Pages는 174개 자산을 보존하며 `https://vignette.chanpaca.net`(미리보기: `2df910db.vignette-b1q.pages.dev`)으로 배포 완료했다. 공개 health(`https://api-vignette.chanpaca.net/health` status:ok, db/engine/openai:true), `/auth/me`(401 Unauthorized fail-closed), 웹 서비스 live 폐루프를 확인했다.
증거: [NAS 배포 증거](./ops/evidence/nas-prod-deploy-2026-09-01.json). TDD 기반 회귀 방지 및 핵심 불변식을 확정했다:
- REQ-010: 회기 무발화 0턴 분리 (`LearnerGrowthMetrics.ended_sessions` 및 대시보드 프로젝션에서 발화 없는 세션을 완료 회기 집계에서 안전하게 분리·제외)
- REQ-011: OAS G5 자기예측 `[0.0, 1.0]` 범위 도메인 검증 및 DB 트리거 수준 락 보장/예외 전환 (`CalibrationTransferStateError`)
- REQ-009: 웹 클라이언트 스트림 에러 시 입력문 복원(`setComposeText(text)`) 및 로딩 상태(`clientReplyPending`) 복원 보장
파일 위생·문서 통합·수용된 코드 경계 정리·리뷰 수정은 이번 차수에서 완료했다. API는 outcome repository 공통값·practice competency 분류·인증/admin projection·text/voice 공통 turn memory·voice metadata 경계를, web은 focus trap·동맹 scale/잠긴 점수·승인 제출 제어 경계를 정리했다. `Knip` dead-code, measurement contract, typecheck/build, Ruff와 API 전체 1090 passed/1 skipped/1 warning, gateway 전체 71 passed/1 warning이 통과했다. 중복은 17 clone/294줄에서 3 clone/48줄·265 tokens(0.04%)로 감소했다. orchestrator retry는 임상 검수 exact-HEAD 원본 고정 경계로, voice abort와 repository query는 서로 다른 lifecycle·도메인 계약으로 유지한다. REQ-009~011, 전 기능·실환경 QA, 외부 운영·임상 게이트는 열린 상태를 유지한다. 단위/회귀 테스트는 API 전체 1104 passed / 1 skipped / 1 warning, gateway 전체 71 passed / 1 warning, web typecheck 및 build 전건 통과를 달성했다.
증거: [NAS 배포 파이프라인](./ops/deployment-pipeline.md), [1차 배포 증거](./ops/evidence/nas-prod-deploy-2026-09-01.json).
## 남은 실행 항목 ## 남은 실행 항목
@ -19,18 +24,18 @@
3. 백업 운영화: 실패 알림, off-host 암호화 복제, 정기 restore drill을 운영 증거로 남긴다. 3. 백업 운영화: 실패 알림, off-host 암호화 복제, 정기 restore drill을 운영 증거로 남긴다.
4. 아바타 fail-closed 후보: 원본과 DB 참조를 보존한 채 public fallback·digest receipt·브라우저 검증을 마친 뒤에만 승격 판단한다. 4. 아바타 fail-closed 후보: 원본과 DB 참조를 보존한 채 public fallback·digest receipt·브라우저 검증을 마친 뒤에만 승격 판단한다.
5. G7/G8 외부 게이트: G7은 동의 기반 물리 마이크와 독립 voice-gain 증거, G8은 실DB append-only 사람 게이트와 public proof가 남아 있다. 5. G7/G8 외부 게이트: G7은 동의 기반 물리 마이크와 독립 voice-gain 증거, G8은 실DB append-only 사람 게이트와 public proof가 남아 있다.
6. 신규 제품 이슈: REQ-009와 REQ-011을 재현·원인 분류한 뒤 REQ-010의 회기 count/취소 정책을 확정한다. 원문 워크북 상태는 `TODO.md`의 로컬 상태와 분리해 보존한다. 6. 신규 제품 이슈: REQ-009, REQ-010, REQ-011은 TDD 불변식 추가 및 헤드풀 브라우저 E2E 검증, 실서버 배포를 완료했다. 외부 원본 워크북과의 최종 동기화만 남아 있다.
세부 ID·차단 이유·완료 조건은 [`TODO.md`](./TODO.md)와 [열린 백로그](./ops/backlog-2026-06-26.md)에 있다. 세부 ID·차단 이유·완료 조건은 [`TODO.md`](./TODO.md)와 [열린 백로그](./ops/backlog-2026-06-26.md)에 있다.
## 재개 순서 ## 재개 순서
1. OS·셸·현재 Git 상태를 확인하고, dashboard와 이 문서·TODO·backlog를 읽는다. 1. OS·셸·현재 Git 상태를 확인하고, dashboard와 이 문서·TODO·backlog를 읽는다.
2. 필요한 항목의 2026-09-01 증거와 현재 NAS 상태를 read-only로 구분해 확인한다. 2. 필요한 항목의 배포 증거와 현재 NAS 상태를 read-only로 구분해 확인한다.
3. 외부 게이트는 증거 수집만 진행하며, 외부 입력·소유자 승인·비밀값을 추정하거나 생성하지 않는다. 3. 외부 게이트는 증거 수집만 진행하며, 외부 입력·소유자 승인·비밀값을 추정하거나 생성하지 않는다.
4. 코드 또는 문서 변경 뒤에는 범위에 맞는 테스트와 SSOT checker를 실행한다. 4. 코드 또는 문서 변경 뒤에는 범위에 맞는 테스트와 SSOT checker를 실행한다.
2026-09-07 현재 baseline은 Python 3.11 API 전체 1090 passed/1 skipped/1 warning, gateway 전체 71 passed/1 warning이며 API 타입 체크와 Ruff도 통과했다. API의 1 skipped는 `VIGNETTE_USAGE_TEST_DATABASE_URL` 미설정 때만 건너뛰는 기존 선택형 격리 DB `test_admin_usage_postgres.py`이고 새 skip은 없다. 2026-09-09 현재 baseline은 Python 3.11 API 전체 1104 passed/1 skipped/1 warning, gateway 전체 71 passed/1 warning이며 API 타입 체크와 web build도 통과했다. API의 1 skipped는 `VIGNETTE_USAGE_TEST_DATABASE_URL` 미설정 때만 건너뛰는 기존 선택형 격리 DB `test_admin_usage_postgres.py`이고 새 skip은 없다.
최종 UI 회귀는 `session-mvp`+`uc-session-coach-voice` 58 passed/0 skipped(exit 0, 2.6분), alliance+admin 39 passed/1 skipped(exit 0, 1.7분)로 합계 97 passed/1 skipped다. skip은 `uc-review-alliance-pulse` 320px 테스트의 desktop 중복 실행 제외이며 mobile은 실행·통과했다. `session-review`의 disabled AI feedback privacy 제어 focused 1 passed(exit 0, 4.4초)도 유지한다. dashboard 10은 별도 검증이다. 최종 UI 회귀는 `session-mvp`+`uc-session-coach-voice` 58 passed/0 skipped(exit 0, 2.6분), alliance+admin 39 passed/1 skipped(exit 0, 1.7분)로 합계 97 passed/1 skipped다. skip은 `uc-review-alliance-pulse` 320px 테스트의 desktop 중복 실행 제외이며 mobile은 실행·통과했다. `session-review`의 disabled AI feedback privacy 제어 focused 1 passed(exit 0, 4.4초)도 유지한다. dashboard 10은 별도 검증이다.

View file

@ -69,6 +69,7 @@
|---|---|---| |---|---|---|
| C-002·C-003·REQ-001~007 | 완료 | 개선관리 완료본은 9 완료·2 검토를 유지한다. C-001과 REQ-008은 별도 게이트다. | | C-002·C-003·REQ-001~007 | 완료 | 개선관리 완료본은 9 완료·2 검토를 유지한다. C-001과 REQ-008은 별도 게이트다. |
| NAS A 경로 | 2026-09-01 당시 완료 | NAS `vignette-prod` 배포, migration 20/21/22, OAuth 실계정 새 사례→턴→리뷰 E2E, 첫 일일 backup sidecar 실행. | | NAS A 경로 | 2026-09-01 당시 완료 | NAS `vignette-prod` 배포, migration 20/21/22, OAuth 실계정 새 사례→턴→리뷰 E2E, 첫 일일 backup sidecar 실행. |
| NAS 2차 실배포 & Cloudflare Pages | 2026-09-08 실배포 완료 | Forgejo/GitHub master `a0311c59`/`d9bb5b36` 배포 완료. NAS API·Web 컨테이너 교체, 사전 DB 덤프(12MB) 생성, Cloudflare Pages 174개 에셋 보존 배포. 실 health/auth/web 폐루프 검증. TDD 1104 passed (0턴 세션 분리, OAS calibration bounds & lock, composer 복원) 완료. [배포 파이프라인](./ops/deployment-pipeline.md) 참조. |
| G0~G6·G8 내부 구현 | 완료 증거 보존 | G7 외부 종료와 G8 실DB/public 사람 게이트는 계속 열린다. | | G0~G6·G8 내부 구현 | 완료 증거 보존 | G7 외부 종료와 G8 실DB/public 사람 게이트는 계속 열린다. |
| B3·B3-신규 소유자 결정 | 결정 및 기존 구현 완료 | 원문은 [정리 전 백로그 원문](./archive/project-cleanup-2026-09-07/backlog-2026-06-26-before-cleanup.md), 남은 후속만 위에 둔다. | | B3·B3-신규 소유자 결정 | 결정 및 기존 구현 완료 | 원문은 [정리 전 백로그 원문](./archive/project-cleanup-2026-09-07/backlog-2026-06-26-before-cleanup.md), 남은 후속만 위에 둔다. |
| 과거 Windows Compose 패키징 gate | SUPERSEDED | 9/1 NAS docker-compose 배포로 현 production 전환 항목에서 제거했다. 새 secret 주입 과제를 만들지 않는다. | | 과거 Windows Compose 패키징 gate | SUPERSEDED | 9/1 NAS docker-compose 배포로 현 production 전환 항목에서 제거했다. 새 secret 주입 과제를 만들지 않는다. |

View file

@ -67,7 +67,7 @@ npx playwright test e2e/uc-session-conversation.spec.ts --grep '스트림 도중
## 완료 기록 경계 ## 완료 기록 경계
2026-09-01 A 경로의 NAS 배포, migration 20/21/22 적용, OAuth 실계정 회기 E2E와 당시 backup sidecar 첫 실행은 완료 이력이다. B3 및 B3-신규의 소유자 결정과 완료된 구현도 archive snapshot에 보존한다. `CLEANUP-001`은 84 regular source와 supplementary 4 files·junction 4개의 대조 뒤 `outputs/local-history/retained-sources-2026-09-07/`으로 가역 보존 이동을 마쳤고 영구 삭제는 0건이다. `RUNTIME-001`은 Windows public-runtime/watchdog scripts를 복구 경로로 보존하기로 결정했으며 이 PC의 두 Disabled Scheduled Task는 운영 서버 다운을 뜻하지 않는다. `REFACTOR-001``sessionViewModel` 분리와 `voiceCapture` 책임 유지를 수용했고, lifecycle setter bag hook은 채택하지 않았다. Space retry→pause와 empty-audio fixture를 교정했으며, `learnerFeedbackEnabled:true` 누락으로 숨던 review feedback UI는 fixture 보완 뒤 focused login→review 1 passed(exit 0)로 확인했다. 제품 feedback guard는 유지했다. `REFACTOR-002`는 repository와 persistence values로 평가 저장 경계를 분리했다. 열린 백로그에 완료 이력을 다시 적지 않는다. 2026-09-01 A 경로의 NAS 배포, migration 20/21/22 적용, OAuth 실계정 회기 E2E와 당시 backup sidecar 첫 실행은 완료 이력이다. 2026-09-08에는 Forgejo master `a0311c59`/`d9bb5b36`의 NAS Production 컨테이너 교체와 Cloudflare Pages 배포, 사전 DB 덤프(12MB) 확보 및 0턴 세션 분리·OAS calibration bounds/lock·composer 복원 등 TDD 회귀 검증(API 1104 passed)을 완료했다. B3 및 B3-신규의 소유자 결정과 완료된 구현도 archive snapshot에 보존한다. `CLEANUP-001`은 84 regular source와 supplementary 4 files·junction 4개의 대조 뒤 `outputs/local-history/retained-sources-2026-09-07/`으로 가역 보존 이동을 마쳤고 영구 삭제는 0건이다. `RUNTIME-001`은 Windows public-runtime/watchdog scripts를 복구 경로로 보존하기로 결정했으며 이 PC의 두 Disabled Scheduled Task는 운영 서버 다운을 뜻하지 않는다. `REFACTOR-001``sessionViewModel` 분리와 `voiceCapture` 책임 유지를 수용했고, lifecycle setter bag hook은 채택하지 않았다. Space retry→pause와 empty-audio fixture를 교정했으며, `learnerFeedbackEnabled:true` 누락으로 숨던 review feedback UI는 fixture 보완 뒤 focused login→review 1 passed(exit 0)로 확인했다. 제품 feedback guard는 유지했다. `REFACTOR-002`는 repository와 persistence values로 평가 저장 경계를 분리했다. 열린 백로그에 완료 이력을 다시 적지 않는다.
## 확인 명령 ## 확인 명령

View file

@ -56,8 +56,8 @@ NAS 호스트에는 git이 없으므로 git 컨테이너로 Forgejo에서 clone
## 4. 검증 게이트 (배포 전) ## 4. 검증 게이트 (배포 전)
- `apps/web`: `npm run typecheck`, `npm run build` - `apps/web`: `npm run typecheck`, `npm run build`
- `apps/api`: 관련 test suite - `apps/api`: 관련 test suite (전체 1104 passed / 1 skipped)
- SSOT checker `scripts/test_dev_dashboard_ssot.py` - SSOT checker `scripts/check-dev-dashboard-ssot.py`
- Forgejo master == 로컬 master (배포 무결성) - Forgejo master == 로컬 master (배포 무결성)
- NAS: `docker compose ps` healthy, `/api/health` ok·db/engine true - NAS: `docker compose ps` healthy, `/api/health` ok·db/engine true
@ -89,10 +89,29 @@ docker compose -f docker-compose.nas.yml --env-file private/env.nas up -d
`node ../../scripts/preserve-assets.mjs`(이전 세대 자산 보존) → `node ../../scripts/preserve-assets.mjs`(이전 세대 자산 보존) →
`npx wrangler pages deploy dist --project-name vignette --branch main`. `npx wrangler pages deploy dist --project-name vignette --branch main`.
## 5.1 2차 정식 실배포 완료 (2026-09-08, SHA `a0311c59`)
- **Forgejo / GitHub master 동기화**: `a0311c59` (파이프라인 문서 포함 `d9bb5b36`).
- **사전 백업**:
- DB dump: `/volume1/docker/vignette-prod/backups/pre-deploy-a0311c59-.dump` (12MB, custom 포맷)
- 환경변수: `private/env.nas.before-deploy-a0311c59`
- **NAS Docker 빌드 및 배포**:
- API 이미지: `vignette-nas-api:a0311c59` (`sha256:8b1ed23d1d24...`)
- Web 이미지: `vignette-nas-web:a0311c59` (`sha256:5c34139d8b56...`)
- `private/env.nas` 이미지 SHA 갱신 및 `docker compose up -d`
- 컨테이너 전건 healthy: `vignette-prod-api-1`, `vignette-prod-engine-1`, `vignette-prod-db-1`, `vignette-prod-web-1`, `vignette-prod-private-proxy-1`
- **Cloudflare Pages 배포**:
- `apps/web`: `npm run build` 성공
- `node ../../scripts/preserve-assets.mjs` 실행 (174개 이전 세대 자산 보존)
- `npx wrangler pages deploy dist --project-name vignette --branch main` 성공 (`https://vignette.chanpaca.net`, preview: `https://2df910db.vignette-b1q.pages.dev`)
- **Live 폐루프 검증**:
- `https://api-vignette.chanpaca.net/health` -> `status: ok`, `db: true`, `engine: true`, `openai: true`
- `https://api-vignette.chanpaca.net/auth/me` -> `401 Unauthorized` (fail-closed 보장)
- `https://vignette.chanpaca.net` -> `HTTP 200 OK`
## 6. 남은 구성 작업 (TODO) ## 6. 남은 구성 작업 (TODO)
- [ ] Forgejo master 기준 NAS 자동배포 후크(수동 절차는 §5로 실증 완료) - [ ] Forgejo master 기준 NAS 자동배포 후크(수동 절차는 §5, §5.1로 실증 완료)
- [x] Forgejo가 SSOT임을 문서에 반영, github은 private 미러 유지 - [x] Forgejo가 SSOT임을 문서에 반영, github은 private 미러 유지
- [ ] cloudflare tunnel 제거 또는 유지 결정 — 현재 `api-vignette`는 NAS 호스트 상주 cloudflared 터널 경유다. 대체 ingress의 보안·가용성·OAuth 경계가 검증되기 전에는 제거하지 않는다. - [ ] cloudflare tunnel 제거 또는 유지 결정 — 현재 `api-vignette`는 NAS 호스트 상주 cloudflared 터널 경유다. 대체 ingress의 보안·가용성·OAuth 경계가 검증되기 전에는 제거하지 않는다.
- [ ] 배포 시 NAS 접근 자격(SSH 키/배포 계정)을 `.env.deploy`/시크릿으로 관리 - [ ] 배포 시 NAS 접근 자격(SSH 키/배포 계정)을 `.env.deploy`/시크릿으로 관리
```