350 lines
21 KiB
Markdown
350 lines
21 KiB
Markdown
# Vignette 전체 개선 목표 · 정식 배포 핸드오프
|
||
|
||
작성 시각: 2026-08-29 21:18 KST
|
||
작업 루트: `D:\workspace\vignette`
|
||
Goal ID: `01a04217-f73b-7303-b597-401fa7f5d290`
|
||
Goal: `엑셀 파일의 모든 내용을 마친다`
|
||
|
||
## 0. 2026-08-30 재개 후 현행 상태
|
||
|
||
이 절이 아래 2026-08-29 종료 스냅샷보다 우선한다. 현재 이어받기 Goal ID는
|
||
`01a04dd0-93ef-7d02-a9cb-40682fd0988a`다.
|
||
|
||
- `preserved_total_size_bytes=52,973`과 decode 3/90, 현재 DB 참조 decode 2/6을 initializer→manifest v3→
|
||
bootstrap/cutover/task-recovery/final receipt→API health까지 결속했다.
|
||
- manifest 이후 생성된 UUID형 아바타도 URL 기록·현재 DB 참조·GET/HEAD에서 3MB 제한, Pillow full decode,
|
||
확장자-format 일치를 다시 검사한다. 검증한 동일 bytes를 응답해 검사 뒤 재오픈 경쟁을 없앴고, 사후 손상은
|
||
current invalid/health fallback과 public 404로 닫는다. 원본 bytes와 DB URL은 삭제하지 않았다.
|
||
- API 전체 `1074 passed / 1 skipped`, gateway `68 passed`, runtime/bootstrap 통합 `154 tests OK`, web typecheck/build,
|
||
이미지+사람 게이트 route E2E가 통과했다. SSOT checker와 scoped diff check도 통과했다.
|
||
- Codex 내장 브라우저의 격리 local stateful fixture에서 8.5초 뒤 overlay 0·heading 정상, content
|
||
`keep_quarantine` effect 0, 증거 없는 release 승인 disabled→`reject` effect 0, 증거 4종 promote 승인
|
||
lifecycle effect 정확히 1을 확인했다. 이는 실DB/public proof를 대신하지 않는다.
|
||
- clean 통합 브랜치는 `YunChan/goal-production-20260830`이며 UI 공통화 두 커밋 위에 runtime·usage·G8·auth·
|
||
관리자 UI·온보딩 계정 전환을 좁은 커밋으로 결합했다. push·Pages 배포·public runtime/task 변경은 아직 없다.
|
||
- 풀스택 `layout-visual-gate` 15/15와 `session-layout` 8/8은 Docker Desktop이 꺼져 있고 활성 public watchdog이
|
||
daemon 기동 즉시 기존 runtime 복구를 시도할 수 있어 승인 대기다. 승인 시 watchdog을 일시 중지·비활성화하고
|
||
고유 DB/container/volume과 56432/58000/55173만 사용한 뒤 exact cleanup, Docker 종료, watchdog 원상복구를 수행한다.
|
||
- 최종 외부 게이트는 여전히 C001 적격 외부 임상 검수와 REQ-008 실제 Windows 재부팅 smoke다. 둘 다 추정 증거로
|
||
닫지 않는다.
|
||
|
||
## 1. 이전 세션 종료 결정과 당시 결론
|
||
|
||
사용자가 세션 장기화를 이유로 상세 핸드오프 후 익일 재개를 지시했다. 21:15 KST부터 모든 에이전트의 새 편집을 중단했고, 로컬 stage·commit·push·Cloudflare Pages 배포·라이브 DB 변경·API/tunnel 재시작·예약 작업 변경·PC 재부팅은 수행하지 않았다.
|
||
|
||
당시 소스는 **배포 가능 GREEN이 아니었다**. 특히 종료 직전 실제 이미지 디코딩 감사를 추가로 수행한 결과, 연결된 운영 DB가 참조하는 아바타 8개 중 6개가 깨진 동일 PNG payload라는 사실을 확인했다. 파일 존재와 해시만 보존하면 사용자가 신고한 깨진 이미지가 그대로 남았다. 이 결함은 위 2026-08-30 후보에서 public 404/fallback으로 닫았지만 아직 정식 배포 전이다.
|
||
|
||
Goal은 완료 처리하지 않았다. 기술 구현·정식 배포·실제 재부팅 증명과 별개로 C001 적격 외부 임상 검수도 여전히 인간 게이트다.
|
||
|
||
## 2. 완료된 엑셀 산출물
|
||
|
||
- 산출물: `D:\workspace\vignette\outputs\01a04217-f73b-7303-b597-401fa7f5d290\Vignette_개선관리_완료.xlsx`
|
||
- SHA256: `c832547f30ae0664e54b302c8e9f62cc157f31022ad158d17803d8cac988d8bd`
|
||
- 크기: 2,751,365 bytes
|
||
- 검증: 6 sheets, 11 requirements, 38 formulas, formula error 0, inspection files 18
|
||
- 상태 집계: 완료 9, 검토 2, 보류 0
|
||
- 남은 두 검토 항목:
|
||
- C001: 적격 외부 임상 검수 입력과 서명 증빙
|
||
- REQ-008: 실제 PC 재부팅 뒤 예약 작업 기반 자동복구와 공개 smoke
|
||
- C001 셀 상태: `G23=pending-valid`, `G24=PACKAGE_MATCH`, `B24=pending_external_review`, `J3=검토`; 외부 검수 입력 46칸은 의도적으로 비워 두었다.
|
||
- 임상 검수 내용을 추정하거나 가짜로 작성하면 안 된다.
|
||
|
||
## 3. UI 작업 상태
|
||
|
||
깨끗한 UI 후보 워크트리는 아래와 같다.
|
||
|
||
- 경로: `D:\workspace\vignette-ui-image-release-20260829`
|
||
- 브랜치: `YunChan/ui-image-resilience-release-20260829`
|
||
- HEAD: `a73b9efff77e3c575e32976bbe4f1ed404e103f0`
|
||
- 관련 커밋:
|
||
- `35a62fda` 탭 구조와 이미지 복구를 공통화
|
||
- `a73b9eff` 분석 탭과 축어록 계층을 정돈
|
||
- 워크트리 상태: clean
|
||
- 로컬 미리보기: `http://127.0.0.1:5188`
|
||
|
||
반영된 브라우저 코멘트:
|
||
|
||
- 학습 대시보드의 불필요한 안쪽 컨테이너 스타일 정리
|
||
- 교수자 요약 카드 상단 간격 분리
|
||
- 관리자 사용자 탭의 의미 없는 외곽 컨테이너 제거 및 공통 탭 컴포넌트화
|
||
- Topbar 프로필 이미지 실패 시 깨진 이미지 아이콘 대신 안전한 fallback 표시
|
||
- 학습자 상세 분석의 4개 탭이 한 줄을 유지하도록 수정
|
||
- 회기 축어록 내담자 발화의 불필요한 테두리 제거
|
||
- Google 로그인 단일 진입 UX 정리
|
||
|
||
이 UI는 로컬 내장 브라우저에서 시각 확인했지만 production에는 배포하지 않았다. 당시 내장 브라우저에는 로컬 분석/축어록 탭과 production 관리자 탭이 열려 있었다. 익일에는 탭 존재를 가정하지 말고 새로 열어 확인한다.
|
||
|
||
## 4. 운영 데이터와 업로드 보존 감사
|
||
|
||
### 4.1 정확한 소스 경계
|
||
|
||
아래 세 root의 `profile-avatars`만 source allowlist로 사용했다.
|
||
|
||
1. `D:\workspace\vignette\apps\api\uploads`
|
||
2. `D:\workspace\vignette-public-runtime-bf5f7352\apps\api\uploads`
|
||
3. `D:\workspace\vignette-public-runtime-dba9b75a3887\apps\api\uploads`
|
||
|
||
결과:
|
||
|
||
- union object count: 93
|
||
- union inventory SHA256: `9d703126f78d4fc8330408835d76a7d680276240dc578d6fc9ca420c2f25e6aa`
|
||
- union total bytes: 52,973
|
||
- maximum object bytes: 28,208
|
||
- same-name content conflict: 0
|
||
- invalid/nested/reparse entry: 0
|
||
- strict server-generated UUID-token filename shape: 93/93
|
||
- DB references found in union: 8/8
|
||
|
||
연결 DB의 개인정보 없는 결속값:
|
||
|
||
- database target SHA256: `81fe4a2844b7340f21396931fa18580e24358f857a08cc60540ddf8a4f8789b5`
|
||
- reference count: 8
|
||
- unique referenced objects: 8
|
||
- reference-set SHA256: `70926cf36ceb2375dd6c471bc59a38138460d8e4895ad1f2bddbcf1a49210d2b`
|
||
- active private multimodal audio: 0
|
||
|
||
### 4.2 종료 직전 발견한 손상 이미지
|
||
|
||
Pillow 12.2.0의 실제 decode/verify와 확장자-format 일치를 파일명·경로·사용자 ID·이메일·URL을 출력하지 않고 검사했다.
|
||
|
||
- 전체 93개: 정상 decode 3, 실패 90
|
||
- 정상 3개: JPEG 2개, PNG 1개; 크기 225×225, 512×512, 1×1
|
||
- 운영 DB 참조 8개: 정상 2, 실패 6, missing 0
|
||
- 정상 참조 2개: JPEG, 225×225 및 512×512
|
||
- 실패 참조 6개: 모두 70 bytes, PNG signature는 있으나 full decode 실패
|
||
- 실패 6개는 동일한 content 한 종류다.
|
||
|
||
근거 파일: `docs/ops/evidence/avatar-decode-audit-2026-08-29.json`
|
||
|
||
이 결과의 의미:
|
||
|
||
- “93개를 덮어쓰기 없이 복사했다”만으로는 깨진 이미지 문제가 해결되지 않는다.
|
||
- 6개 손상 payload와 해당 DB reference를 승인 없이 삭제·초기화하면 안 된다.
|
||
- 원본을 찾을 수 있으면 복구하고, 찾을 수 없으면 손상 bytes는 private forensic 보존하되 public static 응답은 404/fallback으로 보내는 정책이 권장된다.
|
||
- 현재 UI 후보의 `ResilientImage`가 시각적 fallback은 제공하지만, backend가 손상 파일을 정상 이미지처럼 공개하는 문제와 데이터 복구 정책은 별도로 닫아야 한다.
|
||
- 익일 첫 결정 게이트는 다음 둘 중 하나다.
|
||
1. 권장: 손상 bytes와 DB reference를 보존하고, manifest에 decode 상태를 결속해 손상 객체는 public serve하지 않으며 UI fallback을 사용한다. 이후 원본 복구 또는 소유자 승인 기반 정리를 별도 수행한다.
|
||
2. 엄격: 6개 원본을 복구할 때까지 API cutover 자체를 fail-closed로 막는다.
|
||
|
||
## 5. 업로드·DB·재부팅 복구 코드 상태
|
||
|
||
2026-08-29 dirty master에서 시작한 다음 안전 계약은 현재 clean 통합 브랜치에 좁은 커밋으로 결합돼 있다.
|
||
|
||
- exact 3-root union + caller-pinned count/inventory digest
|
||
- source copy 전후 재스캔과 create-only copy
|
||
- DB reference 8/8 보존 확인
|
||
- manifest v3의 privacy-safe path/content hash, total bytes, decode 상태와 DB target binding
|
||
- 새 API가 자기 pool의 repeatable-read snapshot으로 DB target과 현재 avatar refs를 DDL 전에 검증
|
||
- 모든 신규 physical DB connection이 target digest를 재검증
|
||
- production Uvicorn `--workers 1` 고정
|
||
- upload/PATCH/onboarding write lease와 freeze drain
|
||
- unrelated profile PATCH가 stale avatar URL을 되살리지 못하도록 수정
|
||
- 신규 업로드는 UUID(user id)+random token 이름, create-only hard-link publish
|
||
- static 공개 범위는 decode-valid manifest-preserved path 또는 full decode를 재통과한 strict runtime-generated filename으로 제한
|
||
- preserved bytes immutable memory cache와 신규 업로드 single-read response로 per-request 전체 hash DoS와 disk reopen TOCTOU 제거
|
||
- boot/watchdog task를 새 정의로 disabled 설치 → exact action 계약 확인 → 둘을 함께 enable
|
||
- 두 번째 task 설치/enable 실패 시 두 task 모두 disabled로 보상
|
||
- exact root task path `\` 결속
|
||
|
||
재개 후 위 미완료 연결은 해소했다. initializer manifest/result와 bootstrap의 cutover/task-recovery/final passed receipt가
|
||
모두 `preserved_total_size_bytes=52,973`과 decode proof를 교차 검증한다. 남은 것은 승인된 격리 풀스택 E2E와 정식
|
||
배포·public browser proof이지 manifest 생산자/소비자 계약 불일치가 아니다.
|
||
|
||
## 6. 마지막 검증 결과
|
||
|
||
2026-08-30 재개 후 보고:
|
||
|
||
- 전체 API: `1074 passed / 1 skipped`
|
||
- gateway: `68 passed`
|
||
- runtime/bootstrap 결합: `154 tests OK`
|
||
- API runtime focused: `31 passed`
|
||
- web typecheck/build: PASS
|
||
- 이미지 복구+사람 게이트 focused browser E2E: PASS
|
||
- Codex 내장 브라우저 local stateful 사람 게이트: overlay 0, 보류/반려 effect 0, 승인 effect 1
|
||
- SSOT checker와 scoped `git diff --check`: PASS
|
||
|
||
주의:
|
||
|
||
- full API·web build/typecheck·route/internal-browser proof는 현재 후보 기준이다.
|
||
- 실제 Postgres를 쓰는 `layout-visual-gate` 15/15와 `session-layout` 8/8, production browser proof는 아직 없다.
|
||
- Python 3.12/3.14의 `tempfile.TemporaryDirectory`가 현재 sandbox ACL과 충돌해 생성 직후 접근 거부를 냈다. 동일 테스트는 Python 3.11에서 정상 통과했다. 익일 테스트는 `py -3.11` 또는 `C:\Users\encep\AppData\Local\Programs\Python\Python311\python.exe`를 사용한다.
|
||
- `D:\workspace\vignette\tmp` 아래 접근 거부 임시 디렉터리들은 테스트 환경 잔재다. 광범위 재귀 삭제하지 말고, 필요 시 exact path와 ACL을 확인한 뒤 별도로 정리한다.
|
||
|
||
## 7. 이전 세션 Git·워크트리 기준선
|
||
|
||
2026-08-29 21:15 KST 기준:
|
||
|
||
- shared checkout: `D:\workspace\vignette`
|
||
- branch: `master`
|
||
- HEAD: `ac9b7026881139780938f4c4f2b89a235b0a0c08`
|
||
- HEAD tree: `b07cb4dd6b9b33b650b59b24fc1bc4b8bf2b48f8`
|
||
- `origin/master`보다 20 commits ahead
|
||
- shared checkout은 사용자 작업과 이번 작업이 섞인 큰 dirty tree다. `git status --untracked-files=all`은 접근 거부 tmp를 포함해 547 entries를 셌다.
|
||
- `git add .`, `git commit -a`, whole-tree copy는 금지한다.
|
||
|
||
관련 worktree:
|
||
|
||
- UI clean candidate: `D:\workspace\vignette-ui-image-release-20260829`, `a73b9eff`
|
||
- old runtime-storage candidate: `D:\workspace\vignette-runtime-storage-release-20260829`, `dba9b75a`, dirty; 현행 source of truth로 사용하지 않는다.
|
||
- current public runtime: `D:\workspace\vignette-public-runtime-dba9b75a3887`, detached `dba9b75a`
|
||
- current scheduled tasks `VignettePublicRuntime`, `VignettePublicRuntimeWatchdog`는 마지막 확인 시 enabled/Ready이며 여전히 old `dba9b75a` runtime을 가리킨다.
|
||
- current Pages production은 deployment `0c60261e`, source `5bf89ff`였다. UI 후보는 아직 미배포다.
|
||
|
||
## 8. 현재 변경 파일 경계
|
||
|
||
API 소유 범위:
|
||
|
||
- `apps/api/app/config.py`
|
||
- `apps/api/app/db.py`
|
||
- `apps/api/app/main.py`
|
||
- `apps/api/app/routes/users.py`
|
||
- `apps/api/app/upload_runtime.py`
|
||
- `apps/api/app/upload_storage.py`
|
||
- `apps/api/app/test_upload_storage_contract.py`
|
||
- `apps/api/app/test_engine_health_contract.py`
|
||
- `scripts/validate-public-runtime-upload-manifest.py`
|
||
|
||
runtime/bootstrap 핵심 범위:
|
||
|
||
- `scripts/initialize-public-runtime-upload-root.py`
|
||
- `scripts/initialize-public-runtime-upload-root.ps1`
|
||
- `scripts/bootstrap-legacy-public-runtime-upload-root.ps1`
|
||
- `scripts/validate-public-runtime-offline-quiescence.py`
|
||
- `scripts/probe-public-runtime-database-identity.py`
|
||
- `scripts/probe-public-runtime-upload-root.py`
|
||
- `scripts/public_runtime_database_identity.py`
|
||
- `scripts/public-runtime-upload-root.ps1`
|
||
- `scripts/public-runtime-task-maintenance.ps1`
|
||
- `scripts/public-runtime-task-definition-cutover.ps1`
|
||
- `scripts/start-public-runtime.ps1`
|
||
- `scripts/boot-public-runtime.ps1`
|
||
- `scripts/watch-public-runtime.ps1`
|
||
- `scripts/install-public-runtime-task.ps1`
|
||
- `scripts/register-boot-task.ps1`
|
||
- 관련 focused tests 10개
|
||
- `docs/ops/public-runtime-watchdog.md`
|
||
- 관련 architecture/local-development/testing 가이드와 `docs/dev_dashboard.html`
|
||
|
||
마지막 직접 수정된 task tests:
|
||
|
||
- `scripts/test_public_runtime_upload_root.py`
|
||
- `scripts/test_public_runtime_task_definition_cutover.py`
|
||
|
||
파일 전체를 자동 stage하지 말고 각 diff에 선행 사용자 변경이 섞였는지 다시 확인한다.
|
||
|
||
## 9. 익일 재개 순서
|
||
|
||
### 9.1 현재 truth 재확인
|
||
|
||
1. Windows/PowerShell 판, 현재 경로, Git HEAD/worktree/status를 다시 확인한다.
|
||
2. 이 문서와 `docs/dev_dashboard.html`, `docs/ops/backlog-2026-06-26.md`, `docs/ops/public-runtime-watchdog.md`를 읽는다.
|
||
3. production/API/task state는 문서만 믿지 말고 read-only로 다시 확인한다.
|
||
4. 세 source root union을 다시 계산해 `93 / 9d7031... / 52,973 bytes`, DB `8 refs / 70926c... / private audio 0`과 일치하는지 확인한다.
|
||
5. 아바타 decode audit도 재실행해 `DB refs valid 2 / invalid 6 / missing 0`이 유지되는지 확인한다.
|
||
|
||
### 9.2 코드 blocker 해소
|
||
|
||
1. `PreservedInventory.total_size_bytes`를 initializer privacy-safe result, manifest, bootstrap cutover receipt, task-recovery receipt, final passed receipt까지 끝까지 결속한다.
|
||
2. exact expected total `52,973`을 CLI 인자와 tests에서 pin한다. count 93만으로 same-count substitution을 허용하지 않는다.
|
||
3. 6개 손상 DB-ref에 대한 정책을 소유자와 결정한다. 어떤 경우에도 원본 bytes/DB reference를 승인 없이 삭제하지 않는다.
|
||
4. 권장 정책을 택하면 decode-valid preserved object만 immutable public cache로 제공하고, invalid object는 private forensic 보존 + public 404/fallback 처리하며 privacy-safe 손상 count를 health/receipt에 기록한다.
|
||
5. 새 stable upload root가 비어 있거나 exact expected set임을 cutover 전후에 증명한다. UUID형 pre-existing extra를 무조건 허용하지 않는다.
|
||
6. 문서·SSOT·얇은 backlog를 실제 계약과 일치시킨다.
|
||
|
||
### 9.3 통합 테스트
|
||
|
||
Python 3.11로 최소 아래를 한 번에 다시 실행한다.
|
||
|
||
```powershell
|
||
py -3.11 -B -X utf8 -m unittest `
|
||
apps.api.app.test_upload_storage_contract `
|
||
apps.api.app.test_engine_health_contract `
|
||
scripts.test_initialize_public_runtime_upload_root `
|
||
scripts.test_legacy_public_runtime_upload_bootstrap `
|
||
scripts.test_public_runtime_environment_handoff `
|
||
scripts.test_public_runtime_listener_pid_probe `
|
||
scripts.test_public_runtime_task_definition_cutover `
|
||
scripts.test_public_runtime_task_maintenance `
|
||
scripts.test_public_runtime_upload_release_safety `
|
||
scripts.test_public_runtime_upload_root `
|
||
scripts.test_public_runtime_watchdog_provenance `
|
||
scripts.test_start_public_runtime_contract -v
|
||
```
|
||
|
||
추가 검증:
|
||
|
||
- Windows PowerShell 5.1 AST parse for all changed `.ps1`
|
||
- Python compile for all new/changed `.py`
|
||
- scoped `git diff --check`
|
||
- API의 전체 관련 test suite
|
||
- 깨끗한 통합 후보에서 `apps/web`의 `npm run typecheck`, `npm run build`
|
||
- `e2e/layout-visual-gate.spec.ts` 15/15
|
||
- `e2e/session-layout.spec.ts` 8/8
|
||
- `e2e/image-resilience.spec.ts`
|
||
- `e2e/tabs-behavior.spec.ts`
|
||
- Google auth/onboarding/admin/profile avatar 실제 브라우저 E2E
|
||
|
||
### 9.4 좁은 커밋과 clean candidate
|
||
|
||
1. shared dirty master에서 이번 runtime 파일만 line-by-line 검토해 좁게 stage한다.
|
||
2. author는 `Yun Chan <yunchan@twentyoz.kr>`, 한글의 짧은 커밋 메시지를 사용한다.
|
||
3. `git add .` 금지.
|
||
4. master `ac9b7026` 이후 runtime commit을 만들고, 새 clean release worktree/branch를 만든다.
|
||
5. UI 커밋 `35a62fda`, `a73b9eff`를 순서대로 cherry-pick한다.
|
||
6. clean candidate SHA/tree, clean status, 테스트 결과를 고정한다.
|
||
|
||
### 9.5 사용자 승인 후에만 정식 전환
|
||
|
||
후보가 GREEN일 때 사용자에게 아래 범위를 정확히 제시하고 승인받는다.
|
||
|
||
> 후보 커밋 `<sha>`를 원격에 push하고 Cloudflare Pages production과 이 PC의 public API/tunnel·두 예약 작업을 새 detached runtime으로 전환해도 돼? 기존 API/tunnel은 약 1분 재시작되고, 검증된 upload inventory는 덮어쓰기 없이 새 영구 root에 보존돼.
|
||
|
||
승인 전 금지:
|
||
|
||
- `git push`
|
||
- Cloudflare Pages production deploy
|
||
- public API/cloudflared stop/restart
|
||
- scheduled task reinstall/retarget/enable 변경
|
||
- DB avatar URL 수정
|
||
- stable upload root 생성/복사
|
||
|
||
승인 후에도 Pages 자산 보존은 stale default script를 그대로 쓰지 않는다. 최소 다음 실제 production 세대의 immutable asset graph를 explicit origins로 보존한다.
|
||
|
||
- `https://0c60261e.vignette-b1q.pages.dev`
|
||
- `https://ef48c0ae.vignette-b1q.pages.dev`
|
||
- `https://1f1ddf18.vignette-b1q.pages.dev`
|
||
|
||
배포 뒤에는 HTTP 200만 보지 않는다. custom domain의 신규 index/asset hash·MIME·신규 UI marker·구버전 marker 부재, API health manifest/DB/freeze proof, Google 로그인, super account role/onboarding, 데이터/아바타 fallback을 Codex 내장 브라우저로 보여준다.
|
||
|
||
### 9.6 실제 재부팅 게이트
|
||
|
||
production 전환과 browser smoke가 끝난 뒤에만 아래 문구로 명시 승인받는다.
|
||
|
||
> 지금 이 PC를 재부팅해도 돼. 저장하지 않은 작업은 없고, encep 계정으로 로그인한 뒤 REQ-008 자동복구 smoke까지 계속 진행해.
|
||
|
||
재부팅 뒤에는 먼저 task를 수동 실행하지 않는다. 로그인 후 자동으로 API/tunnel/tasks가 복구되는지 관찰하고, 공개 health·Google 로그인·데이터·이미지·새 runtime SHA/task action을 증명한다.
|
||
|
||
## 10. C001 외부 임상 검수 게이트
|
||
|
||
C001은 코드·UI·운영 배포로 대신할 수 없다. 적격 검수자의 실제 입력, 자격/역할, 검토 시각, 대상 버전/패키지 결속, 승인 또는 수정 요청을 받아 workbook의 지정 셀에 반영해야 한다. 검수자가 없으면 최종 Goal은 `기술 완료 / 외부 검수 대기`로 정확히 남긴다.
|
||
|
||
## 11. 절대 하지 말 것
|
||
|
||
- 손상 아바타 6개의 DB URL이나 파일을 승인 없이 삭제·초기화하지 않는다.
|
||
- 90개 decode-invalid legacy payload를 정상 이미지로 간주하지 않는다.
|
||
- 한 개 source root만 복사해 8개 DB ref를 복구했다고 주장하지 않는다.
|
||
- old runtime root 2개만 보고 데이터가 온전하다고 판단하지 않는다.
|
||
- general `/uploads` directory를 static mount하지 않는다.
|
||
- production Uvicorn worker를 2개 이상 띄우지 않는다.
|
||
- reset receipt 없이 initial nonzero refs → current zero를 정상으로 받아들이지 않는다.
|
||
- 예약 작업을 새 정의로 교체한 뒤 검증 전에 enable하지 않는다.
|
||
- 실제 재부팅 전 task를 수동 실행해 자동복구 증거를 오염시키지 않는다.
|
||
- 외부 임상 검수 내용을 만들어내지 않는다.
|
||
- dirty tree에서 전체 stage/commit/copy하지 않는다.
|
||
- Python 3.12/3.14 tempfile ACL 오류를 제품 테스트 실패와 혼동해 같은 방식으로 반복하지 않는다.
|
||
|
||
## 12. 재개 프롬프트
|
||
|
||
다음 세션에서 아래처럼 시작하면 된다.
|
||
|
||
> `docs/ops/handoff-goal-production-2026-08-29.md`를 먼저 읽고, live/Git/DB/avatar decode truth를 read-only로 재검증해. 손상 DB-ref 6개의 보존·fallback 정책과 `preserved_total_size_bytes=52973` end-to-end 결속부터 마무리하고, 전체 통합 GREEN 전에는 stage/push/deploy/runtime/task/DB를 건드리지 마. clean candidate가 준비되면 SHA와 승인 범위를 먼저 보여줘.
|