Files
2026-10-14 10:01:46 +00:00

108 lines
8.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Publish a current automation summary only after every required run succeeds."""
from datetime import datetime, timezone
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
EVIDENCE = Path(__file__).resolve().parent
for name in ('lint', 'unit', 'python', 'build'):
assert 'Exit code: 0' in (EVIDENCE / f'05-{name}.log').read_text(), name
assert '125 passed (125)' in (EVIDENCE / '05-unit.log').read_text()
assert 'Ran 36 tests' in (EVIDENCE / '05-python.log').read_text()
audit = json.loads((EVIDENCE / 'npm-audit.json').read_text())
assert audit['metadata']['vulnerabilities']['total'] == 0
browser = json.loads((EVIDENCE / 'browser-results.json').read_text())
assert browser['stats']['expected'] == 30
assert all(browser['stats'][name] == 0 for name in ('unexpected', 'flaky', 'skipped'))
assert browser.get('errors', []) == []
sandbox = json.loads((EVIDENCE / 'chrome-sandbox.json').read_text())
assert sandbox['exitCode'] == 0 and sandbox['noSandboxFlagPresent'] is False and sandbox['processes']
integrity = json.loads((EVIDENCE / 'browser-integrity-summary.json').read_text())
assert len(integrity) == 2 and all(e['filesMatched'] == 109 for e in integrity)
screen = json.loads((EVIDENCE.parent / 'final-asr.json').read_text())
assert screen['requiredEmptyPassed'] is True
assert screen['limitations']['humanListeningAcceptance'] is False
assert screen['limitations']['legalPrivacyClearance'] is False
preservation = json.loads((EVIDENCE / 'preservation.json').read_text())
summary = {'completedAtUtc':datetime.now(timezone.utc).isoformat(),
'scope':'Requested automated release/screening checks only. Human listening acceptance and legal/privacy clearance were not performed.',
'implementationAndAtomicRegenerationComplete':True,
'allRequestedAutomatedAcceptanceChecksPassed':True,
'requiredEmptyPassed':True, 'humanListeningAcceptance':False, 'legalPrivacyClearance':False,
'blockingAutomatedCriterion':None,
'checks':{
'lint':{'exitCode':0,'log':'05-lint.log'},
'unit':{'exitCode':0,'files':13,'passed':125,'failed':0,'skipped':0,'log':'05-unit.log'},
'python':{'exitCode':0,'passed':36,'failed':0,'skipped':0,'log':'05-python.log'},
'build':{'exitCode':0,'voiceFiles':101,'ambienceFiles':8,'log':'05-build.log'},
'audit':{'exitCode':0,'vulnerabilities':0,'evidence':'npm-audit.json'},
'sandboxedChrome':{'exitCode':0,'passed':30,'failed':0,'skipped':0,'flaky':0,
'durationMs':browser['stats']['duration'],'projects':['desktop','mobile'],
'evidence':'browser-results.json','sandboxEvidence':'chrome-sandbox.json'}},
'asr':{'evidence':'../final-asr.json','sha256':preservation['finalAsrSha256'],
'method':'faster-whisper 1.2.1 tiny multilingual CPU int8; beam_size=5, best_of=5, default VAD, condition_on_previous_text=true',
'selectedRequiredStarts':{'mall':36,'market':24,'cafe':0},
'segmentsByEnvironment':{e['environmentId']:len(e['segments']) for e in screen['files']},
'requiredEmptyPassed':True,'screeningOnly':True,'humanListeningAcceptance':False,'legalPrivacyClearance':False,
'priorFailedAttempt':'../prior-attempt-market60-cafe180/final-asr.json',
'historicalNoVadEvidence':'../no-vad-asr.json',
'noVadLimitation':'Historical candidate text may be hallucinated, does not screen new market/cafe files and does not override the VAD gate. Neither method proves absence of speech/music.'},
'preservation':preservation,'head':preservation['head'], 'commitPushMergeTagDeployPerformed':False}
with (EVIDENCE / 'validation-summary.json').open('x') as out:out.write(json.dumps(summary,indent=2)+'\n')
current = EVIDENCE.parent / 'validation-summary.json'
assert current.read_bytes() == (EVIDENCE.parent / 'prior-attempt-market60-cafe180/validation-summary.json').read_bytes()
root_summary = dict(summary)
root_summary['evidenceBaseDirectory']='retry-market24-cafe0'
current.write_text(json.dumps(root_summary,indent=2)+'\n')
p = ROOT / '.agent/RESULT-v0.2.3.md'
s = p.read_text()
s = s.replace('이번 재시도의 전체 검증 결과는 맨 아래 **최종 privacy screening 재시도** 절에 기록한다.',
'전체 unit 125개·Python 36개·sandboxed Chrome 30개 및 lint/build가 통과했고 audit 취약점은 0개다.\n실행 원문은 맨 아래 **최종 privacy screening 재시도** 절에 있다.')
start = s.index('### 재시도 전체 검증')
base='evidence-v0.2.3/privacy-screening/retry-market24-cafe0'
s = s[:start]+f'''### 재시도 전체 검증
| 검사 | 실제 결과 | 근거 |
| --- | --- | --- |
| lint / typecheck | PASS, exit 0 | [05-lint]({base}/05-lint.log) |
| 전체 unit | 13 files / **125 passed, 0 failed, 0 skipped**, exit 0 | [05-unit]({base}/05-unit.log) |
| 전체 Python | **36 passed**, exit 0 | [05-python]({base}/05-python.log) |
| build | PASS, 101 voice + 8 ambience 및 notices, exit 0 | [05-build]({base}/05-build.log) |
| npm audit | **취약점 0**, exit 0 | [audit]({base}/npm-audit.json) |
| sandboxed Chrome desktop/mobile | **30 passed / 0 failed / 0 skipped / 0 flaky**, exit 0 | [06-browser]({base}/06-browser.log), [JSON]({base}/browser-results.json) |
현재 자동 검증은 모두 통과했다. [validation-summary]({base}/validation-summary.json)는 위 실행들의
실제 exit code·결과를 확인한 뒤 작성했으며 사람의 인수/법적 clearance를 포함한 전체 승인으로 해석하지 않는다.
현재 ASR gate 통과를 이전 실패의 통과로 바꾸어 기록하지 않았다.
Chrome 146.0.7680.80, desktop 1280×1000 / mobile 360×800 touch emulation의 전체 suite는
{browser['stats']['duration']/1000:.1f}초 걸렸다. 이 runner의 Chrome 자손 process {len(sandbox['processes'])}개에서
`--no-sandbox`가 없음을 [실제 process 기록]({base}/chrome-sandbox.json)으로 확인했다.
설정은 `chromiumSandbox=true`이고 opt-out 환경변수는 제거했다.
양쪽에서 현재 **109 WAV response SHA-256/bytes·실제 decode·길이·채널·sample rate**를 전수 확인했다.
[desktop 오디오]({base}/desktop-audio-integrity.json), [mobile 오디오]({base}/mobile-audio-integrity.json),
[독립 실측 대조]({base}/browser-integrity-summary.json): hash/bytes 정확히 일치,
RMS/peak 차이는 브라우저 float scaling을 고려한 PCM16 한 step 이내다.
정상 요청에서 외부 요청·console/page 오류·failed request는 모두 0이며,
실제 여덟 ambience loop, 오류 재시도, UI·키보드·axe, 320/360px 어절·진행률 픽셀 검사도 통과했다.
[desktop runtime]({base}/desktop-runtime-audit.json), [mobile runtime]({base}/mobile-runtime-audit.json).
| 현재 화면 | Desktop | Mobile |
| --- | --- | --- |
| 시작 | [PNG]({base}/screenshots/desktop-start.png) | [PNG]({base}/screenshots/mobile-start.png) |
| 게임 | [PNG]({base}/screenshots/desktop-game.png) | [PNG]({base}/screenshots/mobile-game.png) |
| 정상 결과 | [PNG]({base}/screenshots/desktop-normal-results.png) | [PNG]({base}/screenshots/mobile-normal-results.png) |
| 중도 종료 | [PNG]({base}/screenshots/desktop-early-exit.png) | [PNG]({base}/screenshots/mobile-early-exit.png) |
[보존 검사]({base}/preservation.json): 101 voice·다섯 unaffected ambience·mall 바이트 동일,
이전 `.agent` 파일 484개·읽기 전용 prior-attempt 사본 89개·HEAD 추적 역사 파일 180개 해시 동일.
갱신 허용된 plan/RESULT/current ASR/current summary 4개는 이전 상태를 별도 보존했다.
원본 provenance는 지정 market/cafe 시작점 외에 변경이 없고 dist는 현재 bundle과 바이트 동일하다.
**한계와 인계:** 지정된 자동 VAD acceptance를 충족했다. 사람의 청취 인수와 법적/privacy clearance는
여전히 수행하지 않았으며 empty ASR은 말소리/음악의 부재 증거가 아니다.
mobile은 Chrome viewport/touch emulation이다. Git commit/push/merge/tag/deploy는 하지 않았다.
'''
p.write_text(s)
print(json.dumps({'automatedChecksPassed':True,'unitPassed':125,'pythonPassed':36,'browserPassed':30,'requiredEmptyPassed':True,'humanListeningAcceptance':False,'legalPrivacyClearance':False},indent=2))