Skip to content

E2E PR 필수 게이트와 복구 여정 구현 — v0.17.2

2026-09-08 갱신 · PR 필수 게이트·핵심 플로우 보강 main 머지·최종 CI·staging 완료

사용자는 E2E 마스터플랜을 PR 단위로 적용하고 v0.17.2로 배포할 수 있게 구현하도록 요청했다. 기존 CI 최적화의 v0.17.1은 별도 릴리스이며, 이 작업은 그 다음 후보다. 구현 PR #1361과 핵심 플로우 보강 #1386의 main 머지·최종 원격 CI·staging 확인을 완료했다. 결과와 별도 검증 범위는 §7–10에 구분하며 릴리스 후보는 #1383 완료 기록에서 연결한다.

1. 실제 산출물과 CASE 수

기존 CASE-001–039를 유지하고 신규 18개 패키지를 구현했다. 통합 중 main에 S04의 옛 탭/새 탭 후속 행 여정 CASE-040이 먼저 병합되어(PR #1369, f8334135), 개발 브랜치의 IndexedDB enqueue 실패 CASE-040을 CASE-058로 옮겼다. 신규 18개는 CASE-041–058이며, 현재 합계는 58개다. 이 중 PR 자동 로컬 집합은 57개(CASE-001–058 중 CASE-003 제외), 사전 준비된 provider QA 계정을 요구하는 CASE-003은 별도 조건부 집합이다. viewport 14개, Node DB 여정, 독립 browser 저장소 검사, pgTAP는 이 58개에 더하지 않는다.

최초 계획의 기존 39개 + 신규 18개 = 약 57개 예상은 당시 기록으로 보존한다. 실제 증가분 1개는 S04의 별도 사용자 여정이며, 번호 이동으로 기존 IndexedDB 장애 검증을 삭제하거나 합치지 않았다. 아래 통합 전 run의 56개 결과도 당시 집합의 증거로 유지하며, 현재 57개 자동 집합의 성공으로 간주하지 않는다.

개수는 구현된 번호 패키지 수이며 전체 통과 수가 아니다. 실제 사용자 동작·화면·기기 저장소·인증 RPC·DB·재진입·정리를 각각 관찰한다. 테스트 파일을 만들거나 RPC 성공만 확인한 것을 사용자 여정 완주로 세지 않는다.

산출물위치/역할
신규 번호 패키지 18개error-cases/CASE-041-*CASE-058-*: spec, manifest, README, USER-JOURNEY
main에서 추가된 S04 패키지 1개error-cases/CASE-040-legacy-tab-in-flight-new-tab-successor: 옛 전송 중 새 편집의 후속 행 보존
사전 필수 집합e2e/required-coverage.json: browser 57개·viewport 14개·별도 출시 증거
완주/집계requiredEvidenceReporter.mjs, check-e2e-evidence.mjs: 실제 수집/완료·동일 SHA/run·첫 시도·cleanup 확인
좁은 실패 계약expectedRecovery, expectedFaults, requiredObservations: HTTP 시도 구간·정확한 오류 표면/횟수·telemetry 영수증
기존 시스템 정비SYS-01–19 구현 상태: 수리/부분 완료/유지/미구현 구분
SQL/단위 회귀이름 편집 권한, service-role 인입, offline receipt 대기, pending 상세 접근의 실제 결함 회귀

2. 새 여정이 맡는 경계

CASE실제 검증 경계범위와 상태
040 (S04 통합)실제 v0.17.1 태그 번들 탭 전송 중 새 번들 탭 편집→원문/후속 행 보존→옛 ACK 뒤 새 편집 반영main의 기존 UI·owner·요청 원문·10초 lease/응답 제한·실제 충돌/개정번호·오류 단언 유지. 로컬 장애 주입·7개 완료 신호/실제 계정 삭제 후 검증으로 연결; S04 통합의 039/040/046/058 batch 4/4 첫 시도(2.4분)
041생성·수정·삭제 서버 commit 후 ACK만 유실→동일 요청 재전송개별 green. 실제 원본·revision·receipt가 중복 없이 수렴
042실제 sending 원문→페이지 종료→10초 TTL→같은 저장소의 새 페이지개별 green. 종료 이후 서버 도착 여부는 불확정이며 재전송의 최종 단일 결과를 검증
043실제 서명 만료 JWT의 서버 401→held→동일 owner 새 인증개별 green. 공급자 로그인 화면 자체의 증거와 구분
044A held→B 실제 저장→A 복귀, UI/IDB/DB 소유권 분리개별 green. 종료 전에 401 요청이 끝난 상태로 시험 경계를 고정
045수정/수정·수정/삭제 실제 개정 충돌과 늦은 ACK현재 상세 80→70kg red 수리 후 reload 없이 현재 UI/삭제 수렴·7개 완료 신호 첫 시도 green(29.9초). 별도 empty flush 취소 경합도 세션별 조회 토큰으로 수리하고 행동 검사 4/4 통과. 최종 PR 전체 첫 시도 통과(§8)
046영구 거부 blocked→일지 안내→실제 새 기록 복구 버튼개별 green. 새 mutation/source ref 및 원문 값 보존
047늦은 상세 응답·조회 503→현재 선택 보호·재진입개별 green. 다른 read-model/모든 지연 조합의 보장은 아님
048실제 HTTPS/SW offline queued 재진입·전송 중 worker 교체offline 완료 안내·pending localStorage 검사 보강 후 개별 첫 시도 green(31.0초). 최종 PR 전체 첫 시도 통과(§8)
049provider 취소 callback·실제 PKCE 거부·재시도실제 callback/PKCE 경계 보강 후 개별 green(26.9초). 공급자 웹 로그인 자체의 증거와 구분
050프로필 이름·아이디·사진 편집 실패/재시도·재진입개별 green. 이름 UPDATE 권한 결함 수리; 최종 PR 전체 첫 시도 통과(§8)
051계정 연결 실패 복귀·기존 owner/신원 보존개별 green. 실제 provider 연결·해제 전체를 증명하지 않음
052좋아요 rollback·댓글 초안 유지/재시도·팔로우개별 green. 최종 PR 전체 첫 시도 통과(§8)
053두 사용자의 그룹 생성·초대 수락 UI·멤버십 회수개별 green. 최종 PR 전체 첫 시도 통과(§8)
054한글 조합 검색·종목 보관 실패/재시도·복원개별 green. 과거 세트 값/ID 보존; 최종 PR 전체 첫 시도 통과(§8)
055실제 Wodup UI→Storage→Edge/job→원본·중복 파일 원자 거부개별 green. service-role 인입 결함 수리; 최종 PR 전체 첫 시도 통과(§8)
056Motra 파일 선택 UI→실제 인입 RPC·겹친 파일 전량 거부/수정 재시도개별 green. 최종 PR 전체 첫 시도 통과(§8)
057내보내기 실패 시 다운로드 0개→실제 JSON 재시도개별 green. owner/ID/값 대조; 최종 PR 전체 첫 시도 통과(§8)
058 (개발 브랜치의 구 040)실제 IDB 적재 트랜잭션 중단→실패 안내·초안 보존→사용자 재시도번호만 이동, 기존 모든 단언 유지. S04 통합의 039/040/046/058 batch 4/4 첫 시도(2.4분). 임의 모든 quota/OS 조건의 증거는 아님

NEW-03의 두 상태는 042(sending 종료)와 048(offline queued 종료)으로 분담한다. 같은 queued 여정을 두 패키지에 복제하지 않는다. LG426은 기존 036에 실제 browser 단계를 추가했고 기존 정상 저장·구 RPC 8개 거부·원본 불변·리로드를 유지했다.

3. PR마다 실행하는 정책

영향 선택기의 누락 가능성이 검증되기 전까지 실행 코드 또는 미분류 경로가 있는 PR은 자동 집합 전체를 실행한다. 앱 source/API, DB, fixture, 테스트, 실행 도구, 의존성, 문서 사이트 실행 설정도 포함한다. 명시된 비실행 Markdown/문서 이미지/기여 템플릿만 verify-only 예외이며 full-ci로 전체 실행을 강제할 수 있다.

verify는 scope·정적 검사·단위 샤드·문서 빌드와 함께 DB·browser·viewport·evidence 결과를 기다린다. full인 경우 필요한 job의 실패·취소·skip은 성공이 아니다. 4개 browser 샤드는 각각 독립 Supabase를 사용하고 샤드 안은 workers=1을 유지한다. 실제 수집 집합을 사전 inventory와 대조하며, 이전 SHA의 artifact·누락/중복 샤드·미완주·cleanup 누락·재시도 통과를 승인하지 않는다.

PR 최종 결과와 별개로 실제 branch protection 설정, 후보 태그, staging 배포 SHA는 최종 릴리스 표에서 확인한다. 정기 실행·실기기·성능 레인을 모두 구현했다는 의미도 아니다.

전체 E2E는 PR의 필수 게이트에서 한 번 실행한다. 보호된 main의 머지 push는 정적·단위·문서 확인만 다시 수행하고, 별도 staging 배포가 실제 배포 후 smoke를 맡는다. 같은 변경으로 main에서 전체 DB/browser/viewport 레인을 다시 띄우던 중복을 제거했다. workflow_dispatch의 전체 실행과 full-ci 강제 검사는 유지하며, 미분류 PR 경로는 계속 full이다. 관리자 bypass/direct push는 이 정상 PR 경로의 검증 증거가 아니다.

4. 운영 명령과 기대 산출물

일반 로컬 재현은 저장소의 고정 Node/Supabase/Playwright 도구를 설치한 뒤 전용 sandbox로 실행한다. 필수 로컬 모드는 E2E_REQUIRED_PROFILE=local이며 local URL·anon key·service role 없이 credential 부분집합으로 조용히 대체할 수 없다. JWT 만료 사례의 로컬 signer는 local Supabase status에서만 전달하고 로그에 출력하지 않는다.

sh
npm run ci:local -- --plan
npm run ci:local -- --full --sandbox <dedicated-sandbox>
npm run ci:local -- --only browser,viewport --sandbox <dedicated-sandbox>
npm run check:error-cases

--only는 개발 중 집중 재현이며 full PR 성공을 대체하지 않는다. 이미 구성한 전용 환경에서는 npm run test:e2e-browser -- --grep 'CASE-045' --workers=1 --retries=0 --max-failures=1로 한 실패를 재현할 수 있다. 공유 DB를 두 test 프로세스가 동시에 사용하지 않는다. 개발 중 사용하는 --reporter=line 전용 출력은 최종 required reporter/evidence 집계를 대신하지 않는다.

결과기대 위치/판정
browser 실행test-results/error-cases.json, playwright-report/, 실패 trace/스크린샷
사례 완주journey-completion.json attachment: 7개 신호와 정리 후 조회
required evidencetest-results/browser-*-of-*.e2e-evidence.json, viewport-*-of-*.e2e-evidence.json
원격 artifactlocal-error-case-browser-evidence-shard-*, viewport-matrix-screenshots
최종 집계node scripts/check-e2e-evidence.mjs <artifact-directory> <tested-40-char-SHA>; CI는 같은 run/SHA를 환경으로 전달
DB 변경빈 전용 DB replay→schema:snapshot --check→전체 pgTAP, sql:extract/sql:check

이전 개별 green, 다른 코드의 실행 시간, line reporter만 있는 개발 로그를 최종 후보의 전체 성공으로 합산하지 않는다.

5. 시험이 드러낸 실제 결함과 수리

결함/재현변경과 확인
offline 완료 저장은 IDB에 남았지만 화면이 계속 저장 중offline flush가 deferred를 통지하고 waiter보다 먼저 도착한 비종결 결과를 1회 소비. 다음 await는 새 결과를 기다려 무한 반복을 피함. 새 unit 2개 및 기존 outbox 단언 보강
pending/blocked 일지 카드를 눌러도 상세·복구 버튼에 도달하지 못함pending_saves를 서버 source 분류 전에 로컬 상세로 연결. pending/blocked unit 2개와 046 실제 복구 green
LG426 서버 응답에도 일반 영구 거부 안내만 표시격리 사유 LG426을 보존하고 기존 계약의 업데이트 문구 연결. 036 실제 browser red→green. 임의 새 자동 재시도/파기 정책은 추가하지 않음
프로필 이름 편집의 실제 UPDATE가 403기존 owner RLS 아래 display_name 열권한만 추가. 기존 편집열 유지, handle/onboarding·타 owner·anon 보호 pgTAP
Wodup service worker는 auth.uid가 없어 인입 롤백검증된 explicit owner로 내부 stats job 등록. event/date/exercise 인자 순서와 오류 전파 수정. 원본/통계 잡/owner/worker 후속 완료 DML 검증
늦은 edit ACK가 열린 상세를 구값으로 되돌림045 재로드 전 현재 UI 단언으로 발견. 수정 후 현재 상세/삭제 수렴 green. 무관한 empty flush의 canonical refresh 취소 경합도 세션별 조회 토큰으로 수리. owner·revision·새 pending intent와 삭제 P0002 분기를 포함한 행동 검사 4/4 통과
자정을 지나면 복구 중 요청이 취소되고 저장 재시도 문턱이 닫힌 채 남음실제 React controller에서 9월 30일→10월 1일 변경 중 재수화 signal 취소·dataStatus error·연결만 online으로 남는 red를 재현. 연결 runtime의 수명주기를 날짜에서 분리하고 새 재수화 시작 시 최신 날짜 ref를 읽도록 수리. 진행 중 복구 보존·다음 날짜/월 반영·로그아웃 시 취소와 기존 인증 회귀 4/4 통과

SQL은 최신 main의 S08·D12·D02 뒤 공식 renumber된 20260913050100_e2e_profile_name_and_service_import_recovery.sql과 deployment manifest를 함께 관리한다. 다른 migration이 추가되면 landing 시 공식 renumber/replay/snapshot 절차를 다시 적용한다.

6. 실패 기록과 검증 이력

개발 검증결과/해석
058(당시 040)/042/043/047개별 개발 batch에서 strict green. 다른 코드의 결과를 최종 후보 전체 성공으로 합산하지 않음
041생성·수정·삭제 commit/ACK 유실의 개별 strict green
044/046durability-dev5: 2/2 green, 40.3초. 044는 page close 시 미결 route가 늦게 전달되는 시험 모호성을 실제 settled 401로 수정
036durability-lg426-red에서 업데이트 문구 부재; 최소 수리 후 durability-lg426-green 1/1, 20.8초
045durability-delete-conflict는 DB/reload 경합 green; durability-current-ui는 현재 상세70kg/서버80kg red. 수정 후 reload 없이 현재 UI/삭제 수렴·required reporter 7개 신호 첫 시도 29.9초 green. 추가 empty flush 경합 수리의 행동 검사 4/4 통과; 최신 통합 후보 결과 pending
048/049/050–057048은 pending 저장소 단언 보강 후 개별 첫 시도 31.0초 green. 049 실제 PKCE 경계 보강 후 26.9초 green. 050–057 개별 green 확인; 동일 최종 후보 batch는 pending
offline/pending 상세/기존 관련 unit집중 35/35 통과. 통합 head 전체 unit 결과는 pending
SQL 통합 검증profile 7 + Wodup 16=23/23. main c5b3fd66의 S08과 migration 301을 새 격리 DB에 재생한 뒤 전체 112파일/1,946단언 통과(21초). 이전 111파일/1,923단언 결과와 구분
SQL 생성/정적 계약당시 177개 migration, tail 301; 빈 replay 직후 공식 snapshot 생성/검사, sql:extract 468개 객체·2,788개 문장, sql:check, migration/deployment 검사 통과. 프로필 허용 열과 Wodup explicit owner를 대조하는 기존 source 검사 43개도 통과
SQL 완료 상태 기대 수리imported는 DB CHECK가 허용하지 않는 잘못된 테스트 기대였다. 단언 삭제 대신 실제 worker의 owner/status 조건 UPDATE 후 completed·원문 두 세트·결과건수·완료시각·다른 owner 불변까지 강화
SQL snapshot 순서pgTAP의 dblink 준비가 카탈로그에 남으므로 snapshot은 빈 replay 직후 먼저 확인. 테스트 후 오염된 DB로 snapshot을 재기준화하지 않음
첫 최종 후보 e8937749S02 합류 후 정적/unused/build, unit 3,041 pass/0 fail/23 DB 환경 skip. 별도 DB 단계 112파일/1,946단언, concurrent generation 9/9, CRUD 12/12·empty 8/8·cardio 6/6·persistence browser 19/19 통과. 문서 사이트 빌드 통과
첫 전체 브라우저 실행로컬 preview 포트의 일시적 점유를 확인하고 같은 후보에서 browser/viewport만 재개. 번호 56개 중 첫 시도 53 pass, CASE029/056 fail, CASE044 retry-only pass; viewport 14/14. 집계와 verify는 성공으로 처리하지 않음. 원격 CI 34126273431도 실패
CASE029 시험 순서수정 복구 후의 workspace 요청을 삭제 실패 이후 복구로 잘못 세던 기존 gate를 수정. 실제 update/delete 503 이후의 각 phase 요청·해제·200을 별도로 확인. 기존 요청 각 2회·동일 payload·UI·DB·정리 단언 보존 후 단독 1/1, 재시도 0
CASE044/056 시험 순서044는 A의 실제 replay를 초기 읽기 완료 뒤 해제해 owner 격리 검증을 명확히 함(27초 green). 056은 성공 인입 뒤 진행 중인 카탈로그 갱신 완료를 기다린 후 reload(22.3초 green). 네트워크·앱 오류 면제를 추가하지 않음
원격 샤드별 실제 결과동일 job 이름의 합친 로그는 샤드 간 출력이 잘못 표시될 수 있어 각 artifact의 JSON/trace로 대조. shard2는 CASE029, shard3는 CASE041 retry-only·042 실패, shard4는 CASE054/056/057 실패를 확인
CASE041/042/044 순서 보완저장 직후 갱신과 통계 확정 뒤 강제 갱신의 조회가 6–17ms 간격으로 겹쳐 정상 취소가 발생함을 trace로 확인. 실제 stats RPC를 앞선 조회 완료 후 그대로 실행해 두 갱신 모두 검증. 각 케이스 단독 첫 시도 통과, 최종 042 30.9초·044 26.3초. 저장 원문·영수증·TTL·계정 격리·DB·오류 단언 유지
CASE054/057 순서 보완초기 volume/catalog 읽기가 끝나기 전 reload가 취소를 일으킴. navigation 이전 요청 관찰 및 reload 전후/정리 전 완료 대조를 추가해 2/2, 30.7초, 재시도 0. 기존 오류/다운로드/소유자/원본 단언 유지
D12 최신 main 통합main d1e77113의 DB 개선과 합친 뒤 우리 migration을 당시 꼬리 다음 401로 공식 재번호 지정. 빈 DB에 178개 migration 재생, 공식 snapshot/SQL 원천 일치, 119파일/2,058단언 통과(18초). SQL 470객체/2,801문장. 이전 번호·실행 결과와 구분
D02 최신 main 통합main 7db92fb5의 계획 영수증·세대 경합 변경으로 번호가 겹쳐, 진행 중이던 로컬 전체 실행은 DB 단계 통과 후 중단. 공식 도구로 우리 migration을 501로 재번호 지정하고 합쳐진 빈 DB를 다시 재생. 중단된 실행을 전체 통과로 세지 않으며 최종 후보에서 처음부터 다시 검증
B02 최신 main 통합main 7b44295e의 배포 대상·도구 핀·문서 빌드 검사를 보존해 verify의 선행 8개를 합침. E2E 앱/관리자 빌드는 local로 명시하고, 정적 산출물 검사의 독립 관리자 빌드는 production으로 구분. 새 증거 job도 .nvmrc를 읽음. 합산 실패 판정 28개·도구 경계 7개 통과. D02 통합 빈 replay는 179 migration·39,882줄 snapshot·SQL 원천 470객체/2,801문장 일치
두 번째 원격 전체 실행후보 98eb3249, run 34131312989, 실제 PR 합성 커밋 89584f86. browser 첫 시도 55개·CASE043 retry-only 1개, viewport 14/14. 정적·문서·DB 통과, unit/증거/verify 실패이므로 랜딩하지 않음
CASE043 첫 시도 수리새 페이지의 bootstrap volume 읽기와 만료 JWT 복구 ACK 이후 갱신이 겹친 실제 trace를 확인. 초기 읽기가 끝난 뒤 원문을 그대로 실제 전송하도록 gate를 추가했고 JWT 401·held·영수증·DB·UI·정리·오류 단언은 유지. 최신 schema DB에서 단독 첫 시도 1/1, 26.7초 통과; 최종 전체 원격 결과는 아래 표에서 별도로 확정
세 번째 원격 실행과 준비 상태 수리후보 86a8852b, run 34132686624. CASE043 포함 다른 55개 첫 시도·viewport·DB·unit·정적·문서 통과, CASE054는 두 시도 모두 volume 조회 취소로 실패. 이번 trace는 최초 클릭 이전 stale=true, applied=0/requested=1 → 실제 stats job → 새 Home 적용 시 이전 volume 취소를 확인했으므로 앞선 reload-only 원인 판단을 보완. seedFeatureSession이 actor별 실제 job 완료·실패/남은 잡 0·Home freshness·영수증 요구 세대 반영까지 확인하게 변경. 영향 CASE052/054/057 3/3 첫 시도, 38.4초 통과. 원본·UI·오류/완료 단언과 공용 실패 정책은 유지
D12/B02 통합 누락 수리D12의 DB 장부 생성물에 새 schema 지문·프로필 열권한 반영이 빠져 3개 unit 실패. 공식 db:model로 두 생성물을 갱신해 17/17 통과. B02의 기존 빌드 진입점 단언을 실제 app/admin 공용 builder에 맞춰 12/12 통과. 이후 전체 unit 3,088 pass/0 fail/27 DB 환경 skip
최신 로컬 DB·저장소 검사179 migration 빈 replay·snapshot 일치, 119파일/2,059단언 및 두 연결 세대 경합 13/13 통과. CRUD 12/12·empty 8/8·cardio 6/6·실제 browser 저장소 19/19, 문서/관리자 빌드 통과. 이미 실패한 전체 실행은 원인 수정 시 중단했으므로 로컬 ci:local --full 전체 성공으로 표기하지 않음
반복 실행 도구 보완생성된 Playwright trace viewer의 제3자 Unicode 표를 소스 인코딩 오류로 오인하던 문제를 수정. gitignore된 루트 보고서 두 경로만 생성물로 분류하고, 같은 이름의 소스 하위 디렉터리와 실제 깨진 소스는 계속 실패함을 행동 검사로 확인. 로컬 요약의 분모에도 flaky/skip을 포함해 전체 수를 표시

추가 반복 실행 이력:

  • 첫 전체 green은 후보 2ad252bf, run 34134273788, 실제 합성 SHA 3981c09d293495217d34db4680c1addb78c0fce4였다. Browser 56개·viewport 14개 모두 첫 시도 통과, browser 56개 모두 7개 신호와 cleanup 증거 확인. 실제 전체 시간 8분 40초, 최장 browser shard 3 job 7분 52초(저니 단계 4분 47초), 합산 runner 46분 54초. runner 합은 청구 비용이 아니며 기존 12–15분과 같은 작업량을 비교한 비용 절감 실측도 아니다.

  • main #1362의 로컬 빌드 wrapper 수정 반영 뒤 후보 f0a10badrun 34135562058, 합성 SHA 8219f9b5f7d8ad7f116d5cdfd47d4fbfeb4495a4실패했다. Browser 첫 시도 53개, CASE033/039/043은 재시도에서만 통과; viewport 14개 통과. 첫 시도 gate는 이를 정상적으로 거부했다. 전체 10분 35초·합산 runner 50분 12초로, 앞선 green을 이 후보의 합격 증거로 전용하지 않는다.

  • CASE033은 KST 자정 직전 시작한 기록을 9월 7일로 저장하고, 자정 후 helper가 오늘인 9월 8일에서 찾은 테스트 결함이었다. 달력과 하루 세트 수가 실제 저장 날짜를 사용하도록 수정했다. CASE043은 복구 후 달력→오늘→선택일의 연속 조작이 day summary를 취소한 경우여서, 실제 조회 완료 뒤 저장일을 한 번 선택하도록 순서를 정리했다. S03 main #1363 통합 빌드에서 033/043 첫 시도 2/2, 39.5초 통과했다.

  • CASE039은 구버전의 재수화 대기 중 자정을 지났고, workspace 뒤 Home 조회가 끝나지 않아 마지막 전송이 시작되지 않았다. 공존 테스트는 같은 업무 날짜에서 실제 시간이 흐르도록 시작 시계와 토큰 유효성을 명시하고 probe/lease/재시도 기한은 유지했다. 이 수리 후 로컬 1/1 첫 시도, 1.6분 통과. 제품의 날짜 변경 시 복구 lifecycle은 별도 재현 대상으로 추적하며 구버전 소스를 수정하지 않는다.

  • 최신 main S03 #1363(1bba53eb) 통합 후보 d2de32db의 로컬 verify-only는 8단계·1분 58초 통과, unit 3,098 pass/0 fail/27 DB 환경 skip였다. 서버 소스는 앞선 119파일/2,059단언 preflight와 동일하다. 이 로컬 결과도 새 원격 전체 run을 대신하지 않는다.

  • main A07 #1365와 문서 #1366(1fe87fcd)를 추가 통합했다. 문서 사이트·관리자 셸 빌드와 서버 내용 해시 기반 preflight 확인이 통과했다. A07이 분리한 실제 controller/host에서도 날짜 변경으로 재수화가 취소되는 현상을 재현한 뒤 최신 날짜 ref로 최소 수리했다. 실제 React+Chromium 검사에서 보류 중 복구 유지·다음 재수화의 10월 1일/10월 사용·로그아웃 취소·기존 인증 시나리오 4/4 통과. 구버전 소스에는 이 제품 수리를 적용하지 않는다.

  • 공용 달력 helper는 별도 로컬 진단에서 2025-12-31의 실제 소유자 기록을 조회해 해당 연도/월/일로 이동하고, 리로드 뒤 같은 ID를 다시 열었다(1/1, 22.9초). 이 진단은 번호 패키지나 현재 57개 자동 집합, 최종 run의 완료 건수에 합산하지 않는다.

  • A07 통합과 자정 제품 수리 후 로컬 verify-only 8단계·2분 13초 통과, unit 3,115 pass/0 fail/27 DB 환경 skip. 실제 React 브라우저 4/4와 관련 연결/인증/owner unit 42/42도 통과했다. 최종 원격 후보 증거는 §8에 별도로 마감한다.

  • 후보 4a8eb0a8run 34141462265는 합성 SHA d7e9736b94bf912138449b9f4219063d17bb6778에서 56 browser + 14 viewport 첫 시도 통과, browser 전부 7개 신호·cleanup 확인, skip/retry/error 0이었다. 전체 8분 48초, 최장 shard 3 8분 5초(저니 4분 30초), 합산 runner 47분 38초. Unit 3,115 pass/27 DB 환경 skip, pgTAP 119파일/2,059단언, persistence browser 20/20을 확인했다. 그러나 실행 중 S04 #1369가 main에 먼저 합쳐져, 머지 직전 최신 main 포함 검사가 랜딩을 막았다. 이 green은 S04 통합 후보의 성공 증거가 아니다.

  • 같은 후보의 앞선 run 34139642612는 shard 3의 Ubuntu 폰트 패키지 21.1 MB 다운로드에 13분 36초(25.8 kB/s), 시스템 설치 전체에 13분 49초를 썼다. apt는 성공했으나 job 전체 20분 제한으로 여정이 취소됐다. 부분 성공이나 불완전 artifact를 합산하지 않고 공식 full-ci로 새 전체 run을 요청했다. 위 새 run의 5개 환경 설치는 14–25초였다. 시간 한도·flaky 기준은 늘리지 않았으며 runner 합산 시간은 청구 비용이 아니다.

  • S04 #1369 통합으로 main의 CASE040을 보존하고 기존 enqueue 실패 패키지를 CASE058로 이동했다. check:error-cases는 연속 패키지 58개를 확인했고, 실제 local-supabase manifest 집합과 사전 필수 browser 57개·viewport 14개를 대조했다. CASE058의 spec/manifest/사용자 여정은 번호 치환 이외 동일하며 main CASE040의 spec은 변경하지 않았다. 두 spec 문법, UTF-8, diff 공백 검사와 완료 증거 집계기 행동 검사 2/2 통과. 최신 앱에서 **CASE039/040/046/058 첫 시도 4/4(2.4분)**를 확인했다. 전체 57개 첫 시도 검증은 별도로 마감한다.

  • S04 통합 로컬 정적·unit은 3,128 pass/0 fail/27 DB 환경 skip, 전송/보존 집중 unit 68/68, 실제 browser 저장소 24/24를 확인했다. 앱·관리자·문서 빌드와 배포 대상 산출물·unused 검사도 통과했다. S04는 서버 파일을 바꾸지 않아 기존 DB preflight 해시가 여전히 유효하다.

  • S04 통합의 CASE045 첫 실패는 B 요청이 기존 예상 2개 대신 3개인 경우였다. trace에서 추가 요청은 A의 10초 lease 만료 뒤 같은 mutation/hash/payload를 B가 인계 재확인한 200이며, B 고유 수정은 실제 400→200 그대로임을 확인했다. 이후 서버 80kg/개정번호3과 A의 열린 상세 70kg의 차이를 관측했지만, 추가 확인에서 10초 lease 인계를 기다리는 동안 완료 RPC의 10초 요청 제한까지 함께 넘기는 시험 조건이 드러났다. 이를 제품 회귀로 단정하지 않고 같은 저장소의 후속 행(CASE040)과 독립 기기의 실제 개정 충돌·늦은 ACK(CASE045)를 구분해 검증한다. 진단에서 A의 실제 LG_WORKOUT_WRITE_TIMEOUT(10.009초), uploaded=0/deferred=true, 정상 projection/owner 가드를 확인했다. 성공 ACK를 놓친 제품 회귀라는 초기 추론은 정정한다. 임시 진단은 제거했고 제품 코드는 바꾸지 않았다. 독립 저장소의 두 문맥에서 A save [200,200]·B save [400,200]·B delete [400,200], 각 IDB의 자기 요청만 존재, 제품 제한 전 ACK 해제, 현재 UI·원본·개정번호·소유자·cleanup을 확인한 최종 여정은 1/1 첫 시도, 31.7초 통과했다. 이 line reporter 개발 결과를 전체 필수 집합의 같은 SHA/run 성공으로 합산하지 않는다.

  • 최신 main의 A08 조회 캐시와 후속 문서(b672eb38, PR #1372/#1373)까지 로컬 통합했다. 문서 링크 충돌은 양쪽 항목을 보존했으며 A08의 조회 취소·owner 수명 계약을 바꾸지 않았다. npm run check3,146 pass/0 fail/27 DB 환경 skip(총 3,173), 실제 Chromium 저장소·인증·오류 감시 24/24, unused·앱/문서/관리자 빌드·산출물 검사가 통과했다. 새 앱에서 조회·복구에 걸치는 CASE015/045/047은 3/3 첫 시도, 2.4분 통과했다. 이 개발 집중 실행은 line reporter이며 최종 57 browser + 14 viewport의 같은 SHA/run 완료 증거를 대신하지 않는다. 서버 소스 해시 기반 preflight도 유효함을 확인했다.

  • 사용자 게시 승인 후 main b607a6cc의 S05/S07 대기열 분리와 A12/A13 편집기 변경까지 통합했다. S05의 dispatcher→영수증 대조→feature binding 구조와 S07의 저장소·미러를 유지하며, 기존 오프라인 deferred와 비종결 결과 1회 소비는 store에, LG426 원인 보존은 canonical failure 분류기에, 늦은 ACK 뒤 최신 상세 재조회·개정번호·owner/epoch·새 pending intent·삭제 보호는 feature binding/controller 포트에 옮겼다. 같은 새 경계의 행동 회귀는 수리 전 2 pass/7 fail → 9/9 pass, 성공 삭제가 이전 수정 조회를 무효화하는 추가 1건까지 10/10이다. 기존 관련 dispatcher/영수증/경계/outbox/상세 23/23, CI 범위/완료 증거 26/26도 통과했다. 새 앱의 CASE015/036/045는 3/3 첫 시도, 2.1분으로 오프라인 복구·실제 업데이트 상세 안내·다른 기기의 충돌/늦은 ACK를 확인했다. 전체 필수 집합 검증은 아래 최종 증거에서 별도로 마감한다.

  • 후보 d168de9f원격 CI 34178201278는 실제 합성 SHA 25829528639b4ab62ddffc269d20b31606b44988에서 57 browser + 14 viewport 전부 첫 시도·7개 신호/cleanup 증거 통과, 전체 8분 46초였다. 로컬 공식 full 실행도 같은 후보의 DB 재생·snapshot·119파일/2,059단언·세대 경합 13/13·CRUD 12/empty 8/cardio 6·저장소 browser 37/37·번호 여정 57/57·viewport 14/14·완료 증거를 통과했다(전체 18분 37초, 번호 여정 12분 34초). 다만 그 실행의 unit 1건이 실패했으므로 로컬 full 명령 자체는 실패다. tests/auth/accountDeleteApi.test.mjs가 요청 시작을 5ms 고정 대기로 추측해 storage list request was sent에서 실패했다. 제품 API는 바꾸지 않고, 스토리지·인증 timeout 주입 두 곳을 실제 fetch의 abort listener 준비 신호를 기다리도록 고쳤다. handler가 먼저 끝나면 실패하게 하고 기존 502/504/503·재시도 가능·계정 미삭제 단언을 유지했으며 해당 9건이 통과했다. 이 테스트 변경 후 최종 원격 후보 증거는 §8에 별도로 확정한다.

7. 별도로 필요한 출시 증거

58개 번호를 완전자동 MECE나 모든 핵심 UX의 무결함 보장이라고 부르지 않는다. 한글 검색·반응·인입의 대표값, Chromium의 페이지 종료, 주입한 실패 조건을 검증하는 범위다. 실제 provider 동의/취소/SSO, iOS/Android 바이너리·OS 종료·딥링크, WebKit, 실제 배포 번들, populated migration·구형 사본 복원, 장기 이력 성능·G04 예산은 별도 후보 증거가 필요하다. 소스 재빌드한 legacy bundle은 과거 배포 artifact 자체가 아니다.

SYS-05/09/13/14/17/18 등 전면 fixture 분해·설정 builder·전체 메타데이터 생성·소스 검사 대체·모든 레인 결과 통합·샤드 재균형은 미구현 또는 부분 완료로 남긴다. 이번 기능 경계 수리를 넘어선 리팩터링이나 근거 없는 비용 개선 수치를 추가하지 않는다.

8. 최종 구현 PR·staging 증거

이 절의 원격 완료 수치는 PR #1361의 같은 head와 한 번의 전체 CI 실행에서 확인한 결과다. §6의 이전 실패·부분 실행 기록은 개발 이력으로 보존하며 최종 완주 건수에 합산하지 않는다. 이후 사용자 핵심 UI 기준에 따른 추가 보강은 이슈 #1383에서 별도로 검증하며 이 절의 green을 새 코드의 결과로 재사용하지 않는다.

항목최종 결과
최종 PR/후보 SHA#1361, head 136eff63cdca3eaba5d5a73ac7b4551ab21bed29
CI 실제 시험 SHA4d51a173313fc4f4ede7d2db5366799c0a3c8cb2; parents b607a6cc602571c4c5929b6dfe782eb72258078f + 위 후보
최종 전체 CI34179301795, attempt 1, 전체 13개 job 성공. 2026-09-08 02:13:21–02:22:16 UTC
57 자동 CASE + 14 viewport동일 run/시험 SHA에서 모두 첫 시도 통과. 누락·중복·skip·retry·실패 0. 57개 번호 CASE의 7개 완료 신호·cleanup-readback 완비. viewport는 실제 사용자 삭제/부재 재조회의 성공한 afterAll로 정리 확인
통합 unit/정적/DB정적·문서·unit 3,225 pass/0 fail/27 DB 환경 skip, 179 migration 빈 replay/snapshot, pgTAP 119파일/2,059단언, 두 연결 세대 경합 13/13, CRUD 12/12·empty 8/8·cardio 6/6·독립 저장소/인증 browser 37/37 통과. unit skip은 통과에 합산하지 않음
로컬 검증 구분제품·E2E·DB가 같은 d168de9f의 full에서 DB·37 저장소·57 여정·14 viewport·완료 증거는 통과했지만 계정 삭제 unit의 5ms 고정 대기 때문에 명령 exit 1. 준비 신호로 수리한 실제 변경본의 공식 verify-only 8단계/2분 46초·unit 3,225/0 fail·집중 계정 삭제 9/9 통과. 최종 후보 전체 green은 위 원격 run으로 확정
CI wall time·가장 느린 샤드8분 55초. browser 3/4 job 8분 12초, 그 안의 실제 여정 step 5분 6초. DB 준비 2분 25초, Chromium 시스템 의존성 21초
runner 시간·artifact13개 job 시간 합산 48분 42초, artifact 5개 8,016,315 bytes. 합산 runner 시간은 사용자 대기 시간이나 청구 금액과 다름
main 머지2026-09-08 02:23:28 UTC, 32835b0c541f195dc137250ea6117da81d5be049. 후보와 머지 결과의 전체 파일 diff 0
자동 랜딩34179866109, attempt 1 성공, 02:23:06–02:27:11 UTC(4분 05초). 최종 영수증의 merge/staging SHA 일치
v0.17.2 stagingDeploy 34179889366, 32835b0c541f195dc137250ea6117da81d5be049. attempt 1, 02:23:31–02:26:48 UTC(3분 17초), DB→Edge 3개→frontend→smoke 성공. pending 501 migration 1개 적용/최종 pending 0, remote missing/contract failure 0
배포 후 확인 범위실제 staging Auth/DB 스택의 CRUD smoke 12/12, 실패·skip 0. 57개 UI E2E 추가 실행은 아님. frontend는 해당 SHA checkout→build→deploy로 연결되며 staging에서 Production 전용 served-origin 비교·release tag 생성은 수행하지 않음
branch protectionmain 활성 ruleset의 required verify·landing-queue, production의 required verify 유지. verify가 전체 필수 선행 결과를 기다림
v0.17.2 릴리스 후보main→production 후보 PR에서 최종 main SHA와 required CI를 별도로 확인. 이 문서의 staging 성공이 Production 배포·태그 생성을 뜻하지 않음
실제 provider/native/performance/upgrade-restore이 PR의 자동 Chromium 집합에서는 미검증. CASE003은 사전 준비 provider QA 계정의 조건부 집합이며 실제 인증 전체를 대체하지 않음. native 바이너리/OS 종료·성능 예산·populated upgrade/restore는 후보별 별도 증거 필요

기존 CI 최적화 PR #1306의 37개 집합에서 측정한 6분 34초와 이번 57개 집합의 8분 55초는 작업량이 다르다. 사용자가 경험한 12–15분보다 짧은 성공 표본을 확인했지만, 같은 조건의 속도 개선율·p95·비용 절감으로 해석하지 않는다. 이번 PR은 실행 코드 변경의 전체 검사와 완료 증거를 필수화하고 main push의 전체 E2E 중복을 제거했다. 샤드 재균형은 별도 후속으로 남긴다.

환경 지연 이력도 남긴다. 이전 head의 run 34139642612는 shard 3에서 Ubuntu 폰트 패키지 21.1 MB를 13분 36초에 내려받아 시스템 의존성 설치에 13분 49초를 사용했다. apt는 성공했지만 job 전체 20분 제한으로 여정 실행이 취소됐다. 부분 성공을 합산하거나 시간 한도·flaky 기준을 늘리지 않았다. 이는 관측한 환경 다운로드 병목이며 제품 오류로 확인된 것은 아니다.

9. 적용 전후 — 테스트 통과가 의미하는 것

적용 전에도 운동 저장·수정·DB 재조회·리로드와 사고 회귀 검증은 있었다. 이번에는 장애가 발생하는 지점과 복구 후 사용자 결과를 보강하고, 그 검사가 실제로 실행·완료되지 않은 PR을 차단한다.

관점적용 전이번 구현 적용 후
실행 누락앱/API 단독 변경에서 전체 E2E가 빠질 수 있었음실행 코드·DB·테스트·의존성·설정·미분류 변경은 자동 집합 전체 필수. 명시적 비실행 문서만 예외
저장 도중 장애commit 이후 응답 유실·앱 종료·기기 저장 실패를 함께 추적하는 왕복 증거 부족실제 IDB 중단·sending 종료·ACK 유실·HTTPS offline queued 재진입 후 입력 보존과 최종 원본/개정번호/영수증 수렴 확인(041/042/048/058)
로그인·계정 전환인증·격리 검사는 있었으나 pending 기록의 복합 경계 부족실제 만료 JWT 401→held→재인증, A→B→A UI/IDB/DB 격리 확인(043/044)
늦은 응답·동시 변경저장/리로드 검사만으로 현재 화면의 과거 값 회귀를 놓칠 수 있었음실제 수정·삭제 충돌 및 늦은 ACK 뒤 reload 전 현재 UI·삭제 상태, 지연 조회/503 후 재진입 확인(045/047). 공유 저장소의 옛/새 탭은 main의 040과 구분
오류 안내·복구지연 오류 텍스트 관측 누락, 첫 실패를 추가 조작으로 가리는 경우실제 노출 오류 관측 보강·첫 조작 결과 판정(011), LG426 안내·blocked 상세에서 입력 보존/새 기록 복구 확인(036/046)
주변 핵심 기능하위 검사 대비 사용자 조작 왕복의 공백프로필·소셜·초대/권한 회수·종목 관리·Wodup/Motra·내보내기의 대표 실패/재시도 추가(050–057)
전체 성공 판정환경·발견 조건에 따라 실제 실행 목록이 줄 수 있었음사전 목록과 같은 SHA/run의 실제 결과를 대조. 누락·중복·skip·재시도 통과·미완주·정리 실패를 거절

계획 기준 39개 패키지에 신규 18개와 main의 S04 1개를 더해 58개 패키지, 그중 57개 PR 자동 검사 + 별도 viewport 14개다. 번호 CASE 전면 퇴역은 0개이며 고유한 사고 경계를 보존했다. 중복 helper 정비를 CASE 감소로 세지 않는다.

통과 시 주장할 수 있는 범위는 검증한 코드와 지정된 환경에서, 대표 사용자 여정과 정의한 장애·복구 경로가 첫 시도에 완료됐고 화면·상태·인증된 API/RPC·DB 재조회·재진입·오류 관측·정리 증거를 확인했다는 것이다. 모든 UX의 무결함이나 모든 입력·기기·장애 조합의 MECE 증명이 아니다. 실제 provider 인증·연결/해제 전체와 native·성능·운영 복원은 §7의 별도 검증 범위를 유지한다.

10. 핵심 UI 진행·저장 완료 보강 — #1383

사용자는 자주 쓰는 핵심 UI에서 예상치 못한 오류 때문에 저장하거나 다음 단계로 진행하지 못하는 일이 없음을 확인하고 싶다고 명확히 했다. 마스터플랜 §4.1에 정상 완주·장애 후 입력 보존/실제 UI 복구·저장 원본/재진입의 합격 조건을 적었다.

실제 spec 대조에서 빈 운동의 최초 폐기와 구분되는 사용자가 값을 입력한 초안의 종료→이어하기→완료 저장, 계획 생성/전환과 구분되는 기존 계획 편집의 정상 저장 및 실패→입력 보존→실제 복구 전송이 우선 보강 대상이다. 기존 계획 편집의 retryable 실패는 변경을 기기에 보관하고 편집기를 닫는 현재 계약을 유지하며, 실제 안내·보존 원문·연결 복구 후 서버 반영과 재진입을 확인한다. 같은 편집기를 계속 열어두거나 별도 재시도 버튼을 요구하지 않는다. 제품 오류 확정과 테스트의 증거 공백을 구분한다. 기존 고유 단언과 실행 프로필을 보존하며 추가 보강의 최종 PR/CI/staging 결과는 이 절에 별도로 마감한다.

CASE047은 실제 상세 조회 503 후 새로고침으로 복구하기 전에 뒤로가기→같은 기록 선택→실제 200→현재 상세와 DB까지 확인한다. 리로드 helper가 현재 앱의 복구 동작을 대신하지 못하도록 했다.

CASE029에서는 제품 결함을 재현했다. 온라인 상태의 계획 수정 요청이 한 번 503을 받으면 입력과 요청은 기기에 보존되지만, 새로고침·연결 이벤트 없이 15초 동안 실제 두 번째 요청이 발생하지 않았다. persistPlan이 낮은 단계의 대기열 저장소에 직접 적어 기존 스토어의 즉시 전송 연결을 건너뛰고 있었다. 수정은 계획 편집 적재를 기존 공통 대기열 명령에 연결한다. 요청 형식·전송기의 실패 정책·DB·UI 구성은 바꾸지 않는다. 복구 테스트는 두 번째 실제 요청을 붙들어 IDB 원문·동일 해시·서버 이전 값을 확인한 뒤 서버 200과 같은 계획 ID/revision 증가·현재 화면·재진입을 확인한다.

자동 전송 수정 뒤에는 같은 앱의 실제 200/DB revision 2/80kg까지 통과했지만, 열린 상세가 원래 제목/60kg에 머무는 두 번째 결함을 검출했다. 완료 기록에만 연결됐던 저장 확정 후 상세 갱신을 계획에도 연결하되, 현재 사용자·새 대기 입력·개정번호·늦은 응답 보호를 유지한다. 현재 상세 단언을 먼저 통과해야 뒤로가기/다시 열기와 리로드 재진입으로 넘어간다.

추가 경계로컬 집중 결과
CASE011 실제 초안 이어하기→완료→DB/재진입재시도 없이 1/1, 28.2초. 작성 중 locator·wire receipt·날짜 위치의 테스트 가정을 수정한 뒤 완료
CASE016 기존 계획 정상 편집→저장→DB/재진입재시도 없이 1/1, 24.3초. 계획 하위 행 교체 계약에 맞춰 부모 동일성·값/순서·이전 자식 부재를 검증
CASE047 같은 앱에서 실패한 상세 다시 열기재시도 없이 1/1, 33.8초
CASE029 계획 실패 후 같은 앱의 실제 복구 전송자동 재전송 부재와 현재 상세의 옛 값 잔류를 각각 검출·수정. 수정 후 재시도 없이 1/1 완주(Playwright 출력 약 1.7분), 같은 앱의 실제 전송/현재 상세/다시 열기/리로드/전체 정리 통과
관련 쓰기 명령 단위 검사5/5 통과
계획 상세 갱신과 기존 완료/전송 경계신규 계획 행동 4개 + 기존 완료 상세/dispatcher 경계 15개, 19/19 통과. 타입·lint·manifest 통과
최종 로컬 전체 검사npm run check 통과: 정적 게이트 + unit 3,234 pass / 0 fail / 27 DB 환경 skip. 앱·관리자 build/artifact와 unused 검사도 통과
PR #1386 최초 원격 전체 실행34183258513, 후보 85e7743a, 실패. 56/57 browser 첫 시도 통과, CASE028만 첫 실패 후 재시도 통과. viewport 14/14·unit 3,234·DB/저장소는 통과했으나 전체 Green으로 합산하지 않음
CASE028 재진입 경계 보완저장 후 앱 반영이 끝나기 전 reload와 경고가 겹친 순서 확인. 실제 후속 상세 200·대기열 0·관측 요청 완료를 요구하고 기존 오류 gate 유지. 보강 후 로컬 1/1 첫 시도, 26.1초
최신 main rebase 후 원격 실행후보 df12ffb6, 34185059149, 실패. CASE045 첫 시도에서 늦은 ACK 이후 자동 day summary 두 번이 겹쳐 이전 요청이 취소됨. 실제 reload/사용자 클릭 이전이며 화면 오류는 없었지만 첫 시도 오류 gate가 거절. 재시도 통과를 전체 Green으로 세지 않음
CASE045 조회 순서 보완두 문맥 각각 저장 직후 실제 조회 완료→실제 통계 처리→통계 확정 조회를 통제. 수정/수정·수정/삭제 충돌, 제한 시간 내 늦은 ACK, 현재 UI·DB·영수증·오류·정리 단언 유지. 최신 통합 앱/관리자 빌드에서 로컬 1/1 첫 시도, 54.2초 완주·정리 통과. 자동 조회끼리의 경합을 이 쓰기 충돌 CASE의 보장으로 확대하지 않음

로컬 집중 결과는 최종 전체 PR CI를 대신하지 않는다. 패키지 58개·PR 자동 CASE 57개·viewport 14개 수는 유지한다.

최신 main 1d8b9aaf를 통합한 제품/CASE 코드에서는 네 보강 CASE를 함께 재실행해 **4/4, 첫 시도 통과(약 2.1분)**를 확인했다. 문서/관리자 빌드도 통과했다. 공식 verify-only의 첫 실행은 공통 helper 이름을 고정한 기존 경계 검사 2개에서 실패했고, 감사 신고와 함께 함수명 앵커 두 곳만 갱신한 뒤 해당 검사 29/29를 확인했다. 저장 순서·동작 단언을 유지하며 최종 전체 검사와 PR/staging 결과는 #1383에 연결해 기록한다.

최종 PR·스테이징 결과

#1386에서 위 네 핵심 플로우 보강과 계획 저장 복구·현재 상세 갱신 두 결함 수리를 마쳤다. CASE028은 재저장 이후 실제 상세 반영을 확인하고 다시 진입하도록, CASE045는 늦은 ACK 이후 두 실제 조회를 모두 완료하도록 보완했다. 오류 허용 범위·첫 시도 기준·시간 제한을 완화하지 않았다.

확인 항목최종 결과
검증한 후보3a58c64391192364334e9964c4212a6812f791a8, 실제 PR 합성 SHA f90a1a0bd9f1bce793524d9f282f9eac7a259393, 기준 main 46687bcfbfa5374446ca84a3104758b8a22b40fc
필수 CIRepository checks 34186101211, attempt 1 전체 성공, 8분 48초
같은 실행의 사용자 여정browser 57/57 + viewport 14/14 첫 시도 통과. Browser 57개 모두 7개 완료 신호와 정리 확인. 누락·skip·retry·실패 0
같은 실행의 하위 검사unit 3,246 pass / 27 skip / 0 fail, pgTAP 119파일·2,059단언, 실제 브라우저 저장소 38/38. 단위 skip을 성공 수에 합산하지 않음
main 병합4e50e4af281e6b2ec1decca559ef478db0c0b308, Landing 34186664264 성공
같은 SHA의 stagingDeploy 34186683775, DB → Edge → frontend 성공. 미적용 migration 0·원격 계약 오류 0, 실제 staging CRUD 12/12

앞선 후보 7eab0966CI 34184288213도 실제 최신 main 46687bcf와 합친 코드에서 57+14 첫 시도·완료 증거를 통과했다(8분 45초). 다만 후보 브랜치 자체가 최신 main을 조상으로 포함하지 않아 첫 랜딩이 차단됐다. 최신 main 위로 rebase한 tree는 그 통과한 합성 커밋과 동일했지만 새 실행에서는 CASE045가 첫 시도에 실패했다. 위 표는 해당 경계까지 보완한 새 head의 별도 실행이며, CASE028·045의 재시도 통과 실행은 실패 이력으로 유지한다.

합격 의미는 검사에 정의한 핵심 화면에서 입력·저장·다음 단계·다시 열기가 실제 완료됐고, 주입한 일시 장애 뒤 입력 보존과 실제 복구를 확인했다는 것이다. 온보딩 최종 제출 실패, picker 최초 조회 실패, 각 통계 탭의 독립 오류 등 남은 직접 검증 경계는 별도로 남는다. 모든 사용자 환경에서 오류가 없다는 보장으로 확대하지 않는다.

v0.17.2 main→production 릴리스 후보의 최신 SHA와 필수 CI는 #1383 완료 기록에서 연결한다. 이 문서 마감은 Production 배포·태그 생성이나 마스터플랜의 전면 fixture/메타데이터 정비 완료를 뜻하지 않는다.