46 lines
2.6 KiB
Python
46 lines
2.6 KiB
Python
"""Read-only scope audit against reviewed baselines; writes evidence in this directory."""
|
|
from pathlib import Path
|
|
import hashlib, json, re
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
ROOT = HERE.parents[2]
|
|
UP = HERE.parent
|
|
def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest().upper()
|
|
def read(path): return json.loads(path.read_text(encoding='utf-8-sig'))
|
|
def changed(entries):
|
|
return [p for p,h in entries.items() if not (ROOT/p).exists() or sha(ROOT/p) != h.upper()]
|
|
|
|
inventory = read(UP/'B3DesignAudit/source-hashes.json')
|
|
design = read(UP/'阶段4B3方案受审基线-2026-09-24.json')
|
|
b2 = read(UP/'KVGameLoadTests/checkpoint4-delivery-hashes.json')
|
|
pf = 'Client/Assets/Scripts/Core/PlayFabMgr.cs'
|
|
current = (ROOT/pf).read_bytes()
|
|
begin = b'\r\n // BEGIN KV explicit fixed-handle access\r\n'
|
|
end = b' // END KV explicit fixed-handle access\r\n'
|
|
assert current.count(begin) == current.count(end) == 1
|
|
start = current.index(begin)
|
|
finish = current.index(end) + len(end)
|
|
old_equal = current[:start] + current[finish:] == (HERE/'PlayFabMgr.before.txt').read_bytes()
|
|
callers = {}
|
|
for path in (ROOT/'Client/Assets/Scripts').rglob('*.cs'):
|
|
# Identifier-only scan: Latin-1 preserves ASCII in both legacy GBK and UTF-8 sources.
|
|
lines = [i for i,s in enumerate(path.read_bytes().decode('latin-1').splitlines(),1)
|
|
if re.search(r'\b(?:ReadKV|WriteKV|FlushKVAsync|WaitForKVTicketAsync)\s*\(',s)]
|
|
if lines: callers[path.relative_to(ROOT).as_posix()] = lines
|
|
new = sorted(p.relative_to(ROOT).as_posix() for p in (ROOT/'Client/Assets/Scripts').rglob('*.cs')
|
|
if p.relative_to(ROOT).as_posix() not in inventory)
|
|
result = dict(sourceBaselineCount=len(inventory), sourceChanged=changed(inventory), newScriptSources=new,
|
|
oldPlayFabBytesUnchanged=old_equal,
|
|
designMaterialChanged=changed({f['path']:f['sha256'] for f in design['files']}),
|
|
oldB2DeliveryChanged=changed({f['path']:f['sha256'] for f in b2['files']}),
|
|
facadeReferences=callers,
|
|
limitation='Scope is reviewed baselines, not all pre-existing working tree changes. Static/conditional probes do not prove Unity Player linking or stripping.')
|
|
assert result['sourceChanged'] == [pf], result
|
|
assert result['designMaterialChanged'] == [pf], result
|
|
assert result['oldB2DeliveryChanged'] == [pf], result
|
|
assert old_equal
|
|
assert len(new) == 2
|
|
assert set(callers) == {pf,'Client/Assets/Scripts/Services/PlayerData/PlayerKVSaveRouteEditorValidationHost.cs'}
|
|
(HERE/'checkpoint4-boundary-audit.json').write_text(json.dumps(result,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
|
print(json.dumps(result,ensure_ascii=False,indent=2))
|