feat: release Find-Word v0.2.3
This commit is contained in:
+33
-16
@@ -1,8 +1,8 @@
|
||||
# Find-Word v0.1.1 설계
|
||||
# Find-Word v0.2.3 설계
|
||||
|
||||
## 데이터와 출제
|
||||
|
||||
`src/content.ts`는 패턴, 질문, 단어, 오답 규칙, 배경 프리셋, 상대 dB를 서로 다른
|
||||
`src/content.ts`는 패턴, 질문, 단어, 오답 규칙, 현장음 URL, 상대 dB를 서로 다른
|
||||
배열로 보관한다. `renderSentence`가 각 패턴의 `{word}`를 정답으로,
|
||||
`{distractor1}`·`{distractor2}`를 해당 보기의 오답으로 채운다. 같은 함수를
|
||||
음성 생성기도 사용하며 런타임 문장과 WAV의 대응은 manifest 테스트가 검증한다.
|
||||
@@ -29,8 +29,9 @@
|
||||
목표 반복 횟수, 취소·조건·방향 단서와 질문 의도를 검증한다.
|
||||
|
||||
`src/game.ts`의 `createQuestions`는 seed 기반 PRNG와 Fisher–Yates로
|
||||
유형·단어·정답 위치를 섞는다. 한 세션에서 유형과 정답 단어는 각각 한 번씩
|
||||
나온다. 100개 문장 조합에 응답 방식·환경·난이도를 독립적으로 결합한다.
|
||||
유형·단어·정답 위치를 섞는다. 한 라운드는 3문항이며 유형과 정답 단어가 중복되지 않는다. 시작 단계는 1~5로
|
||||
정규화하며 세 문항에 같은 level/db를 적용한다. 혼합 모드는 선택/입력/선택이다.
|
||||
환경 순환은 seed로 여덟 곳을 섞어 세 곳을 선택한다. 100개 문장 조합에 응답 방식·환경·난이도를 독립적으로 결합한다.
|
||||
|
||||
오답의 `rule`은 `RULE_DIFFICULTY`에 연결된다. 음절 교체 1, 초성 교체 2,
|
||||
모음 교체 3, 받침 교체 4는 편집상 예상 혼동 순서이며 검증된 청각 척도가
|
||||
@@ -49,9 +50,23 @@ stateDiagram-v2
|
||||
answer --> loading: 다시 듣기
|
||||
answer --> feedback: ANSWER
|
||||
feedback --> ready: NEXT (다음 문제)
|
||||
feedback --> results: NEXT (마지막 문제)
|
||||
feedback --> results: NEXT (세 번째 문제)
|
||||
ready --> results: EXIT
|
||||
loading --> results: EXIT
|
||||
playing --> results: EXIT
|
||||
answer --> results: EXIT
|
||||
feedback --> results: EXIT
|
||||
```
|
||||
|
||||
정상 결과는 다음 단계(최대 5)의 새 라운드로 연결되며 중도 종료는 응답 수·정답 수를
|
||||
표시한 뒤 홈으로 연결된다. 무응답 정답률은 `— / 응답 없음`, 응답하지 않은 단계는 `미진행`으로 표시한다.
|
||||
중도 종료 제목과 현재 단계 완료 제목을 구분한다. 진행 막대는 답변 수가 아닌 현재 문항의 1/3, 2/3, 3/3이다.
|
||||
결과 단계는 모든 지연 이벤트를 무시한다.
|
||||
SNR은 −12~+12 dB 정수로 제한하고 NaN/Infinity는 단계 기본값으로 복구한다.
|
||||
수동 SNR은 재생 도중 현재 gain을 바꾸지 않고 현재 재청취/남은 문항/다음 라운드에
|
||||
적용한다. `heardDb`는 실제 재생 시작값을 보존해 결과를 정확히 기록한다. 홈은
|
||||
수동 SNR·답·입력·IME·토큰을 초기화하고 시작 단계·모드·환경·전체 음량은 유지한다.
|
||||
|
||||
허용되지 않은 이벤트는 동일 상태를 반환한다. 재생 전/중에는 채점할 수 없고,
|
||||
피드백 이후의 중복 답변·다음 클릭도 한 번만 반영된다. UI에서도 버튼 비활성화와
|
||||
동기 ref 잠금을 함께 사용한다. 세션 토큰으로 처음 화면 복귀·unmount 뒤 완료된
|
||||
@@ -63,7 +78,7 @@ Promise를 무시한다. 질문과 보기는 재생 완료 후 DOM에 생성되
|
||||
입력을 HTML로 해석하지 않는다.
|
||||
|
||||
점수는 정답 시 `100 × 단계 + 10 × min(연속 정답 - 1, 4)`이다. 오답은 0점,
|
||||
현재 연속 정답을 초기화한다. 최고 연속 정답과 난이도별 정답 수는 유지한다.
|
||||
현재 연속 정답을 초기화한다. 기존 공식의 cap은 40점이며 세 문항 라운드에서는 문항별 최대 20점, 라운드 합계 최대 30점(0 + 10 + 20)이다. 1단계 세 정답은 330점이다. 최고 연속 정답과 난이도별 정답 수는 유지한다.
|
||||
|
||||
## 오디오
|
||||
|
||||
@@ -73,26 +88,28 @@ Promise를 무시한다. 질문과 보기는 재생 완료 후 DOM에 생성되
|
||||
[AUDIO_PROVENANCE](AUDIO_PROVENANCE.md)에 있으며 앱은 provider에 연결하지 않는다.
|
||||
|
||||
`src/audio/dsp.ts`는 순수 수치 함수이며 장치가 없어도 테스트할 수 있다.
|
||||
정수 seed 잡음에 저역 통과 필터, 사인파, 진폭 변조를 조합하고 양 끝을 페이드한다.
|
||||
8개 프리셋은 실제 현장 녹음이 아니라 환경을 추상적으로 표현한 합성 신호다.
|
||||
8개 현장 녹음 WAV를 디코드해 재생한다. 각 12초, 24kHz mono PCM16이며 양끝
|
||||
50ms fade로 루프 접합 클릭을 줄인다. 절차적 잡음 합성 코드는 제거했다.
|
||||
|
||||
`src/audio/engine.ts`는 클릭 이벤트에서 AudioContext 생성·resume을 호출한 뒤
|
||||
같은 출처의 WAV를 로드한다. mono PCM을 decode하고 음성과 배경의 전체 버퍼
|
||||
RMS를 0.03으로 정규화한다. `gain = 10^(dB/20)`으로 목표 gain을 지정한다.
|
||||
RMS를 0.03으로 정규화한다. `gain = 10^(dB/20)`으로 목표/배경 비율을 지정한다. 정규화한 세 신호의 최대
|
||||
피크 합을 계산해 모든 경로를 공통 감쇠하므로 합계 peak ≤ 0.8이고 SNR이 유지된다.
|
||||
시간별·주파수별 청감이나 물리적 dB SPL을 보장하는 수치는 아니다.
|
||||
|
||||
`src/audio/assets.ts`는 음성 자산 버전과 URL 생성을 한 곳에서 관리한다.
|
||||
intro와 목표 100개 모두 `?v=0.1.1`을 붙여 동일 파일명에 남은 이전 캐시를
|
||||
intro·목표 100개·현장음 8개 모두 `?v=0.2.3`을 붙여 동일 파일명에 남은 이전 캐시를
|
||||
피한다. 파일을 다시 생성하면 제품 버전 유지 여부와 관계없이 자산 버전을
|
||||
갱신한다. 버전 확인을 위한 외부 요청이나 런타임 manifest 요청은 없다.
|
||||
|
||||
```text
|
||||
배경 BufferSource → 배경 Gain (1, 시작/끝 fade) ─┐
|
||||
목표 BufferSource → 음성 Gain (10^(dB/20)) ─────┼→ master Gain → destination
|
||||
안내 BufferSource → 안내 Gain (1.8 → 0.12) ─────┘
|
||||
배경 BufferSource → 배경 Gain (공통 감쇠, 시작/끝 fade) ─┐
|
||||
목표 BufferSource → 음성 Gain (공통 감쇠 × 10^(dB/20)) ─────┼→ master Gain → destination
|
||||
안내 BufferSource → 안내 Gain (공통 감쇠 × 1.8 → 0.12) ─────┘
|
||||
```
|
||||
|
||||
첫 문제에서는 웃음과 안내 음성을 낮추어 배경에 묻히게 한 후 목표 문장을
|
||||
배경 소스는 `loop=true`이며 목표 ended에서 즉시 stop/disconnect한다.
|
||||
각 라운드의 첫 문제에서는 웃음과 안내 음성을 낮추어 배경에 묻히게 한 후 목표 문장을
|
||||
재생한다. 이후에는 목표만 재생한다. 안내 도중 실패했으면 재시도 시 안내도
|
||||
다시 재생한다. 기본 master는 35%이며 음량 조절은 두 신호의 비율을 유지한다.
|
||||
|
||||
@@ -116,7 +133,7 @@ reduced motion에서는 파형이 움직이지 않는다. 오류는 role=alert
|
||||
## 검증 경계
|
||||
|
||||
Vitest는 실제 RED/GREEN으로 데이터·채점·상태·오디오 그래프·화면을 검증한다.
|
||||
Playwright는 production build와 실제 Chrome AudioContext로 두 크기의 10문제
|
||||
완주·재청취·오류 복구·axe 검사를 수행한다. 테스트 자동화는 한국어 발음의
|
||||
Playwright는 production build와 실제 Chrome AudioContext로 두 크기의 3문항
|
||||
완주·다음 단계·SNR·중도 종료·재청취·오류 복구·axe 검사를 수행한다. 테스트 자동화는 한국어 발음의
|
||||
자연스러움, 실제 사용자의 청각 난이도, 모바일 Safari의 장치별 정책까지
|
||||
증명하지 않으므로 인수 시 직접 청취를 추가한다.
|
||||
|
||||
+133
-6
@@ -1,4 +1,4 @@
|
||||
# Find-Word v0.1.1 오디오 출처와 재현
|
||||
# Find-Word v0.2.3 오디오 출처와 재현
|
||||
|
||||
## 포함 자산과 생성 설정
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
| --- | --- | --- | --- |
|
||||
| `public/audio/intro.wav` | Microsoft Edge online TTS neural 음성 | `src/content.ts`의 INTRO | 24kHz mono PCM16 WAV |
|
||||
| 목표 음성 100개 | 같은 provider·voice | 10 패턴 × 10 단어, `renderSentence` | 같은 WAV |
|
||||
| 8개 배경 환경 | 직접 작성한 결정론적 DSP | `ENVIRONMENTS`, 고정 seed | 브라우저 메모리에서 합성 |
|
||||
| 8개 배경 환경 | 공개 라이선스 실제 현장 녹음 | `public/ambience/manifest.json` | 12초·24kHz mono PCM16 WAV |
|
||||
| 화면 파형·S 캐릭터 | 직접 작성한 CSS | `App.tsx`, `styles.css` | CSS |
|
||||
|
||||
voice는 **`ko-KR-HyunsuMultilingualNeural`**, rate는 **`-6%`**, pitch는
|
||||
@@ -69,8 +69,8 @@ MP3를 24kHz mono signed 16-bit little-endian PCM으로 디코드한다. 파일
|
||||
|
||||
생성기와 독립 자산 테스트는 101개 파일의 원문·집합·SHA-256·bytes·duration,
|
||||
24kHz mono PCM16, 1–20초 길이, RMS > 100/32768, full-scale 미도달,
|
||||
총 48MiB 미만을 검사한다. 런타임 RMS 0.03과 최대 +6dB에서도 peak < 0.8을
|
||||
요구한다. 기존 앱은 Web Audio에서 배경·음성을 RMS 정규화한 뒤 상대 SNR을 적용한다.
|
||||
총 48MiB 미만을 검사한다. 기존 음성 단독 검사는 RMS 0.03과 +6dB에서 peak < 0.8을
|
||||
요구한다. 0.2.3의 사용자 최대 +12dB 혼합은 세 경로 공통 감쇠로 별도 검증한다. 앱은 Web Audio에서 배경·음성을 RMS 정규화한 뒤 상대 SNR을 적용한다.
|
||||
물리적 음압이나 주파수별 청감을 보정한 값은 아니다.
|
||||
|
||||
## 도구 라이선스와 서비스 조건
|
||||
@@ -99,5 +99,132 @@ MP3를 24kHz mono signed 16-bit little-endian PCM으로 디코드한다. 파일
|
||||
|
||||
자동 검증은 PCM 신호·무결성·재생 흐름을 확인한다. 한국어 발음, 유사 자모의
|
||||
구분, 웃음의 자연스러움과 실제 사용자의 난이도는 청취 평가가 필요하다.
|
||||
대표 샘플과 게임 내 소음 혼합 상태를 직접 들어 인수 판단한다. 배경은 장소를
|
||||
추상화한 합성 신호다. 이 게임의 수치는 임상 검증·치료·청력 판정용이 아니다.
|
||||
대표 샘플과 게임 내 소음 혼합 상태를 직접 들어 인수 판단한다. 배경은 실제 현장 녹음의 짧은 구간이다. 이 게임의 수치는 임상 검증·치료·청력 판정용이 아니다.
|
||||
|
||||
|
||||
## v0.2.3 현장 녹음 파생본
|
||||
|
||||
원본 선정 계약은 [.agent/AMBIENCE-SOURCES-v0.2.3.json](../.agent/AMBIENCE-SOURCES-v0.2.3.json),
|
||||
배포 바이트의 출처·직접 URL·저작자·라이선스·변환·SHA-256·bytes·duration·RMS·peak는
|
||||
[manifest](../public/ambience/manifest.json), 정확한 attribution과 변경 고지는
|
||||
[AMBIENCE_NOTICES](../public/ambience/AMBIENCE_NOTICES.md)에 있다. 이 고지는 dist에도 포함되고 UI에서 링크한다.
|
||||
여덟 원본 모두 서로 다른 현장 녹음이며 NC/ND 자산을 사용하지 않는다. 원본은 저장소/빌드에 포함하지 않는다.
|
||||
|
||||
| 환경 | 저작자 | 라이선스 | 원본 구간(초) |
|
||||
| --- | --- | --- | --- |
|
||||
| 길거리 | cori (Cori Samuel) | PD-author | 35–47 |
|
||||
| 쇼핑몰 | thore (Thore) | PD-author | 36–48 |
|
||||
| 극장 | ElevatorFan2020 | CC0 1.0 | 45–57 |
|
||||
| 백화점 | icmusic | CC0 1.0 | 90–102 |
|
||||
| 시장 | Marie Flutre | CC BY-SA 4.0 | 24–36 |
|
||||
| 지하철 | PascalHD | CC BY 4.0 | 65–77 |
|
||||
| 카페 | Marble Toast | CC0 1.0 | 0–12 |
|
||||
| 비 오는 거리 | Extemporalist | CC0 1.0 | 180–192 |
|
||||
|
||||
Commons primary 페이지/API와 Freesound primary 페이지의 라이선스 근거를 evidence에 보존한다.
|
||||
Freesound 두 원본은 지정된 preview MP3이다. 프로젝트의 비공개 라이선스를 제3자 녹음에
|
||||
적용하지 않으며, 시장 파생 WAV는 **CC BY-SA 4.0**으로 계속 공개·수정·재배포할 수 있다.
|
||||
지하철은 **CC BY 4.0**의 PascalHD credit·변경 고지·라이선스 링크를 유지한다.
|
||||
|
||||
재현: 검증한 원본 8개를 `/tmp/findword-ambience-sources`에 놓고
|
||||
`python3 scripts/ambience_audio.py`를 실행한다. 계획의 파일별 `selectedSegmentStartSeconds`에서 12초를 선택하고,
|
||||
FFmpeg로 mono 24kHz float PCM 디코드 후 양끝 50ms 선형 fade, RMS 목표 .08,
|
||||
최대 증폭 4배/peak .85 중 가장 작은 선형 gain을 적용한다. 마지막은 표준 44-byte
|
||||
WAV 헤더의 PCM16이다. 시간 변형·절차적 합성·원본 음성 대체는 없다.
|
||||
원본 SHA-256과 실측 FFmpeg 버전을 함께 기록하므로 같은 원본/도구로 재현 가능하다.
|
||||
|
||||
런타임은 음성/배경 각각 RMS .03 후 상대 gain `10^(dB/20)`을 적용한다. −12~+12 dB
|
||||
범위에서도 세 경로의 최악 피크 합을 공통 감쇠하여 최대 .8로 제한한다. 양끝 fade가
|
||||
있는 배경을 loop하고 목표 끝에서 정리한다. 전체 버퍼 RMS 기준이며 짧은 시간창별
|
||||
SNR이나 실제 음압을 보증하지 않는다. 원본 녹음의 우연한 사람 말소리는 환경의 일부다.
|
||||
자동 검사로 음악·개인 대화의 완전한 부재를 인증할 수 없으므로 사람의 최종 청취 검토가 필요하다.
|
||||
|
||||
기존 neural WAV 101개의 원문·해시는 v0.1.1 그대로다. 음성 manifest의 version은
|
||||
배포 버전 0.2.3, `generatedForVersion`은 0.1.1이며 원래 생성 시각·도구 정보는 보존한다.
|
||||
|
||||
|
||||
### 리뷰 후 출처 고정과 원자 발행
|
||||
|
||||
승인 계획의 `expectedSourceSha256`와 `sourceBytes`는 불변 입력이다. 생성기는 로컬 경로나
|
||||
현재 파일에서 이 승인값을 새로 기록하지 않으며, 여덟 원본의 해시·크기를 **첫 변환 전**에 모두 검사한다.
|
||||
한 원본이라도 다르거나 누락되면 실패한다. `sourceVerification`은 검증 상태·일자·방법·보존된 증거를 가리킨다.
|
||||
임시 경로를 담던 `verifiedLocalSource` 필드는 제거했다.
|
||||
|
||||
`directMediaDurationSeconds`는 **directUrl에서 받은 바로 그 바이트**의 ffprobe `format.duration`이다.
|
||||
Freesound 항목은 preview MP3의 길이이며 primary 페이지 원본 길이 또는 반올림한 표시 길이가 아니다.
|
||||
배포 manifest의 `duration`과 `conversion.durationSeconds`는 파생 WAV의 길이(12초),
|
||||
`selectedSegmentStartSeconds`는 파일별 불변 승인 시작점이며 생성기는 별도 hardcoded map 없이 이 값을 읽는다.
|
||||
`conversion.startSeconds`는 같은 값이어야 한다. 시작점은 유한한 0 이상 수이고, 시작점+12초가
|
||||
`directMediaDurationSeconds` 이하여야 한다. 누락·음수·NaN·Infinity·문자열·bool·범위 초과는 첫 변환 전에 거부한다. 원본 전체 디코드와 실제 수치는
|
||||
[보존된 source-integrity.json](../.agent/evidence-v0.2.3/source-integrity.json)에 있다.
|
||||
|
||||
생성기는 출력 폴더와 같은 부모의 `.ambience-stage-*/ready`에서 8 WAV·manifest·`AMBIENCE_NOTICES.md`를
|
||||
완성한다. 정확한 파일 집합, 고유 해시, 원본 계획, PCM 형식·길이·fade·RMS·peak,
|
||||
항목별 저작자/primary URL/direct URL/라이선스 링크/outputLicense/변경 설명을 다시 검사한다.
|
||||
존재하는 symlink 및 dangling symlink 출력을 모두 거부한다. Linux `renameat2(RENAME_EXCHANGE)` 한 번이 교체의
|
||||
commit 지점이며, 최초 생성은 같은 파일시스템의 rename 한 번이다. 지원하지 않는 환경에서는 실패한다.
|
||||
파일별 overlay를 하지 않으므로 오래된 파일이 남지 않고 고지도 음원과 같은 디렉터리로 교체된다.
|
||||
|
||||
commit 전 변환·쓰기·검증·교환 실패 또는 중단은 이전 디렉터리를 보존한다. syscall 이후에는 완성된 새 디렉터리가
|
||||
공개된 상태다. SIGKILL 등 강제 종료는 숨은 임시 디렉터리를 남길 수 있지만 부분 배포는 만들지 않는다.
|
||||
전원 손실에 대한 디스크 내구성이나 여러 HTTP 요청에 걸친 snapshot 격리를 주장하지 않는다.
|
||||
앞선 독립 리뷰에서는 기존 109 WAV를 재생성하지 않았다. 이후 아래 privacy refinement에서
|
||||
전체 현장음 bundle을 원자 재생성했으며 mall/market/cafe 3개만 바이트가 바뀌었다.
|
||||
**사람의 현장음 청취 인수는 미실행**이다.
|
||||
|
||||
|
||||
### 최종 privacy excerpt refinement
|
||||
|
||||
현재 선택은 **mall 36–48초, market 24–36초, cafe 0–12초**다. Neo가 동일한
|
||||
`scripts/ambience_audio.convert` 경로와 아래 ASR 설정으로 해시 고정 원본을 재검사해 제시한
|
||||
market/cafe 후보를 사용했다. 제공받은 재검사 설명은
|
||||
[selection-context.json](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/selection-context.json)에
|
||||
별도로 기록했으며, 원본 후보 결과를 최종 WAV 검사 결과로 대신하지 않았다.
|
||||
|
||||
승인 원본 8개의 SHA-256·bytes·ffprobe 길이를 먼저 대조하고 하드닝된 생성기로
|
||||
8 WAV·manifest·notice 전체를 staging/검증/원자 교환했다.
|
||||
[생성 실측 기록](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/regeneration.json)에
|
||||
현재 해시·RMS·peak·변환이 있다. 이번 재시도는 market/cafe 두 WAV만 변경했다.
|
||||
**101개 voice, 다섯 unaffected ambience, 기존 mall 36초 WAV는 모두 바이트 동일**하다.
|
||||
|
||||
일부 Ogg 구간은 FFmpeg timestamp/seek 때문에 12초보다 몇 프레임 짧게 출력된다.
|
||||
짧은 결과일 때만 처음부터 디코드한 24kHz PCM의 `round(start × 24000)`부터 정확한 288,000개
|
||||
sample을 선택하고 출력 PTS를 sample 수로 재설정한다. silent padding이나 time stretching은 없다.
|
||||
정말 원본이 짧으면 여전히 실패하며 `conversion.seekMethod`가 실제 경로를 기록한다.
|
||||
|
||||
[final-asr.json](../.agent/evidence-v0.2.3/privacy-screening/final-asr.json)은 정확한 현재 8 WAV를
|
||||
로컬 **faster-whisper 1.2.1, tiny multilingual, CPU int8, beam_size=5, best_of=5,
|
||||
기본 Silero VAD 활성화, condition_on_previous_text=true**로 검사한 원문이다.
|
||||
모델 revision `d90ca5fe260221311c53c58e660288d3deb8d356`, 모델/VAD 파일 해시,
|
||||
라이브러리 버전·전체 설정·각 입력 해시·반환 segment/info를 저장했다.
|
||||
이전 실패 실행과 모든 decoder/VAD 인자가 같은지 스크립트가 대조한다.
|
||||
**mall/market/cafe 각각 segment 0개, duration_after_vad=0.0, requiredEmptyPassed=true**다.
|
||||
다른 다섯 WAV도 segment 0개다. threshold 조절이나 반환 segment 삭제는 하지 않았다.
|
||||
테스트는 지정 시작점·true gate·VAD 설정·실제 WAV/manifest 해시와 아래 false 인수값을 함께 강제한다.
|
||||
|
||||
**humanListeningAcceptance=false, legalPrivacyClearance=false**를 유지한다.
|
||||
Tiny-model ASR은 screening signal일 뿐이며 빈 결과는 말소리·음악·개인 대화가 없음을 증명하지 않는다.
|
||||
출력 text/language도 환각일 수 있고 충실한 전사나 화자 식별로 주장하지 않는다.
|
||||
독립적인 사람 청취 인증은 수행하지 않았다. 다만 제품 소유자 Oz는 2026-10-14 제공된
|
||||
최종 WAV 8개 청취 검수 묶음과 명시된 자동 검사 한계를 기준으로 현재 자산 그대로 릴리스를
|
||||
진행하도록 승인했다. 이 승인은 제3자의 법적/privacy clearance를 대신하지 않는다.
|
||||
|
||||
이전 market 60–72초/cafe 180–192초 실행은 market 3개/cafe 1개 segment를 반환하여
|
||||
**requiredEmptyPassed=false**였으며 release acceptance 실패였다.
|
||||
그 실행의 모든 screening 파일은 읽기 전용
|
||||
[prior-attempt-market60-cafe180](../.agent/evidence-v0.2.3/privacy-screening/prior-attempt-market60-cafe180/)
|
||||
아래 바이트 그대로 보존했다. [당시 final-asr.json](../.agent/evidence-v0.2.3/privacy-screening/prior-attempt-market60-cafe180/final-asr.json)을
|
||||
성공으로 덮어쓰지 않았고 회귀 테스트가 이전 실패 상태와 모든 보존 파일 해시를 검사한다.
|
||||
|
||||
[기존 no-VAD 증거](../.agent/evidence-v0.2.3/privacy-screening/no-vad-asr.json)도 바이트 그대로 남겼다.
|
||||
이 결과는 mall 36초/market 60초/cafe 180초에서 환각일 수 있는 candidate text를 냈으며,
|
||||
새 market/cafe WAV의 검사 결과가 아니다. **no-VAD 결과는 지정된 VAD gate를 대체하거나 뒤집지 않는다.**
|
||||
두 방법 모두 말소리/음악의 부재를 증명하지 않으며 사람의 청취 인수나 법적/privacy clearance를 제공하지 않는다.
|
||||
Neo의 [이전 후보 scan](../.agent/evidence-v0.2.3/privacy-screening/candidate-scan-original.json),
|
||||
[이전 파생본 ASR](../.agent/evidence-v0.2.3/privacy-screening/prior-derivatives-asr-original.json),
|
||||
[당시 provenance](../.agent/evidence-v0.2.3/privacy-screening/earlier-asr-provenance.json)도 변경하지 않았다.
|
||||
raw JSON에 없던 설정이나 입력 연결을 사후에 있었던 것으로 주장하지 않는다.
|
||||
|
||||
새 RED → GREEN, 전체 검증과 보존 기록은
|
||||
[retry-market24-cafe0](../.agent/evidence-v0.2.3/privacy-screening/retry-market24-cafe0/),
|
||||
현재 검증 요약은 [RESULT](../.agent/RESULT-v0.2.3.md)의 마지막 절에 있다.
|
||||
|
||||
+35
-5
@@ -1,4 +1,4 @@
|
||||
# Find-Word v0.1.1 정적 배포 인계
|
||||
# Find-Word v0.2.3 정적 배포 인계
|
||||
|
||||
이 문서는 **Neo가 검토 후 수행할 절차**다. Codex는 서버, DNS, 인증정보에
|
||||
접근하지 않았고 배포·서비스 생성·Git commit/push도 하지 않았다.
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
Node.js 최소 **22.22.2** (`>=22.22.2`)의 지원 LTS 환경에서 `npm ci`, `npm run lint`, `npm test`,
|
||||
`npm run build`를 실행한다. `dist/` 전체를 하나의 릴리스로 전달한다.
|
||||
`dist/audio/`의 24kHz neural WAV 101개와 version 0.1.1 manifest가 반드시 포함되어야 한다. 런타임은
|
||||
Nginx 정적 파일만 필요하며 Node 서버·TTS 엔진·DB·환경변수·API 키는 필요 없다.
|
||||
`dist/audio/`의 24kHz neural WAV 101개와 version 0.2.3 manifest가 반드시 포함되어야 한다.
|
||||
`dist/ambience/`의 고유 현장 WAV 8개·manifest와 `dist/ambience/AMBIENCE_NOTICES.md`도 필수다.
|
||||
런타임은 Nginx 정적 파일만 필요하며 Node 서버·TTS 엔진·DB·환경변수·API 키는 필요 없다.
|
||||
잠긴 jsdom 계열 의존성 때문에 24.x는 24.15.0 이상, 26.x는 26.0.0 이상이어야 한다.
|
||||
브라우저 검증의 Chromium sandbox는 기본 활성화다. sandbox를 지원하지 않는
|
||||
격리된 개발 환경에서만 `PLAYWRIGHT_NO_SANDBOX=1`로 명시적으로 끈다.
|
||||
@@ -55,6 +56,12 @@ server {
|
||||
expires 7d;
|
||||
}
|
||||
|
||||
# 현장음도 누락 시 SPA HTML로 대체하지 않는다.
|
||||
location /ambience/ {
|
||||
try_files $uri =404;
|
||||
expires 7d;
|
||||
}
|
||||
|
||||
# SPA의 직접 진입·새로고침을 index.html로 받되 HTML은 재검증한다.
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
@@ -67,9 +74,9 @@ server {
|
||||
|
||||
1. 서버에 적용하기 전 `nginx -t`, 기존 서비스 충돌, 파일 읽기 권한을 확인한다.
|
||||
2. TLS/HTTPS와 DNS를 운영자가 확인한다. 실제 도메인에서 시작 후 음성이 들리는지 확인한다.
|
||||
3. `audio/intro.wav?v=0.1.1`와 목표 WAV의 같은 버전 query가 정상 응답하고
|
||||
3. `audio/intro.wav?v=0.2.3`와 목표 WAV의 같은 버전 query가 정상 응답하고
|
||||
존재하지 않는 오디오는 query가 있어도 404인지 확인한다.
|
||||
4. 모바일 Safari/Chrome, 데스크톱에서 음량·중단·다시 듣기·10문제 완주를 직접 확인한다.
|
||||
4. 모바일 Safari/Chrome, 데스크톱에서 음량·중단·다시 듣기·3문항 완주·다음 난이도·시작 단계·SNR 변경·중도 종료를 직접 확인한다.
|
||||
5. 원자적으로 릴리스 디렉터리를 전환하고 이전 디렉터리를 보관해 되돌릴 수 있게 한다.
|
||||
|
||||
오프라인 캐시를 제공하는 PWA는 아니다. 정적 자산의 최초 로드에는 해당 서버
|
||||
@@ -77,3 +84,26 @@ server {
|
||||
같은 파일명으로 WAV를 교체할 때 `src/audio/assets.ts`의 `AUDIO_ASSET_VERSION`도
|
||||
갱신한다. 제품 버전을 유지하는 음성 수정에서도 새 자산 버전이 필요하다.
|
||||
이 query는 로컬 정적 파일 요청에만 사용하며 런타임 외부 요청을 추가하지 않는다.
|
||||
|
||||
|
||||
## 0.2.3 독립 인수와 릴리스 (Neo 수행, 이 작업에서는 미실행)
|
||||
|
||||
1. `.agent/RESULT-v0.2.3.md`와 RED/GREEN 원문, 원본/배포 해시, 라이선스 고지를 검토한다.
|
||||
2. sandboxed system Chrome desktop/mobile suite와 `npm audit`를 다시 실행한다.
|
||||
3. 검토 완료 후 feature branch push, main fast-forward, annotated `v0.2.3` tag,
|
||||
fresh-clone readback으로 commit과 자산 해시를 확인한다.
|
||||
4. commit-addressed release 디렉터리로 dist를 복사하고 current 심볼릭 링크를 원자 전환한다.
|
||||
이전 release는 rollback 대상으로 보존한다.
|
||||
5. 공개 HTTPS에서 title/UI 0.2.3, WAV MIME·SHA-256·cache-busting query, 누락 자산 404,
|
||||
시작 단계·3문항 완료→다음 단계·SNR·중도 종료를 실제 Chrome으로 재검증한다.
|
||||
|
||||
이 문서의 Nginx 설정은 인계 예시이며 실행 증거가 아니다. 이번 작업은 localhost의
|
||||
production preview만 사용하며 Git commit/push/merge/tag, 외부 배포, secrets 사용은 하지 않는다.
|
||||
|
||||
|
||||
v0.2.3 리뷰 검증은 `.agent/evidence-v0.2.3/review-fixes/`에 별도로 보존한다.
|
||||
`check-build`는 앱 콘텐츠로 구성한 **정확히 101개**의 음성 파일명과 dist 파일 집합을 독립 대조하므로,
|
||||
manifest와 디렉터리를 함께 축약하거나 추가 WAV를 넣어도 실패한다. 현장음은 승인 계획의 출처 수치와
|
||||
각 notice 항목의 저작자·primary URL·direct URL·라이선스 링크·outputLicense·변경 고지까지 검사한다.
|
||||
현장음 notice의 배포 URL은 `/ambience/AMBIENCE_NOTICES.md`다. 고지는 음원/manifest와 함께
|
||||
원자 교체하는 같은 디렉터리 안에 있으며, 기존 루트의 notice 사본은 제거했다.
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
# 단어와 오답 변형
|
||||
# Find-Word v0.2.3 단어와 오답 변형
|
||||
|
||||
임의의 한글 조합을 자동 생성하지 않고 사전에 있는 표제어만 고른다. 다음의
|
||||
짧은 의미 구분은 앱 작성자가 작성한 설명이며 사전의 정의·예문·음성을
|
||||
@@ -38,3 +38,5 @@
|
||||
기록한다. 각 묶음의 세 오답은 서로 다른 규칙과 순위를 가진다. 이 순서는
|
||||
출제 메타데이터이며 청감·발음·청력에 대한 실측 난이도나 임상 척도가 아니다.
|
||||
새 단어를 넣을 때는 표제어·의미·변형 규칙을 검토하고 이 목록을 갱신한다.
|
||||
|
||||
0.2.3은 기존 10가지 mechanic·100문장을 보존하며 한 라운드에서 서로 다른 세 문항을 고른다.
|
||||
|
||||
Reference in New Issue
Block a user