# Find-Word v0.2.5 독립 리뷰 수정 결과 2026-10-14 UTC · `/home/hermes/worktrees/find-word-v0.2.5` · `fix/v0.2.5-ambience-loudness`. HEAD `812540c7438639f25b886cfd620201d92de15362` 유지. **commit/push/merge/tag/deploy 미실행.** ## 릴리스 판정: 차단 정규화 결함은 strict TDD로 수정했다. 전용 **FFmpeg `ebur128=peak=true`**가 릴리스 수용 계기이며, 8개 exact 최종 WAV 모두 **−32.5 LUFS**, spread **0.0 LU**, 최대 true peak **−6.2 dBTP**다. 독립 **pyloudnorm 0.2.0 / soundfile 0.13.1**도 **−32.6062~−32.5291 LUFS**, spread **0.0771547792 LU**로 목표 ±0.2 LU / spread≤0.4 LU를 통과했다. loudnorm input_i를 수용 계기로 사용하는 주장은 철회했다. 그러나 같은 faster-whisper/VAD 설정으로 새 바이트를 검사했을 때 **market 1개 segment**가 반환되었다. **requiredEmptyPassed=false**이므로 릴리스를 중단한다. `npm test`도 **143 통과 / 1 실패**이며, 실패하는 테스트는 새 exact-WAV ASR 결과에 `requiredEmptyPassed=true`를 요구한다. 조건을 면제하지 않았다. - exact market WAV SHA-256: `7178307c48c192ac396dcd3c880c377bf56b45e829b459b1feca9f986437e632` - 보존한 원본 구간: 24–36초. ASR 반환 구간: **10.45–12.45초**. 반환 끝 시각도 수정하지 않았다. - 후보 텍스트: ` Let's go, let's go, let's go.` (검증된 전사가 아님) - mall/cafe 및 다른 5개는 segment 0개. market을 포함한 필수 3개 전부 empty 조건은 미충족. - [실패 원문](evidence-v0.2.5/review-fixes/final-asr.json), [실행 로그](evidence-v0.2.5/review-fixes/08-asr.log), [현재 unit 실패](evidence-v0.2.5/review-fixes/15-unit.log). 설정/threshold/모델/선택 구간을 바꾸거나 반환 segment를 삭제하지 않았다. `humanListeningAcceptance=false`, `legalPrivacyClearance=false`다. 이전 Oz 승인은 당시 v0.2.3 exact WAV에 한정된다. ASR의 후보 텍스트가 실제 발화를 입증한다고 주장하지 않으며, 이를 이유로 필수 gate를 면제하지도 않는다. ## 거부된 역사와 불변 보존 독립 리뷰 결과를 적용했다. 이전 loudnorm input_i는 spread **0.01 LU**를 보고했지만 같은 WAV의 전용 FFmpeg ebur128은 **2.0 LU**, 별도 pyloudnorm 0.2.0은 **1.925 LU**였다. 당시 정규화 결과는 릴리스 조건 실패다. 계기 차이를 진단값으로만 분류하고 ebur128 equality assertion을 제거한 판단은 철회했다. 이전 [RESULT 사본](evidence-v0.2.5/review-fixes/rejected-RESULT-v0.2.5.md), [당시 bundle](evidence-v0.2.5/review-fixes/rejected-loudnorm-bundle/), [당시 정규화 계획](evidence-v0.2.5/review-fixes/rejected-AMBIENCE-NORMALIZATION-v0.2.5.json)을 별도 보관했다. 기존 `.agent/evidence-v0.2.5` **150개 파일**은 전부 byte 동일하며 새 증거는 `review-fixes/`에만 추가했다. 상위 evidence의 GREEN/완료 표시는 거부된 당시 기준의 역사이며 현재 릴리스 통과를 뜻하지 않는다. 기존 불변 파일 **660개**, voice WAV **101개**, source **8개**의 hash/bytes와 원본 선택 구간·creator·license·attribution을 보존했다. source plan hash는 `3529c8534be204208ac504a0f4c1a69b312131f9bbff92aa9a3135d61d24db65`다. [history hash 목록](evidence-v0.2.5/review-fixes/history-sha256.json), [보존 검증 결과](evidence-v0.2.5/review-fixes/preservation.json). ## 구현과 manifest 1. 불변 source plan으로 모든 원본 SHA-256/bytes를 먼저 검증한다. 기존 seek 및 짧은 Ogg의 full decode/sample trim fallback, 12초/24kHz/mono와 양끝 50ms 선형 fade를 보존한다. 2. 정확한 faded f32 PCM을 새 `ebur128=peak=true` 프로세스로 측정한다. 3. 모든 환경의 공통 target **−32.5 LUFS**에서 `gain_db=target−measured_i`를 구한다. market의 입력 I=−26.4 LUFS, TP=−0.1 dBTP이므로 gain=−6.1 dB로 파형을 보존하며 내부 ceiling에 맞춘다. 4. 입력 true peak+gain이 **−6.2 dBTP**를 넘으면 변환 전에 실패한다. **`volume=dB:precision=double`만 적용**하고 FFmpeg `pcm_s16le`로 인코딩한다. 5. staged WAV를 새 ebur128 프로세스로 측정한다. 오차가 ±0.2 LU 밖일 때만 같은 원본 PCM에서 스칼라를 보정한다. 매번 peak를 사전 검사하며 최대 총 3회다. 비수렴/NaN/측정 실패/내부 peak 초과는 공개를 차단한다. 6. staging의 8 WAV·manifest·notice 전체를 검증하고 새 ebur128 측정으로 bundle spread≤0.4 LU 및 각 파일 target±0.2 LU/TP≤−6 dBTP를 강제한 뒤 단일 `renameat2(RENAME_EXCHANGE)`로 원자 교환한다. 이번 8개는 모두 첫 시도에 통과하여 보정 반복은 필요하지 않았다. 모든 sample에 동일 scalar만 적용하고 PCM16 반올림 오차만 남는다는 실제 FFmpeg fixture 검사, corrective gain/비수렴/peak 초과 검사가 있다. 실패하면 기존 공개 디렉터리를 보존하는 검증/쓰기/교환/중단 테스트도 유지했다. [manifest](../public/ambience/manifest.json)는 입력 ebur128 통계, faded PCM hash, 각 iteration의 정확한 gain/filter, 예측 peak/출력 통계, 최종 ebur128 통계, 목표/허용오차/spread/내부·릴리스 ceiling/최대 반복 수와 **FFmpeg 6.1.1-3ubuntu5** 버전을 기록한다. [정규화 계획](AMBIENCE-NORMALIZATION-v0.2.5.json)도 같은 계약이다. 12초, 288,000 frames, mono 24kHz PCM16, 576,044 bytes와 고유 hash/non-silence/양끝 0을 유지한다. | 환경 | 원본 시작 초 | gain dB | 최종 ebur128 LUFS | 최종 dBTP | | --- | --- | --- | --- | --- | | street | 35 | +3.2 | −32.5 | −10.2 | | mall | 36 | −10.4 | −32.5 | −12.2 | | theater | 45 | −6.8 | −32.5 | −16.1 | | department | 90 | −8.4 | −32.5 | −16.6 | | market | 24 | −6.1 | −32.5 | −6.2 | | subway | 65 | −16.0 | −32.5 | −16.2 | | cafe | 0 | −13.0 | −32.5 | −18.2 | | rain | 180 | +19.7 | −32.5 | −12.1 | [독립 ebur128 script/hash/raw summary/결과](evidence-v0.2.5/review-fixes/ebur128-results.json), [독립 pyloudnorm script/hash/version/결과](evidence-v0.2.5/review-fixes/pyloudnorm-results.json). 일반 npm test는 Python 표준 라이브러리와 FFmpeg만 사용하며 네트워크나 전역 pyloudnorm을 요구하지 않는다. 독립 meter는 별도 disposable venv에서 실행했다. 7개 의존성 전부 version/wheel SHA-256을 고정한 [lock과 재현 명령](evidence-v0.2.5/review-fixes/README.md#독립-pyloudnorm-재현)을 보존했다. 같은 원본에서 별도 임시 디렉터리로 두 번 재생성해 공개 WAV/notice/입력·iteration·최종 통계가 동일함을 확인했다. manifest 생성 시각만 제외한다. [재현 결과](evidence-v0.2.5/review-fixes/reproducibility.json). 재현성 범위는 기록한 도구 빌드/플랫폼이며 다른 FFmpeg 빌드의 byte 동일성을 주장하지 않는다. ## 런타임과 검증 기존 고정 배경 gain **G=0.4198884518664126**을 변경하지 않았다. 환경·SNR·intro 유무와 무관하다. voice/intro RMS .03, SNR은 voice 상대 gain만, master는 세 경로에 동일 적용한다. 보수적 상한 B=.55,V=.25,I=.20, SNR_MAX=12, intro=1.8, ceiling=.8을 유지한다. ```text G = 0.8 / (0.55 + 0.25*10^(12/20) + 0.20*1.8) |mix| ≤ master * G * (B + V*10^(12/20) + I*1.8) ≤ 0.8 ``` 101 voice×8 배경×25 SNR, **20,200개** 조합을 다시 검사했다. 새 background 최대 sample peak는 **0.471954345703125**, voice=0.2052977830171585, intro=0.14995422959327698이며, 실측 peak를 대입한 최악 합성 상계는 **0.6546804814413929 < .8**이다. 배경 gain 집합의 크기는 1이다. [전수 runtime/doc 검사](evidence-v0.2.5/review-fixes/21-docs-runtime.log). | 검사 | 결과 | 증거 | | --- | --- | --- | | ebur128 TDD | RED 2.0 LU 실패 → GREEN | [01](evidence-v0.2.5/review-fixes/01-ebur128-RED.log), [06](evidence-v0.2.5/review-fixes/06-ebur128-GREEN.log) | | 선형 gain/peak/비수렴 TDD | RED → 7 PASS | [02](evidence-v0.2.5/review-fixes/02-linear-RED.log), [04](evidence-v0.2.5/review-fixes/04-linear-GREEN.log) | | ASR gate TDD | RED, 실제 재검사도 FAIL 유지 | [03](evidence-v0.2.5/review-fixes/03-asr-gate-RED.log), [08](evidence-v0.2.5/review-fixes/08-asr.log) | | build manifest 계약 TDD | RED → 해당 39 PASS | [07](evidence-v0.2.5/review-fixes/07-build-contract-RED.log), [15](evidence-v0.2.5/review-fixes/15-unit.log) | | `npm run lint` | PASS | [14](evidence-v0.2.5/review-fixes/14-lint.log) | | `npm test` | **143 PASS / 1 FAIL (ASR)** | [15](evidence-v0.2.5/review-fixes/15-unit.log) | | 전체 Python | **47 PASS** | [11](evidence-v0.2.5/review-fixes/11-python.log) | | `npm run build` | PASS, 109 WAV 및 notice/manifest 일치 | [16](evidence-v0.2.5/review-fixes/16-build.log) | | `npm audit --json` | 취약점 0개 | [audit](evidence-v0.2.5/review-fixes/npm-audit.json) | | system Chrome desktop/mobile | **36 PASS**, skipped/flaky/unexpected=0 | [17](evidence-v0.2.5/review-fixes/17-browser.log), [summary](evidence-v0.2.5/review-fixes/browser-summary.json) | | 문서 변경 후 관련 계약/runtime 재검사 | **12 PASS** | [21](evidence-v0.2.5/review-fixes/21-docs-runtime.log) | | 불변 이력/원본/음성/public-dist | PASS | [20](evidence-v0.2.5/review-fixes/20-preservation.log) | Chrome은 system executable의 sandbox를 켜서 실행했다. 실제 프로세스 인자에 `--no-sandbox`가 없음을 [기록](evidence-v0.2.5/review-fixes/chrome-sandbox-final.json)했다. desktop/mobile은 viewport/touch emulation이며 물리 모바일/Safari 인증은 아니다. 109 WAV의 24/44.1/48/96kHz decode/peak와 8환경×3 SNR의 native GainNode, 3문항·종료·재청취·오류 재시도·무결성·axe·네트워크를 검증했다. 정상 흐름 console/page 오류·실패 요청·외부 요청·axe 위반은 모두 0개다. 의도적인 404/변조 오류는 정상 흐름 통계와 구분한다. 각 프로젝트 436개 리샘플 측정에서 최대 background=0.4879775941371918, voice=0.20585650454525403, intro=0.14999594059820148로 기존 보수적 상한 이하다. 두 프로젝트 모두 24개 GainNode 관측의 예약 gain은 0.4198884518664126, 실제 Float32 plateau는 0.4198884665966034로 동일하다. README/CHANGELOG/ARCHITECTURE/AUDIO_PROVENANCE/DEPLOYMENT/정규화 계획/manifest/테스트 한국어 주석을 현재 계기와 **릴리스 차단 상태**로 수정했다. 제품/query 버전 0.2.5, 정확한 `Designed by OZ at Heat-T Medical Inc.` 및 제3자 notice/market CC BY-SA 4.0은 유지한다. 원래 TASK/ACCEPTANCE와 이전 릴리스 기록은 역사로 보존하며 이번 사용자 지시가 수용 계기와 gate를 정한다. 현재 수정본의 loudness 통과를 전체 릴리스 통과로 확대하지 않는다.