108 lines
8.0 KiB
Python
108 lines
8.0 KiB
Python
"""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))
|