{ "status": "approved", "language": "ko", "reviewedUtc": "2026-10-08T17:48:13.665069+00:00", "summary": "독립 전체 네 관점 검토를 확정한다. 기존 전체 219파일 검토와 원경 32파일 delta 검토를 유지하고 새 제품 4단계 원문 및 최종 문서/채택 기록을 대조했다. 차단 0건이며 수용된 한계만 남아 있다.", "scope": { "mode": "읽기 전용 전체 검토 + 후속 delta/실제 원문 독립 대조", "runtimeExecution": false, "testsBuildUnityAdbBlenderRecordingStarted": false, "onlyWrittenFile": ".dryforge/reviews/final-review.json", "base": "58410281e015c6600dc543c4e093fd95c036288c", "reviewedHead": "0d992d9dcc94843a72489b454ca4e8137178bc56", "testedProductCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "changedFilesFromProtectedDev": 219, "latestDocumentationChangedFiles": 10, "latestDocumentationPaths": [ "SourceAssets/Models/Heroes/active-adoption.json", "SourceAssets/Models/Meadow/active-adoption.json", "docs/asset-register.md", "docs/content.md", "docs/engineering-notes.md", "docs/final-verification.md", "docs/handoff.md", "docs/operations.md", "docs/tracking/decisions/0005-hybrid-assets.md", "docs/tracking/status.md" ] }, "repositoryChecks": { "gitRootBefore": "C:/git/MagnetismHeroes", "HEADBefore": "0d992d9dcc94843a72489b454ca4e8137178bc56", "cleanBefore": true, "HEADAfter": "0d992d9dcc94843a72489b454ca4e8137178bc56", "cleanAfter": true, "protectedDev": "58410281e015c6600dc543c4e093fd95c036288c", "rootAndModuleInstructionsUnchanged": true, "testedProductToCurrentAssetsPackagesProjectSettingsToolsDiff": "", "beforeAfterRawProductHashCount": 732, "beforeAfterDictionariesIdentical": true, "currentRawProductHashesMatched": 732, "acceptedGeneratedYamlWhitespaceCheckExit": 0, "defaultCodeDocsWhitespaceCheckExit": 0 }, "rubric": [ { "lens": "명세 준수", "criteria": "R01~R10의 영웅 우선 장난감 외형·세 자연 테마·실제 지형 연결·승인 파일 동일성·수량/ID/배치/입력/저장 경계", "result": "통과. 원래 전체 검토에서 승인 연결·대표 장비 lifecycle·30개 비시각 정의 보존을 확인했다. 유일한 원경 틈 차단 사항은 공통 radius27 배치로 수정되어 실제 A/B 및 최신 전체 화면에서 해결됐다. 전체 외곽/모든 각도 가시성을 보장하지 않는다." }, { "lens": "코드 품질", "criteria": "기존 상태 소유와 취소·복원 경로 유지, scoped Unity API, 실제 메시/입력 검사 및 최소 변경", "result": "통과. 원래 GroupBadge 3줄 변경은 기존 수명을 따르고 Core/input/persistence를 변경하지 않는다. 원경 helper는 y/scale/rotation/다른 props를 유지하며 generator와 같은 상수를 사용한다. 새 geometry 검사는 별도 PhysicsScene의 실제 sharedMesh hit이며 게임 collider/board 상태는 불변이다. 엄격한 55개 발견/pick/drag·아치 hole/side·95% label 검사를 유지한다." }, { "lens": "문서 내용·형식", "criteria": "한국어 자기완결 설명, 현재/과거/미검증 범위 구분, 적절한 상세, 허위 통과·새 불필요 의존 금지", "result": "통과. 최신 8개 docs는 source3346·103/53/226·새 APK 및 실패 시도/Smoke만 재실행을 실제 원문에 맞게 기술한다. ADR는 선택 이유 2문장으로 제한했다. 과거 83182 결과는 BeforeHorizonFix 이력으로 명시했다. 신규 cross-doc 링크 및 active 3문서 참조는 0이다." }, { "lens": "문서 완전성·소스 교차 확인", "criteria": "원본/FBX→Unity GUID/재질→실제 증거/APK 해시, 실제 종료/소스/파일 동일성, 운영 API/필수 지침/최종 승인 구분", "result": "통과. active-adoption 239개 SHA 기록(별도 승인 파일25개 포함 총264개 SHA 노드)·111 GUID/metaSHA가 실제 root 파일과 일치한다. gallery8Editor+3native 상대 링크 모두 유효하고 source/시각/카드수치가 일치한다. 문서 통합 이후 raw 제품732개 바이트가 동일하므로 문서만의 이유로 Unity 검사를 추가 요구하지 않는다. 제품 전체 사용자 최종 승인은 여전히 별도다." } ], "issues": [], "advisory": [ { "id": "기존-지면-아래-시점", "location": "docs/tracking/findings.md:5", "observation": "yaw210/pitch−45/distance15에서 새 넓은 지면 뒷면이 원래 Island보다 보드를 더 많이 가림을 실제 A/B로 확인했다. 여섯 first physical hit 동일성이 동일 시각 가림을 증명하지 않는다. 55구 탐색/직접 pick/drag 통과에는 음의 pitch 사례가 있다.", "disposition": "명시적으로 수용된 이번 범위 제한. 기존 카메라/입력/배치 보존을 우선하고 별도 카메라 UX 결정으로 남긴 기록이 정확하다. 현재 변경의 추가 차단 항목으로 올리지 않는다." }, { "id": "실기기-및-얼굴-가시성-한계", "location": "docs/tracking/status.md:11; FinalProduct/EditorCapture 캡처 metadata", "observation": "실제 Stage21 기본 화면의 큰 묶음 얼굴 일부가 앞 구에 물리적으로 가려지며 숫자5와 다른 대표 얼굴은 보인다. Editor texture memory는 폰트/RT 포함이고 resident triangle 수는 꺼진 원래 floor도 포함한다. Camera.Render 시간은 Editor CPU wall time이다. AVD와 합성 viewport는 실제 모바일 GPU/FPS/열/배터리·아이 사용성·iOS를 증명하지 않는다.", "disposition": "배치와 physical occlusion 보존에 따른 수용 제한·후속 검증 범위. 모든 각도/모든 얼굴 가시성 또는 실기기 성능 합격을 주장하지 않은 현재 문서를 유지한다." }, { "id": "원경-geometry-표본-범위", "location": "docs/engineering-notes.md; DistantTerrainHasContinuousApronAcrossItsVisibleFootInsteadOfSkyGaps", "observation": "0 누락 결과는 cardinal corridor lateral ±12m/방사 .25m/횡단2m 표본이며 actual foot 약±15.35m 전체 경계·픽셀·각도 증명이 아니다. FOV14는 비교용 임시 카메라이고 제품 FOV62는 유지한다.", "disposition": "최종 문서의 표본 범위와 실제 close/full 시각 판단을 함께 근거로 사용한다. 현재 실제 관찰에서 중앙 틈은 해결되었고 양끝 평평한 림은 외곽 silhouette로 판정했다. 추가 차단 사항은 없다." } ], "resolvedIssues": [ { "id": "원경-지형-연속성", "previousStatus": "차단", "resolution": "ef036 원경 배치 수정 및 3346 실제 전체 4단계 통과/현재 문서 반영", "evidenceReview": ".dryforge/reviews/horizon-fix-conformance.json", "reviewSha256": "5eba704c16ab4e7319c10aad8e337b8737e974df99966ff4b9d05040f3ac3e22", "originalWholeReview": "artifacts/verification/VisualUpgrade/BeforeHorizonFix/final-review.json", "originalReviewSha256": "2f4269c77224aea872289cf51f76a5f6cdb626ec7af1789a63f5fcfb91a0e5b0" } ], "capturedVerification": { "phases": [ { "phase": "EditMode", "command": "pwsh -NoProfile -File tools/verify.ps1 -Phase EditMode -Milestone Final", "outerExit": 0, "rawExit": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "startedUtc": "2026-10-08T16:56:47.0526983Z", "finishedUtc": "2026-10-08T16:57:10.801033Z", "evidenceSha256": "c8e8b452df15fdf1a953d0b679af8f8f36b948668e75e4e6d7f76765b981dc14", "outerLogSha256": "27b5747f628fe5968282f21fa7eb401c5280ad1dbf83967f45fdee5ac207abc2" }, { "phase": "PlayMode", "command": "pwsh -NoProfile -File tools/verify.ps1 -Phase PlayMode -Milestone Final", "outerExit": 0, "rawExit": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "startedUtc": "2026-10-08T16:57:10.8088291Z", "finishedUtc": "2026-10-08T16:57:54.4619847Z", "evidenceSha256": "e279aa904d6852115df0204135caef908fdd3e74ae71a8ea8a5827b8c013a41b", "outerLogSha256": "07316d712aa9e277134cb6a1a406b2718571b358da8a0a2186bd97e2c57f86ef" }, { "phase": "AndroidBuild", "command": "pwsh -NoProfile -File tools/verify.ps1 -Phase AndroidBuild -Milestone Final", "outerExit": 0, "rawExit": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "startedUtc": "2026-10-08T16:57:54.4634842Z", "finishedUtc": "2026-10-08T16:58:44.8633063Z", "evidenceSha256": "ac136676b9052f84eeef31d40180e5cd6d91f8516b1e67f08d8134a5addf2dc5", "outerLogSha256": "f3f115511da8d3e848d705f30789ee4a962ec0eb5709ebb7d7dfbd092e758ead" }, { "phase": "AndroidSmoke", "command": "pwsh -NoProfile -File tools/verify.ps1 -Phase AndroidSmoke -Milestone Final", "outerExit": 0, "rawExit": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "startedUtc": "2026-10-08T17:04:22.9959710Z", "finishedUtc": "2026-10-08T17:19:58.4677196Z", "evidenceSha256": "0c1cbcd64170c4e3747aa40ea9de51e36dabf9621b13a09f46c974f51a399122", "outerLogSha256": "50d4a2b0ee8dfe1891a02b236243aec79dec086cdad391f5d8b6bae66390fa1b" } ], "xmlActual": [ { "name": "editmode", "actualCaseCount": 103, "actualPassed": 103, "failed": 0, "skipped": 0, "inconclusive": 0, "sha256": "5f5f187799de24fba7ec9db705306c38c86e69d944d61fc56d09d4413a146516" }, { "name": "playmode", "actualCaseCount": 53, "actualPassed": 53, "failed": 0, "skipped": 0, "inconclusive": 0, "sha256": "e8b3c90b13f4887126ef6a7d03711d3c8f48e678b6d5034fa9463ee95427e826" } ], "androidActual": [ { "path": "android-final-evidence.json", "count": 226, "notPassed": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "apkSha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "sha256": "18ec499dd9d30cd0a00df16012e8e8021e0cbf77a97089611a3954ed5c00aa7b" }, { "path": "Fresh30/android-final-progression-evidence.json", "count": 151, "notPassed": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "apkSha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "sha256": "afe9adb99144f811761340586f27fdaff49d677c490f2bea8dad6a67afff066c" }, { "path": "FinalBoundary/android-final-boundary-evidence.json", "count": 37, "notPassed": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "apkSha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "sha256": "c3ea05c1b5d1041a3660af6063dfa21090e1d02857ac9e17d7cd72ade2bcf6eb" }, { "path": "RapidBoundary/android-final-rapid-evidence.json", "count": 39, "notPassed": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "apkSha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "sha256": "95a415c702a5f407a2fe86194ff22959a0584cb85328011ec83090b1ae5e42fe" }, { "path": "ContentBoundary/android-content-evidence.json", "count": 69, "notPassed": 0, "sourceCommit": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceCommitEnd": "3346eb559bdfba24332feb4d9be4b7104520233e", "sourceDirty": false, "sourceDirtyEnd": false, "apkSha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "sha256": "bf93139c8b749c10c2c562b20888320b586edeaebe2ba6f27ff5bf214755a9e7" } ], "childrenActualExitCodes": [ 0, 0, 0, 0 ], "freshSequentialActualSuccessChecks": 30, "freshSavePushCommands": 0, "apkCopies": { "paths": [ "artifacts/android/MagnetismHeroes.apk", "artifacts/android/Final/MagnetismHeroes.apk", "artifacts/verification/Final/Fresh30/installed-base.apk" ], "bytes": 57215937, "sha256": "DA533F235A9869E5A68F4A244AF9A89E34A8E6FB9E7C7F2F57D830939507B829", "allThreeIndependentlyMatched": true }, "voicePayload": { "actualApkDecodedRawReportPassed44": true, "actualRuntimeWavShaPcmFormatIndependentlyRecomputedMatched": 44, "apkRedeocodeByReviewer": false, "newRecordingOrListeningByReviewer": false }, "noticesZipExactHashes": { "NotoSansCJK-OFL.txt": "88f117575237307bdd86a17ef15e21790fc9a662fe4dfb103ca1ca077f0d9982", "TTS-Apache-2.0.txt": "7137274bab133744763a3906ace2a13844c2b34635136fc6d4454c25bfd76eda", "TTS-model-card.txt": "2157466302fcaf8e4979d0505aa4b648ad32468aff98b3e964046db05e574f3c" }, "forbiddenSourceToolCacheApkEntries": 0, "approvedModelFileHashesMatched": 25, "materialExactBytesAndValuesMatched": 31, "stageNonvisualDefinitionsPreserved": 30, "metadataShaNodesMatched": 264, "metadataShaRecordsExcludingApproved25": 239, "guidAndMetaShaMatched": 111, "latestEditorCaptureCount": 119, "galleryEditorCards": 8, "galleryActualAvdCards": 3, "galleryDeadLinks": 0, "galleryRemoteLinks": 0, "latestImagesPersonallyViewed": { "artifacts/verification/Final/Fresh30/stage-1-enter.png": "24a1fee6f57ed238976dde803184895fbe4900e3ed218fc3064c9743ef9c7e63", "artifacts/verification/Final/Fresh30/stage-10-next.png": "a17e8540e959fcad55fcde48ccee3654999647e59f7e245839e3872108776fc9", "artifacts/verification/Final/Fresh30/stage-20-next.png": "79cf0d0bef7671ebc92c2d1cf1f9b557633f7832425b6fc01809944ea8b0b3b3", "artifacts/verification/VisualUpgrade/FinalProduct/EditorCapture/world11-ten-one-group-tablet-orbitzoom.png": "31e8a98b730295f894f448a2a45e71d246c723354dece8d047013fc55495ebef", "artifacts/verification/VisualUpgrade/FinalProduct/EditorCapture/world21-single-resupplied-phone-orbitzoom.png": "91683df326dfe70f269b56d02cd2beedd93f6350fb0957995199b1a54c812dad" }, "previousWholeReviewImagesKeptAt": "artifacts\\verification\\VisualUpgrade\\BeforeHorizonFix\\final-review.json", "horizonImagesPersonallyViewed8KeptAt": ".dryforge\\reviews\\horizon-fix-conformance.json" }, "failureAndHistoryPreservation": { "latestFailedAttemptSource": "3346eb559bdfba24332feb4d9be4b7104520233e", "latestFailedAttemptActualExit": 1, "koreanObservation": "Fresh30 stage5의 adb shell wm size가 localhost5037 연결에서 약21초 뒤 timeout10060으로 실제 실패했다. 게임 판정/AVD 충돌로 원인을 단정하지 않는다.", "latestFailedAttemptArchivedFiles": 1257, "latestFailedAttemptArchiveHashesIndependentlyMatched": 1257, "previous83182ArchivedFiles": 2311, "previousArchiveHashesIndependentlyMatched": 2311, "retry": "같은 source/APK/732제품 바이트에서 AndroidSmoke만 실제 재실행했다. 새 Edit/Play/Build의 선행 통과를 재사용했으며 세 단계를 재실행했다고 주장하지 않는다. 최초 실패를 통과로 바꾸지 않았다.", "successfulSmokeStartedUtc": "2026-10-08T17:04:22.9959710Z", "successfulSmokeFinishedUtc": "2026-10-08T17:19:58.4677196Z", "olderPreviousFinal2517And113FailedAttemptPreservation": "이전 전체 독립 검토의 원문/해시 확인을 그대로 보존한다." }, "latestDocumentsRead": [ "docs/asset-register.md", "docs/content.md", "docs/engineering-notes.md", "docs/final-verification.md", "docs/handoff.md", "docs/operations.md", "docs/tracking/decisions/0005-hybrid-assets.md", "docs/tracking/status.md" ], "harnessRequiredFilesPresent": true, "reviewerInstructionsRead": [ "reviewer-prompt.md", "harness-review.md", "harness-format.md" ], "currentDocsReadRule": "기존 전체 검토에서 root/모듈 AGENTS와 적용 문서를 직접 읽었고 이번 8개 docs 전후 diff와 운영/결정/인수인계 현재 문맥 및 최신 원문을 다시 대조했다. 역사/범위 밖 문서 참조를 광범위 정리할 신규 요구로 만들지 않는다.", "evidenceSha256": { "artifacts\\verification\\VisualUpgrade\\FinalProduct\\completion.json": "dd898f331a31fb49545e9c3ee2d1c5b52adca97d907f5cff1b0c21b1e6d429fd", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\product-before.json": "c8232551e6b814b7eaadc343e95929ece779102b09daad3817253c847643213f", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\product-after.json": "c8232551e6b814b7eaadc343e95929ece779102b09daad3817253c847643213f", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\horizon-documentation-result.json": "816b1725a45bd0206c517a2a2a6b71153a9150d519152547872b3d3ce66a3a1b", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\horizon-documentation-audit.json": "0cc133ea881ccc9a96172edb40ad12ba7ed25ce00eec0b366119018e8aa6203d", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\documentation-final-evidence-audit.json": "14e62264a22f360f9afda94e1c8660507cda3b27c30d6f9916607889c2819e08", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\root-final-product-audit.json": "7f1c84d9fa0f593fe72e15e9d3970c6b10fcb329e71adda291cd07e1802a5b49", "artifacts\\verification\\VisualUpgrade\\FinalProduct\\index.html": "c959897dce94e24ea3d54198864bcc49dcdc58965aac739930920e26194d79cc", "artifacts\\verification\\Final\\VoicePayload\\apk-voice-payload.json": "a3c1fc9e0ef0170b3fcb60170ae4ca5b9ec640b644fd1f2b00fea591bdc28650", "SourceAssets\\Models\\Heroes\\active-adoption.json": "3447de26a676872a4f1527dea9c0c642c90cc690569323f3e19554c31ea99cb5", "SourceAssets\\Models\\Meadow\\active-adoption.json": "8d77a7fce5a847af64bbca8cb54d0997ab728ff5ca8bf0a9b6949f1df233b6b4" }, "nextGate": "검토 승인·차단0. 최종 제품 사용자 승인과 dev 통합/원격 push는 이 리뷰가 수행하거나 대체하지 않는다." }