39 KiB
Find-Word v0.2.3 구현·검증 결과
작성일: 2026-10-14 UTC. worktree /home/hermes/worktrees/find-word-v0.2.3, branch feat/v0.2.3.
기준 HEAD c92660b514f7af8eb556d3fa5c0fc80e4bdd4cf5. 지정된 TASK/ACCEPTANCE/AMBIENCE-SOURCES를 먼저 읽고 기존 코드·테스트·문서를 확인했다.
Git commit/push/merge/tag, 외부 배포, secrets 사용은 하지 않았다. 로컬 production preview만 사용했다. 정확한 credit **Designed by OZ at Heat-T Medical Inc.**와 private/UNLICENSED 프로젝트 권리를 보존했다. 제3자 현장음은 각각의 라이선스를 유지한다.
현재 최종 상태: privacy excerpt 구현/재생성 완료, ASR zero-segment acceptance 미달. 단위 123 통과 / 1 실패이며 실패는 새 ASR acceptance다. lint/build·Python 36개·sandboxed Chrome 30개 PASS, npm audit 0건. 최종 Chrome 결과와 상세 근거는 맨 아래 최종 privacy excerpt refinement 절에 있다. 앞선 구현/독립 리뷰의 기록은 당시 결과로 보존하며 최신 acceptance 성공으로 오인하지 않는다.
최초 구현 내용 (아래 리뷰 수정 내역으로 보완)
- 정확히 세 개의 서로 다른 문제/단어를 한 단계에서 출제한다. 시작 단계 1~5 선택, mixed 선택/입력/선택, 진행률/안내/분모 3문항, 정상 완료→다음 단계의 새 3문항, 5단계 재도전과 홈 복귀를 구현했다.
- SNR을 −12~+12 dB, 1 dB 눈금으로 직접 설정한다. 범위 밖 값은 clamp, NaN/Infinity는 단계 기본값으로 복구한다. 변경은 현재 재청취·미응답 문항·이후 라운드에 적용한다. 재생 중 gain을 바꾸지 않는다. 다음 단계도 수동 값은 유지하고 홈 복귀 시 수동 override를 지운다. 시작 단계/모드/환경/전체 음량은 홈 설정으로 유지한다.
- ready/loading/playing/answer/feedback에서
문제 풀이 종료가 가능하다. token 무효화→엔진 정지→결과 전환으로 지연 콜백을 차단한다. 응답 수·정답 수·실제 응답 분모를 표시하고 무응답을 오답으로 세지 않는다. - 여덟 고유 실제 현장 녹음을 fetch/decode/loop한다. 절차적 잡음 합성 코드는 제거했다.
101개 음성 및 여덟 배경은 모두 same-origin
?v=0.2.3정적 요청이다. 런타임 외부 API/TTS/추적은 없다. - 음성과 배경을 각각 RMS .03으로 정규화하고 상대 gain
10^(dB/20)을 적용한다. 안내/목표/배경의 피크 합에 공통 gain을 적용해 최악 합계 peak ≤ .8을 유지한다. master 음량은 그 뒤 공통 적용되므로 SNR을 보존한다. 배경은 목표 ended에서 함께 정리한다. - HTTP/decode/준비 15초 timeout/재생 길이+5초 timeout/abort 후 한국어 안내와 재시도를 유지한다.
- CHANGELOG 생성, package/lock/HTML/UI/자산 버전/README/설계/배포/오디오/단어/권리 문서를 0.2.3에 맞췄다. 상세 한국어 설계 주석을 수정 코드의 모듈·함수·클래스·상태/매개변수·경합/수치 계산에 추가했다.
RED → GREEN 원문
각 동작/회귀는 테스트를 먼저 작성·실행한 뒤 구현했다. 아래 RED의 종료 코드는 1, GREEN은 0이다.
-t로 좁힌 실행의 skipped는 필터 제외이며 최종 전체 실행은 skip 0이다. 실패 원문을 성공 로그로 대체하지 않았다.
| 계약/회귀 | RED → GREEN | 원문 |
|---|---|---|
| 세 문항/같은 시작 단계/혼합/점수 | 기존 10문항·자동 단계에서 3 실패 → 9 통과 | 01 RED, 01 GREEN |
| SNR 정규화/미응답 전파/전 단계 종료/지연 이벤트 | 누락 reducer action 등 7 실패 → 15 통과 | 02 RED, 02 GREEN |
| 시작 단계/수동 SNR/다음 라운드/5단계 경계/중도 결과/UI 초기화 | 10 실패 → 18 통과 | 03 RED, 03 GREEN |
| 고유 녹음 URL/절차적 매개변수 제거/peak/SNR 수학 | 2 실패 → 콘텐츠 포함 19 통과 | 04 RED, 04 GREEN |
| 실제 배경 fetch/decode/loop/abort/timeout/재시도 | 전환 중 남은 합성 호출 및 누락 녹음 경로로 9 실패 → 11 통과 | 05 RED, 05 GREEN |
| Node 직접 import 회귀 | ERR_MODULE_NOT_FOUND → 101문장 import 통과 | 06 RED, 06 GREEN |
| 8개 배포 PCM/해시/출처/고지/루프 경계 | manifest ENOENT → 전수 통과 | 07 RED, 07 GREEN |
| 실제 FFmpeg 변환/재현/무음 거부/길이 제한 | 변환 모듈 없음 → Python 2 통과 | 변환 RED, 변환 GREEN |
| 재생 중 SNR 변경의 실제 청취 이력 | −10을 들었다고 잘못 기록 → 34 통과 | 08 RED, 08 GREEN |
| 버전/문서/변경 이력/기존 voice metadata | 이전 버전·누락 CHANGELOG → 50 통과 | 09 RED, 09 GREEN |
| 3문항의 환경 순환 회귀 | 3개 환경만 도달 → 8개 도달, 35 통과 | 10 RED, 10 GREEN |
| dist 현장음/manifest/notice 변조·누락·원본 혼입/고지 링크 | 5 실패 → 26 통과 | 11 RED, 11 GREEN |
| 누락 WAV의 SPA fallback | desktop/mobile 200 HTML → 양쪽 404, 4 통과 | 13 RED, 13 GREEN |
| 결과 화면의 잘못된 도움말 anchor | 없는 #howto 링크 노출 → 제거 | 15 RED, 15 GREEN |
| 새 설정의 터치 크기/카드 경계 | 양쪽 23px 높이 → 44px 이상, 2 통과 | 16 RED, 16 GREEN |
| 3문항의 보너스 안내 | 당시 40점 → 20점 안내; 리뷰에서 문항별 20점/합계 30점으로 재정정 | 17 RED, 17 GREEN |
| 모바일 select 선택값 잘림 | 360px에서 글자 폭 초과 → 중복 SNR을 아래 제어에 모음 | 21 RED, 21 GREEN |
| Chrome favicon 기본 404 | 내장 icon 없음/실제 콘솔 오류 → 내장 SVG | 19 RED, 19 GREEN |
추가 진단 기록도 보존했다. 01-round-sampling-regression.log의 96/100은 세 문항으로 줄인 뒤
기존 200 seed 표본이 작아진 테스트 회귀여서 1000 seed로 전체 100조합 도달성을 검사했다.
03-screen-duplicate-description-RED.log는 같은 SNR 설명을 중복 배치한 회귀를 잡았다.
05-playback-fixture-regression.log 뒤 mock AudioBuffer의 copyToChannel을 실제 복사처럼 보완했고
부동소수점 0.12000000000000001 비교를 근사 비교로 바꿨다. 실제 재생은 별도의 Chrome으로 검증한다.
12-lint-initial.log의 축소된 union 비교/fixture 타입 오류도 수정했다.
현장음 원본과 변환
지정된 원본 8개를 모두 사용했다. 대체 원본은 0개다. 여섯 기존 원본을 재사용했고 café는 HTTP 429의 Retry-After 600초 backoff 뒤 지정 직접 URL로 다운로드했다. rain도 지정 URL에서 받았다. 다운로드 기록, rain 기록.
원본 전수 검사는 전체 원본 SHA-256/bytes/ffprobe 정보와 FFmpeg 전체 디코드 8/8 성공, stderr 0을 기록한다. café 19,947,952 bytes, rain 91,187,572 bytes는 Commons primary 메타데이터의 크기와 일치한다. Commons API 근거, primary 페이지/권리 재확인.
python3 scripts/ambience_audio.py로 원본의 명시적 중간 구간을 선택해 전부 12초 / 24,000Hz / mono / PCM16으로 만들었다.
양끝 50ms 선형 fade, RMS 목표 .08, 최대 증폭 4배, peak ceiling .85 중 안전한 선형 gain을 적용했다.
저레벨 rain과 순간 peak가 큰 market은 제한 때문에 RMS 목표보다 낮다. 엔진은 재생 시 각각 다시 RMS 정규화한다.
양끝 PCM은 0, non-silent 8/8, 고유 출력 해시 8/8, 각 576,044 bytes, 합계 4,608,352 bytes다.
대형 OGG/MP3/FLAC 원본은 /tmp/findword-ambience-sources에만 있으며 Git/public/dist에 번들하지 않았다.
배포 자산 (public/ambience/) |
원본 구간 | RMS | peak | 출력 SHA-256 |
|---|---|---|---|---|
| street.wav | 35–47s | 0.07999756 | 0.39675903 | a8bffa201b174618955bc51b860167169125304811aabe2086b0bb35b06c3ae1 |
| mall.wav | 20–32s | 0.07999757 | 0.55468750 | 6e9171f549cacadfaeedd57a41c8e2a76b0e789f5c9a97af029a8d3558c9f145 |
| theater.wav | 45–57s | 0.07999757 | 0.49508667 | 2d6a444fb7874cdf6b2d8a741a69175299b112eb66834912c025437d8277d635 |
| department.wav | 90–102s | 0.07999758 | 0.47497559 | aa43f3d1d3e7c2b1f8ace24ecbda45d0ea3a031db941c39506dc6c1665b8efa7 |
| market.wav | 30–42s | 0.04922208 | 0.84997559 | 4287e971a12767f70da714e0c1aff30125268f9c3faf07ebfbcc0d2904f4a312 |
| subway.wav | 65–77s | 0.07999755 | 0.42529297 | 9faf70b68617d267b367a0f3692ed90015458543ab4b0844f6c704e6a724728f |
| cafe.wav | 120–132s | 0.07999759 | 0.39709473 | 8db06f3f09bbd8409573ba4874c7ccdd1e7e825c8a61989a4efe66206a66c2d2 |
| rain.wav | 180–192s | 0.01138463 | 0.10241699 | f4315084e820f742b0709de5bb0d1abd3d5af1730620e08c2948b70347356dd9 |
배포 manifest에 environment id/표시 이름, source page/direct URL, creator, license/license URL, attribution, 원본/출력 SHA-256, bytes/duration/RMS/peak, 실제 FFmpeg 버전과 변환 설정을 기록했다. AMBIENCE_NOTICES를 dist에 포함하고 UI에서 접근할 수 있다. 시장 파생 WAV는 CC BY-SA 4.0, 지하철은 CC BY 4.0, 나머지는 CC0/PD이며 출처·변경 고지를 보존했다. 프로젝트의 UNLICENSED를 이 녹음에 적용하지 않는다. 런타임 React/ReactDOM/scheduler의 기존 MIT 전문도 그대로 배포한다.
보존과 구체적 회귀 수정
- 101개 neural WAV 바이트/원문/해시 변경 0. voice manifest는 배포 version만 0.2.3으로 올리고
generatedForVersion: 0.1.1을 추가했으며 생성 시각·provider·voice·prosody·도구/실측값은 보존했다. - 기존 10 mechanic/100문장, 정답·오답 규칙·점수 공식·재청취·객관식/주관식/mixed·IME 보호를 유지했다.
- 과거 .agent 추적 파일 180개 모두 Git blob hash 동일. v0.1/v0.1.1 RESULT와 evidence 수정 0. 보존 검사.
- 짧아진 라운드 때문에 순환 환경이 street/mall/theater에만 갇히는 회귀를 seed 기반 환경 셔플로 수정했다.
- 환경 URL 모듈 추가로 Python 생성기의 Node 직접 import가 깨지는 회귀를 명시적
.ts경로로 수정했다. heardDb를 PLAY 시점에 기록해 재생 중 조절값이 과거 청취 이력/결과를 덮어쓰지 않게 했다.- 중복 SNR 설명, 결과 화면의 없는 도움말 anchor, 실제 라운드 보너스 상한 안내를 바로잡았다.
- Vite dev/preview의 누락 WAV HTML fallback을 차단하고 Nginx 인계에도
/ambience/404 규칙을 추가했다. - 모바일 최종 이미지에서 시작 단계 select의 긴 선택값 잘림을 찾아 글자 폭 검사로 재현하고, 중복 SNR 표기를 전용 제어로 모았다.
- 실제 Chrome의 기본
/favicon.ico404 콘솔 오류를 내장 SVG로 제거했다.
리뷰 전 검증 기록 (리뷰 수정 후 결과는 문서 하단)
환경: Node 26.7.0, npm 11.19.0, Python 3.11.16, FFmpeg 6.1.1-3ubuntu5, system Chrome 146.0.7680.80.
환경. Chrome sandbox 활성화, --no-sandbox 0개를 실행 중 process argv로 확인했다.
실행 sandbox 기록; 설정 계약 테스트도 통과했다.
| 검증 | 결과 | 원문 |
|---|---|---|
npm run lint |
PASS, ESLint + TypeScript strict, exit 0 | 22-lint |
npm test |
13 files / 94 passed, skip 0, exit 0; Python runner 포함 | 22-full-test |
python3 -m unittest discover -s tests/python -v |
20 passed, exit 0 (기존 neural 18 + 새 변환 2) | 18-python |
npm run build |
PASS, 101 voice + 8 ambience + 두 notice 검증, exit 0 | 22-build |
npm audit --json |
취약점 0 (info/low/moderate/high/critical 모두 0), exit 0 | audit JSON |
| 최종 sandboxed system Chrome desktop/mobile | 26 passed / 0 failed / 0 skipped, exit 0; 실제 재생·접근성·무외부 요청 검증 | 22-browser, machine-readable 결과 |
| 원본/배포 녹음 및 101개 voice 보존 | PASS | 원본, 보존 |
| 비밀정보 형식 검사 | 0 findings, 값 노출 없이 경로/개수만 기록 | scan |
git diff --check |
PASS | 최종 worktree 점검 |
브라우저는 1280×1000 desktop / 360×800 mobile에서 같은 production build를 사용한다. 실제 디코드한 109 WAV의 response hash/bytes/24kHz/mono/duration/RMS/peak를 전수 대조하고, 앱에서 여덟 환경을 실제 loop로 재생 후 정지했다. 혼합 모드 세 문항 완주/재청취/키보드, 4단계 시작→5단계 새 라운드, 수동 SNR 유지/재청취/홈 초기화, 재생 중 종료/응답 뒤 종료, intro/target/ambience 404 재시도, 누락 WAV의 HTML Accept 404, notice 원문 제공을 검사한다. 정상 흐름의 console/page errors·failed requests·외부 요청·axe violations가 모두 0이어야 통과한다. 브라우저 native audio 메서드를 관찰할 때 원래 메서드를 실행하며 가짜 decode/ended를 주입하지 않는다.
최종 캡처 8개와 실제 검사 JSON을 새 evidence에 보존했다. 모바일 게임/시작과 desktop 시작/결과의 레이아웃을 이미지로 확인했고, 결과 분모/현재 SNR/종료 버튼/고지 링크가 잘리지 않는다.
| 화면 | Desktop | Mobile |
|---|---|---|
| 시작 | PNG | PNG |
| 게임 | PNG | PNG |
| 정상 결과 | PNG | PNG |
| 중도 종료 | PNG | PNG |
실제 109 WAV 해시/디코드/레벨 및 오류 0 집계: desktop JSON, mobile JSON. 세 문항→다음 단계→중도 종료→홈·재청취의 실제 소스 시작/정지 및 네트워크 집계: desktop runtime, mobile runtime.
초기 browser suite 24/24 통과 후 console/requestfailed 검사를 강화해 missing favicon을 찾았다.
그 실패는 18-browser.log에 남기고, 최종 검증은 별도 로그로 구분했다. 오류를 숨기거나 예외 목록으로 제외하지 않았다.
404/잘못된 WAV 주입 테스트의 의도적 실패 응답은 정상 흐름의 오류 0 집계와 구분한다.
실제 검증의 한계와 인계
- Chrome은 실제 WAV를 디코드하고 실제 AudioContext/BufferSource를 실행했다. 헤드리스 자동 검증은 스피커/헤드폰의 물리 음압, 한국어 청감, 개인의 난이도나 임상 효과를 보증하지 않는다.
- 녹음 장면은 primary 출처 설명으로 확인했고 짧은 연속 구간의 포맷/신호/해시/루프를 검증했다. 사람이 여덟 구간을 직접 청취하여 음악·불필요하게 명료한 우연 대화가 없는지 판단하는 인수는 수행하지 않았다. 자동 검사를 인간 청취 인증으로 주장하지 않는다. 샘플과 provenance를 Neo가 검토할 수 있다.
- mobile은 system Chrome 360×800 viewport/touch emulation이다. 실제 Android/iOS 기기 및 Safari 검증은 별도다.
- SNR은 전체 버퍼 RMS에 대한 디지털 상대값이다. 현장음의 시간 변화 때문에 순간/주파수별 SNR은 다르다.
- 로컬
dist만 검증했다. production HTTPS/MIME/cache/서버 설정은 배포 후 Neo의 독립 검증 대상이다. - 사용자 지시대로 commit/push/merge/tag/deploy는 미실행이다. acceptance의 Neo 릴리스 항목은 완료로 표시하지 않았다. DEPLOYMENT에 feature push→main FF→annotated tag→fresh clone→commit-addressed 원자 배포/rollback 절차를 인계했다.
독립 리뷰 수정 — 2026-10-14
사용자가 요약한 두 독립 리뷰와 본 결과 문서를 읽고 release-hardening을 수행했다. 기존 uncommitted v0.2.3 작업을 이어서 수정했으며 commit/push/merge/tag/deploy는 하지 않았다. 새 실패 테스트를 먼저 실행하고 생산 코드/검증기를 수정했다. 이전 evidence 로그는 수정하지 않았다. 신규 기록은 모두 review-fixes/ 아래에 있다.
수정 내용과 동작
- 진행 막대는 답변 수가 아닌 현재 문항 1/3 → 2/3 → 3/3이다. 첫 재생·답변 전·피드백과 다음 라운드에서도 일관된다. 접근성 이름/값, native progress 위치, 실제 PNG 채움 픽셀까지 검사한다.
- 결과/README/설계/CHANGELOG의 점수 설명은 정답마다 단계×100점 + 연속 정답 보너스, 문항별 최대 20점, 라운드 합계 0+10+20=30점이다. 1단계 세 정답의 330점을 실제 UI 흐름으로 검증했다.
- 응답이 없으면 정답률은 — / 응답 없음이며 0%나 0/0을 보여 주지 않는다. 응답 없는 단계는 미진행이다. 중도 종료 제목은 문제 풀이를 중간에 종료했어요., 정상 결과는 **N단계 문제 풀이를 마쳤어요.**로 구분한다.
- 실제 Chrome RED에서
입력, 결과의만나요/최대등 어절 분리를 검출했다. 모드 설명과 결과 영역에 keep-all을 적용하고 줄바꿈을 허용했다. 320px/360px에서 어절 내부 Range 줄 분리와 요소/문서 overflow를 검사하며 시작·정상 결과·중도 결과 캡처를 남겼다. - README 현재 증거 경로를
.agent/evidence-v0.2.3/review-fixes/로 바로잡고 일본어 reducer 테스트 제목을 한국어로 바꿨다. - build verifier는 앱 콘텐츠의 10 patterns×10 words+intro로 정확한 101개 이름을 독립 구성한다. manifest 정확히 101개, 중복 없는 예상 inventory, dist/audio의 추가/누락 파일을 모두 검사한다. 양쪽 manifest와 디렉터리를 함께 비우기/축약/중복/이름 변경해도 실패하며 정상 사본은 통과한다.
- 승인 계획과 배포 manifest의
verifiedLocalSource및 모호한sourceDurationSeconds를 제거했다.expectedSourceSha256,sourceBytes,sourceVerification과 directUrl 바이트의 ffprobe format.duration인directMediaDurationSeconds를 보존한다. Freesound preview MP3의 길이와 primary 페이지 표시 길이를 혼동하지 않는다. 파생 WAV의duration/conversion.durationSeconds는 별도로 12초다. 기존 source-integrity 증거와 대조했다. - 생성기는 첫 변환 전에 여덟 원본 전부의 승인 해시/bytes를 확인한다. 불일치/누락/중복/잘못된 목록은 실패하고, 현재 파일 값으로 승인 계획을 덮어쓰지 않는다. 실제 원본 8개도 새 승인 필드로 재검증했다.
- 현장음 notice를 public/ambience/AMBIENCE_NOTICES.md로 옮겼다. 같은 파일시스템의 staging에서 8 WAV·manifest·notice와 실측 PCM을 전수 검사한 다음 Linux renameat2(RENAME_EXCHANGE) 한 번으로 교체한다. 최초 생성은 rename 한 번이다. overlay를 없애 stale 파일을 제거하고 정상/dangling symlink 출력을 거부한다. 모든 변환 위치의 실패/KeyboardInterrupt, manifest/notice 쓰기 실패, staged 변조, 교환 실패/미지원, commit 전 SIGTERM에서 이전 디렉터리를 보존한다. 실제 교환 도중 디렉터리 fd로 읽은 세 파일이 같은 세대인 것도 확인했다. UI 링크·build verifier·권리·배포·재현 문서를 함께 수정했다.
- 모든 배포 notice 항목에 creator, primary page URL, direct download URL, license URL, outputLicense, 명시적 Changes가 있어야 한다. 다른 항목에 공통 URL이 남아도 누락을 감추지 못한다. 8개 항목×6개 필드 제거와 public/dist 동시 metadata 변조를 build verifier에서 거부한다.
- CHANGELOG와 본 문서에 실제 수정/검증을 반영했다. 109 WAV 재생성 0 / 바이트 변경 0이다.
새 RED → GREEN 원문
| 계약 | RED | GREEN |
|---|---|---|
| 진행률·330점·보너스·무응답·종료/완료 문구·README | 01 RED | 01 GREEN-02: 27 통과 |
| 실제 desktop/mobile 진행률·320/360px 어절·overflow | 02 RED: 4 실패 | 02 GREEN: 4 통과 |
| manifest/폴더 동시 축약·추가/누락 | 03 RED | 03 GREEN |
| durable 승인 원본 메타데이터 | 04 RED | 04 GREEN |
| 첫 변환 전 전수 원본 검사 | 05 RED | 05 GREEN |
| staging·notice·symlink·검증·원자 교환·실패/중단 보존 | 06 RED | 06 GREEN |
| notice 동시 발행 경로/UI 링크/항목 내용 | 07 RED | 07 GREEN |
| 항목별 필수 notice 강제 | 08 RED | 08–09 GREEN: 27 통과 |
| manifest 사본 동시 출처/라이선스/변경 변조 | 09 RED | 08–09 GREEN |
RED 로그는 exit 1, 표에 연결한 GREEN은 exit 0이다. 필터 실행의 skipped는 최종 전체 실행과 구분한다.
01-ui-GREEN.log는 이름과 달리 exit 1인 중간 실행이다. 새 계약은 통과했지만 기존 통합 테스트의
이전 제목 regex가 남아 실패했고, 그것을 고친 01-ui-GREEN-02.log가 실제 GREEN이다. 실패 로그도 보존했다.
초기 RED/GREEN browser PNG를 사후 픽셀 분석한 RED / GREEN도 보존했다. desktop 1096px 막대는 365→731→1096px, mobile 320px 막대는 107→213→320px 채워졌다. 같은 픽셀 검사를 최종 브라우저 테스트에도 넣었다. 추가 동시 읽기/미지원 교환 검증은 10-atomic-additional에 있다.
리뷰 수정 후 전체 검증
| 실행 | 실제 결과 | 원문 |
|---|---|---|
| npm run lint | PASS, exit 0 | lint |
| npm test | 13 files / 118 passed, skip 0, exit 0 | unit |
| python3 -m unittest discover -s tests/python -v | 32 passed (neural 18 + ambience 14), exit 0 | Python |
| npm run build | PASS, 101 voice + 8 ambience + runtime/ambience notices, exit 0 | build |
| npm audit --json | 취약점 0, exit 0 | audit |
| sandboxed system Chrome desktop/mobile | 30 passed / 0 failed / 0 skipped / 0 flaky, 4.0분, exit 0 | browser log, JSON |
보존 검사: 리뷰 시작 시점의 WAV 109개와 이전 .agent 파일
268개 모두 해시 동일하다. Git 추적된 v0.1/v0.1.1 .agent 파일 180개도 HEAD와 동일하다.
원본 재확인: 승인 원본 8개와 배포 bundle을 검증했고 변환은 호출하지 않았다.
Chrome 146.0.7680.80, desktop 1280×1000/mobile 360×800에 추가 320px/360px copy 검사를 수행했다.
실행 중인 이 테스트의 Chrome 프로세스 20개에 --no-sandbox가 없음을 실제 process 기록으로 확인했다.
원래 AudioContext/BufferSource를 실행한 109 WAV 해시·decode 검사와 8개 실제 ambience loop, 오류 재시도,
키보드/axe/외부 요청/콘솔 검사에 새 진행률 픽셀·한국어 어절 검사를 더했다.
desktop 오디오,
mobile 오디오,
desktop runtime,
mobile runtime.
| 최종 화면 | Desktop | Mobile |
|---|---|---|
| 시작 | PNG | PNG |
| 게임 | PNG | PNG |
| 330점 정상 결과 | PNG | PNG |
| 무응답 중도 종료 | PNG | PNG |
리뷰 후에도 남는 한계
사람이 여덟 현장음 구간을 청취하여 음악/우연 대화와 적절성을 판단하는 인수는 수행하지 않았다. 자동 PCM/Chrome 재생 검증을 인간 청취 승인으로 주장하지 않는다. mobile은 Chrome viewport/touch emulation이며 실제 Android/iOS/Safari, 물리적 음압 또는 임상 효과 검증은 아니다.
원자 commit 전 실패/중단은 이전 디렉터리를 보존하며 commit 뒤에는 완성된 새 트리가 공개된다. 강제 kill은 숨은 stage를 남길 수 있다. 전원 손실 내구성이나 여러 HTTP 요청에 걸친 snapshot 격리는 검증하지 않았다. 로컬 build/preview만 확인했으며 사용자 지시대로 Git commit/push/merge/tag 및 배포는 하지 않았다.
최종 privacy excerpt refinement — 2026-10-14
요청한 ASR-empty 조건은 아직 충족하지 못했다. 지정된 새 구간과 provenance, generator,
전체 원자 재생성은 반영했지만 최종 normalized WAV의 ASR에 market/cafe candidate segments가 남았다.
해당 acceptance test를 완화하거나 skip하지 않았으며 현재 npm test는 123 통과 / 1 실패다.
정확한 이전 ASR 설정이 제공되지 않아 Neo의 scan과 동등한 방법을 재현했다고 주장하지 않는다.
commit/push/merge/tag/deploy는 하지 않았다.
변경과 원자 재생성
.agent/AMBIENCE-SOURCES-v0.2.3.json의 8개 항목에selectedSegmentStartSeconds를 추가했다. street=35, mall=36, theater=45, department=90, market=60, subway=65, cafe=180, rain=180. 원본 hash/bytes/직접 미디어 길이/권리 정보는 바꾸지 않았다. generator는 별도 시작점 map을 제거하고 계획 값을 읽는다. 누락/비수치/bool/비유한값/음수/12초 범위 초과는 첫 변환 전에 실패한다.- 임의의 fractional start와 정확한 source 끝 경계를 주는 테스트로 hidden hardcoded map이 없음을 확인한다. 성공/실패 시 계획을 변경하지 않고 manifest의 선택값/실제 conversion 시작점/notice 구간이 일치해야 한다. build verifier는 public/dist manifest와 notice를 함께 변조한 시작점·길이도 거부한다.
- 첫 변환 전에 8개 원본 SHA-256·bytes·ffprobe duration을 전수 대조했고 generator의 preflight도 다시 수행했다. 같은 파일시스템 staging에서 전체 8 WAV·manifest·notice를 검증한 뒤 원자 디렉터리 교환했다. 재생성 실측, 성공 로그.
- 실제 Ogg 입력 seek에서 market은 287,958, cafe는 287,809 frame으로 짧아져 최초 생성이 중단됐다.
output-side seek 재시도만으로 cafe는 해결되지 않았다. 각 실패와 기존 bundle 보존을 남겼다.
최종 fallback은 처음부터 디코드한 24kHz PCM에서 승인 시작 sample부터 288,000개를 선택하고
sample 수로 output PTS를 재설정한다. 패딩/시간 변형 없이 실제
seekMethod를 manifest에 기록한다. 진짜 원본 부족은 여전히 거부한다. 진단, 추가 진단. - 기존 입력 seek가 완전한 다섯 WAV는 기존 byte를 재현했다. 모든 최종 WAV는 12초/24kHz/mono/PCM16, 576,044 bytes이며 양끝 50ms fade와 동일 bounded normalization을 유지한다.
| 최종 자산 | 원본 구간 | RMS | peak | SHA-256 |
|---|---|---|---|---|
| street.wav | 35–47s | 0.07999756 | 0.39675903 | a8bffa201b174618955bc51b860167169125304811aabe2086b0bb35b06c3ae1 |
| mall.wav | 36–48s | 0.07999755 | 0.71917725 | 680a769940c08f0d12c6c954c08366598dd8b5745e276f39c82b10d1a88261a1 |
| theater.wav | 45–57s | 0.07999757 | 0.49508667 | 2d6a444fb7874cdf6b2d8a741a69175299b112eb66834912c025437d8277d635 |
| department.wav | 90–102s | 0.07999758 | 0.47497559 | aa43f3d1d3e7c2b1f8ace24ecbda45d0ea3a031db941c39506dc6c1665b8efa7 |
| market.wav | 60–72s | 0.07999756 | 0.50723267 | 7a7a980845a4aade2a7e8a108eae746220a4688e92792ee93d3deb76b2a762f6 |
| subway.wav | 65–77s | 0.07999755 | 0.42529297 | 9faf70b68617d267b367a0f3692ed90015458543ab4b0844f6c704e6a724728f |
| cafe.wav | 180–192s | 0.07999757 | 0.44708252 | 802a956e91b85a2fdd0e1f161d75bfada7a53499bcb57ba7f578411480ded216 |
| rain.wav | 180–192s | 0.01138463 | 0.10241699 | f4315084e820f742b0709de5bb0d1abd3d5af1730620e08c2948b70347356dd9 |
위 표가 최신 바이트다. 문서 상단의 최초 구현 표와 앞선 리뷰 기록은 당시 값으로 그대로 보존했다.
ASR 증거와 미충족 조건
final-asr.json은 정확한 최종 8 WAV 전수 검사다.
faster-whisper 1.2.1, Systran faster-whisper-tiny multilingual revision
d90ca5fe260221311c53c58e660288d3deb8d356, CPU int8/4 threads, beam 5, random seed 0,
자동 language detection, package 기본 Silero VAD/decoding threshold를 사용했다.
모델/VAD 파일 해시·의존성 버전·전체 설정·변환 옵션·각 WAV/source hash와 반환 segment/info를 보존했다.
VAD의 무한대 기본 옵션은 JSON 호환 {"nonFiniteFloat":"Infinity"}로 의미를 명시해 저장했다.
| 환경 | VAD 활성 최종 segment 수 | 별도 VAD 미사용 segment 수 |
|---|---|---|
| street | 0 | 0 |
| mall | 0 | 1 |
| theater | 0 | 1 |
| department | 0 | 1 |
| market | 3 | 1 |
| subway | 0 | 1 |
| cafe | 1 | 1 |
| rain | 0 | 1 |
mall은 비었지만 **market 3개, cafe 1개가 남아 requiredEmptyPassed: false**다.
별도 VAD 미사용 결과는 세 변경 구간 모두에서 text가 나왔다.
VAD 비교는 방법의 영향을 확인하기 위한 추가 검사이며 이전 설정과 같다는 증거는 없다.
threshold 튜닝이나 반환 segment 삭제로 조건을 충족시키지 않았다. 원본 구간을 검사한 scan의 빈 결과를
정규화된 최종 WAV의 빈 결과로 치환하지 않는다. 정확한 Neo 명령/설정 확인을 요청했으며 최종 파생본 재검토가 필요하다.
Tiny-model ASR은 screening signal일 뿐, 사람의 청취 인수나 법적/개인정보 clearance가 아니다. 빈 segment도 말소리/음악/개인 대화의 부재를 증명하지 않으며 출력 text/language도 환각일 수 있다. 충실한 transcript나 실제 화자의 발언이라고 주장하지 않는다. 사람의 최종 청취 인수는 미실행이다.
기존 후보 scan과
기존 파생본 ASR을 /tmp 원문 그대로 보존했다.
provenance는 원래 경로·크기·hash·수정 시각,
Neo 제공이라는 맥락, 당시 계획/manifest와의 연관을 기록한다. raw JSON 자체에는 모델 revision/decoding 설정/
입력 hash가 없어 독립적으로 검증한 연결이라고 주장하지 않는다. 휴리스틱 text를 편집하거나 전사로 확정하지 않았다.
새 RED/GREEN과 실패 기록
모든 새 기록은 evidence-v0.2.3/privacy-screening/에 있다. 이전 로그를 덮어쓰지 않았다.
| 계약/실행 | RED/실패 | GREEN/현재 결과 |
|---|---|---|
| 계획 provenance·manifest·notice·build 변조 | 01 RED: 4 실패 | 11 GREEN: 관련 24 통과 |
| plan 직접 사용·immutability·범위 검사 | 02 RED | 02 GREEN: 17 통과 |
| served manifest·notice·plan 일치 | 03 browser RED: desktop/mobile 실패 | 아래 전체 Chrome 결과 |
| ASR/바이트 보존 evidence 계약 | 04 RED | 보존 PASS; ASR-empty는 여전히 FAIL |
| 짧은 seek와 full decode fallback | 06 RED, 08 RED | 08 GREEN |
| 실제 변환의 짧은 PCM | 05 실패, 07 실패 | 09 성공 |
| ASR exact results·zero-segment 조건 | 10 ungated 실패, 13 criterion RED | 16 VAD 결과: criterion FAIL |
14-final-asr-vad.log는 ASR을 완료했지만 VAD 기본 Infinity를 strict JSON으로 저장하다 실패한 중간 실행이다.
그 로그·초기 스크립트·빈 출력 artifact도 보존하고, tagged value 직렬화로 다시 실행한 16번 결과가 최종 JSON이다.
ASR가 실패한 사실과 JSON 기록 문제를 분리한다.
최종 검증과 보존
| 검사 | 실제 결과 | 근거 |
|---|---|---|
| lint | PASS | 18-final-lint |
| 모든 unit tests | 123 PASS / 1 FAIL, skip 0; 유일한 실패는 ASR-empty acceptance | 17-unit |
| 모든 Python tests | 36 PASS, skip 0 | 12-python |
| build | PASS, 101 voice + 8 ambience 및 notices | 12-build |
| npm audit | 취약점 0, exit 0 | audit JSON |
보존 전수 검사: 101 voice + 다섯 ambience WAV 바이트 동일,
변경 WAV는 mall/market/cafe뿐이다. 시작 당시 399 .agent 파일 중 요청으로 갱신한 plan/RESULT를 제외한
397개는 SHA-256 동일하다. HEAD에 추적된 과거 .agent 180개도 Git blob hash가 같다.
계획/manifest/notice/RESULT의 변경 전 사본과 모든 새 실패/성공 로그를 별도로 보존했다.
최종 sandboxed system Chrome 30 PASS / 0 FAIL / 0 SKIP / 0 FLAKY, 4.0분:
실행 로그,
JSON 결과.
Chrome 146.0.7680.80, desktop 1280×1000 / mobile 360×800 touch emulation에서
최종 served manifest/notice의 승인 구간을 대조하고 109개 WAV response hash·실제 decode·RMS·peak를 확인했다.
desktop 무결성,
mobile 무결성.
SHA-256/bytes는 정확히 일치하며 Chrome float decode와 PCM/32768 실측 RMS·peak의 차이는
독립 대조에서 PCM16 한 step 이내다.
두 기기의 정상 요청에서 외부 요청/console/page 오류/failed request는 모두 0이다.
실제 8 ambience loop·재시도·UI·axe 검증과 PNG는 새 browser-final/ 아래 보존했다.
이 suite runner의 Chrome 자손 process 21개에서 --no-sandbox token이 없음을
process 근거로 확인했다.
인계: 요청한 세 시작점은 구현했으나 market/cafe의 ASR-empty 요구가 미충족이므로 최종 인수 완료가 아니다. 정확한 이전 ASR 설정/명령을 확보해 방법 차이를 확인하고 최종 WAV를 검토해야 한다. 기본 threshold와 반환 결과를 조작하지 않았다. 사람의 청취 인수·법적/privacy clearance는 수행하지 않았고, 원격 전송·Git commit/push/merge/tag/deploy도 하지 않았다. 역사 evidence와 보호 WAV는 그대로다.