P23-03: 生活の観察

This commit is contained in:
Agent Control Runner
2026-10-15 10:32:29 +09:00
parent 0b7727a66c
commit 21b5d3a31a
36 changed files with 4133 additions and 66 deletions
+343 -45
View File
@@ -155,9 +155,9 @@ def image_kind(data):
raise ValueError('unknown screenshot byte magic')
def inspect_conversion(rec, cua_receipt, converter_sha256=None):
def inspect_conversion(rec, cua_receipt, converter_sha256=None, resolve_path=Path):
"""CUA receipt and converter pin are independent of conversion assertions."""
raw, png = Path(rec['raw_path']), Path(rec['png_path'])
raw, png = resolve_path(rec['raw_path']), resolve_path(rec['png_path'])
require(raw.resolve() != png.resolve() and not raw.is_symlink() and not png.is_symlink(),
'conversion must preserve a separate raw file')
require(rec['raw_sha256'] == sha(raw) == cua_receipt['raw_sha256']
@@ -169,7 +169,7 @@ def inspect_conversion(rec, cua_receipt, converter_sha256=None):
require(rec['converter'] == '/usr/bin/sips', 'conversion executable')
pin = converter_sha256 if converter_sha256 is not None else sha('/usr/bin/sips')
require(rec['converter_sha256'] == pin, 'converter SHA mismatch')
require(rec['argv'] == ['/usr/bin/sips', '-s', 'format', 'png', str(raw), '--out', str(png)],
require(rec['argv'] == ['/usr/bin/sips', '-s', 'format', 'png', rec['raw_path'], '--out', rec['png_path']],
'converter argv mismatch')
require(type(rec['exit_code']) is int and rec['exit_code'] == 0, 'converter exit code')
for key in ('stdout_sha256', 'stderr_sha256'):
@@ -206,27 +206,92 @@ def affine_rect(matrix, rect):
return lo + [max(p[i] for p in points)-lo[i] for i in (0, 1)]
def compare_rectangles(report, audit, local_to_viewport, viewport_to_screen, local_to_screen, image, root=ROOT):
"""All draw rows, full affine composition, and exact existing style colors.
Font advance is recorded by the pinned engine/font, not approximated using
a new text width threshold. No image similarity threshold is introduced.
def screenshot_transform(calibration, request, image_size, clicks):
"""Content -> window screenshot pixels, cross-checked against actual clicks.
This is independent of the renderer's content-space screen_rect. In
particular, window_position is a desktop coordinate, not an image origin.
No titlebar height, scale, or image extent is assumed by the checker.
"""
for point in ([0, 0], [1, 0], [0, 1]):
close(affine_point(viewport_to_screen, affine_point(local_to_viewport, point)),
affine_point(local_to_screen, point), 'viewport/screen composition')
rows = audit['rows']
scale = calibration['backing_scale']
stretch = calibration['canvas_stretch']
titlebar = calibration['titlebar_pixels']
require(all(type(v) in (int, float) and math.isfinite(v) for v in
(scale, stretch, titlebar)) and scale > 0 and stretch > 0 and titlebar >= 0,
'invalid screenshot calibration')
close(calibration['window_size'], request['window_size'], 'calibrated window size')
close(calibration['window_position'], request['window_position'], 'calibrated window position')
close(calibration['screenshot_pixels'], list(image_size), 'calibrated image size')
close([request['screen_scale'], request['content_scale_factor']], [scale, stretch],
'calibrated engine scale')
close([request['window_size'][0]*scale, request['window_size'][1]*scale+titlebar],
list(image_size), 'calibrated content extent')
matrix = [scale, 0, 0, scale, 0, titlebar]
matched = 0
for receipt in clicks:
if receipt.get('target_pid') != request['target_pid']:
continue
for event in receipt['events']:
if event.get('action') != 'click':
continue
close(event['calibration'], calibration, 'click calibration')
point = event['point']
close(affine_point(point['viewport_to_screen'], point['viewport']),
point['screen'], 'click content affine')
close(affine_point(matrix, point['screen']), event['coordinates'],
'click screenshot offset')
matched += 1
require(matched > 0, 'missing independent click calibration')
return matrix
def rect_intersection(a, b):
require(len(a) == len(b) == 4 and all(type(v) in (int, float) and math.isfinite(v)
for v in a+b) and min(a[2:]+b[2:]) >= 0, 'invalid clipping rectangle')
x, y = max(a[0], b[0]), max(a[1], b[1])
return [x, y, max(0, min(a[0]+a[2], b[0]+b[2])-x),
max(0, min(a[1]+a[3], b[1]+b[3])-y)]
def rectangle_eligibility(rect, viewport):
clipped = rect_intersection(list(rect), [0, 0, *viewport])
if not clipped[2] or not clipped[3]:
return 'outside', clipped
return ('visible' if clipped == list(rect) else 'clipped'), clipped
def paired_crop_noise(before, after, rect):
"""Measured temporal differences, never an invented JPEG RGB tolerance.
A stable pair alone does not establish class or state identity. The result
is diagnostic data only and must not be promoted to pixels_<category>.
"""
require(before[:2] == after[:2], 'paired image dimensions')
x, y, w, h = rect_intersection(list(rect), [0, 0, *before[:2]])
errors = [max(abs(a-b) for a, b in zip(before[2][py][px][:3], after[2][py][px][:3]))
for py in range(math.ceil(y), math.floor(y+h))
for px in range(math.ceil(x), math.floor(x+w))]
require(errors, 'empty noise crop')
return dict(samples=len(errors), max_channel_delta=max(errors),
mean_channel_delta=sum(errors)/len(errors), unchanged=sum(v == 0 for v in errors))
def drawing_rectangle_rows(report):
"""Derive identities and local positions; do not read audit verdicts."""
expected = []
tower, people, world = 'scripts/ui/pixel_tower_art.gd', 'scripts/ui/pixel_people.gd', 'scenes/main/world_preview.gd'
tower = 'scripts/ui/pixel_tower_art.gd'
people = 'scripts/ui/pixel_people.gd'
world = 'scenes/main/world_preview.gd'
def actor(a, category=None):
expected.append((category or ('staff' if a['staff'] else 'guest'), a['key'],
a['at'] + [16*a['scale'], 18*a['scale']], people, None))
def badge(category, identifier, at, text):
expected.append((category, identifier, at + [None, 14], world, text))
def badge(category, identifier, b):
expected.append((category, identifier, b['at'] + [None, 14], world, b['text']))
for fid, room in report['rooms'].items():
if 'rect' in room:
expected.append(('room', fid, room['rect'], tower, None))
for i, b in enumerate(report['landing_badges']):
badge('queue', str(i), b['at'], b['text'])
badge('queue', str(i), b)
for cabin in report['cabins']:
expected.append(('EV', cabin['shaft_id'], cabin['rect'], tower, None))
for a in cabin['passengers']:
@@ -236,36 +301,254 @@ def compare_rectangles(report, audit, local_to_viewport, viewport_to_screen, loc
if a['staff'] and a['key'].removeprefix('staff/') in report['resting_staff']:
actor(a, 'rest')
for i, b in enumerate(report['badges']):
badge('goods' if b['kind'] == 'supply' else 'business', str(i), b['at'], b['text'])
require(len(rows) == len(expected), 'rectangle coverage')
width, height, pixels = image
checked = []
for row, (category, identifier, rect, source, text) in zip(rows, expected):
require((row['category'], row['id'], row['style_source']) == (category, identifier, source), 'rectangle row identity')
badge('goods' if b['kind'] == 'supply' else 'business', str(i), b)
for row in report.get('traffic', []):
if row['traffic']['current_density'] > 0 or row['traffic']['temporary_block']:
expected.append(('traffic', ','.join(map(str, row['cell'])), row['rect'], world, None))
return expected
def validate_drawing_rows(report, audit, root=ROOT):
expected = drawing_rectangle_rows(report)
require(len(audit['rows']) == len(expected), 'offline rectangle coverage')
for row, (category, identifier, rect, source, text) in zip(audit['rows'], expected):
require((row['category'], row['id'], row['style_source']) == (category, identifier, source),
'offline rectangle identity')
rect = list(rect)
if text is not None:
require(row['text'] == text and type(row['font_width']) in (int, float) and row['font_width'] > 0, 'badge font/text')
require(row['text'] == text and type(row['font_width']) in (int, float)
and math.isfinite(row['font_width']) and row['font_width'] > 0, 'offline font/text')
rect[2] = row['font_width'] + 6
close(row['rect'], rect, 'local drawing rectangle')
viewport = affine_rect(local_to_viewport, rect)
screen = affine_rect(viewport_to_screen, viewport)
close(row['viewport_rect'], viewport, 'viewport rectangle')
close(row['screen_rect'], screen, 'screen rectangle')
close(row['rect'], rect, 'offline report drawing rectangle')
colors = list(dict.fromkeys(re.findall(r'Color\("([0-9a-fA-F]{6})"', (root/source).read_text())))
require(row['style_colors'] == colors and colors, 'drawing style palette')
x, y, w, h = screen
require(w > 0 and h > 0 and x >= 0 and y >= 0 and x+w <= width and y+h <= height,
'drawing rectangle outside screenshot')
# Badge ink is distinct from its translucent backing. Actor ink/skin
# and facility colors are taken verbatim from their pinned draw source.
palette = {'fff2ce'} if text is not None else set(colors)
palette -= {'303c40', 'c6d3b6', 'd5dec4'} # shadow / sky decorations
rgb = {tuple(bytes.fromhex(c)) for c in palette}
found = any(tuple(pixels[py][px][:3]) in rgb
for py in range(math.ceil(y), math.floor(y+h))
for px in range(math.ceil(x), math.floor(x+w)))
require(found, 'missing drawing pixels: ' + category + '/' + str(identifier))
checked.append(category + '/' + str(identifier))
return checked
require(row['style_colors'] == colors and colors, 'offline source palette provenance')
def encode_png(rows):
"""Lossless review crop from decoded pixels, without an imaging dependency."""
require(rows and rows[0], 'empty crop')
width, channels = len(rows[0]), len(rows[0][0])
require(channels in (3, 4), 'crop channels')
def chunk(kind, body):
return (struct.pack('>I', len(body)) + kind + body
+ struct.pack('>I', zlib.crc32(kind + body)))
raw = b''.join(b'\0' + bytes(v for pixel in row for v in pixel) for row in rows)
return (b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', struct.pack(
'>IIBBBBB', width, len(rows), 8, 2 if channels == 3 else 6, 0, 0, 0))
+ chunk(b'IDAT', zlib.compress(raw)) + chunk(b'IEND', b''))
def frame_rows(report, audit, request, receipt, images, clicks, root=ROOT):
"""One mechanical path for frozen diagnostics and actual OS frames.
Errors are retained as failures, including incomplete frozen audits. Every
supplied row is accounted for; no palette value is an image oracle.
"""
errors, rows = [], []
try:
validate_drawing_rows(report, audit, root)
except (ValueError, KeyError, TypeError) as exc:
errors.append(str(exc))
calibration = screenshot_transform(receipt['calibration'], request, images[0][:2], clicks)
for image in images:
require(image[:2] == images[0][:2], 'frame image dimensions')
for point in ([0, 0], [1, 0], [0, 1]):
close(affine_point(request['viewport_to_screen'], affine_point(request['local_to_viewport'], point)),
affine_point(request['local_to_screen'], point), 'frame affine composition')
for index, row in enumerate(audit['rows']):
failures = list(errors)
close(row['viewport_rect'], affine_rect(request['local_to_viewport'], row['rect']),
'frame viewport rectangle')
close(row['screen_rect'], affine_rect(request['local_to_screen'], row['rect']),
'frame content rectangle')
status, clipped = rectangle_eligibility(row['rect'], report['viewport'])
screenshot_rect = affine_rect(calibration, affine_rect(request['local_to_screen'], clipped))
room = report['rooms'].get(row['id']) if row['category'] == 'room' else None
if row['category'] in ('business', 'goods'):
room = report['rooms'].get(report['badges'][int(row['id'])]['facility'])
operation, state = None, None
if room is not None:
states = enum_names(root, 'scripts/facility/facility_instance.gd', 'State')
operations = enum_names(root, 'scripts/facility/facility_instance.gd', 'OperationState')
require(type(room['state']) is int and 0 <= room['state'] < len(states), 'frame room enum')
state = states[room['state']]
require(state == room['state_name'], 'frame room state name')
require(type(room['operation']) is int and 0 <= room['operation'] < len(operations), 'frame operation enum')
operation = operations[room['operation']]
actors = list(report['actor_drawings']) + [a for c in report['cabins'] for a in c['passengers']]
actor = next((a for a in actors if a['key'] == row['id']), None)
if actor is not None:
actor_states = enum_names(root, 'scripts/staff/staff_runtime.gd' if actor['staff']
else 'scripts/guest/guest_runtime.gd', 'State')
require(type(actor['state']) is int and 0 <= actor['state'] < len(actor_states),
'frame actor state enum')
state = actor_states[actor['state']]
if row['category'] == 'queue':
badge = report['landing_badges'][int(row['id'])]
state = {k: badge[k] for k in ('members', 'visible_count', 'overflow')}
if row['category'] == 'EV':
cabin = next(c for c in report['cabins'] if c['shaft_id'] == row['id'])
state = {k: cabin[k] for k in ('operational', 'doors_open')}
if row['category'] == 'traffic':
traffic = next(r['traffic'] for r in report.get('traffic', [])
if ','.join(map(str, r['cell'])) == row['id'])
state = {k: traffic[k] for k in ('current_density', 'temporary_block')}
result = dict(row_index=index, category=row['category'], id=row['id'], layer=report['layer'],
state=state, state_name=state if isinstance(state, str) else None, operation=operation,
dimmed=row['category'] == 'room' and operation != 'OPERATING',
text=row.get('text'), local_rect=row['rect'], screenshot_rect=screenshot_rect,
style_source=row['style_source'], style_source_sha256=sha(root/row['style_source']),
style_colors=row['style_colors'], font_width=row.get('font_width'),
eligibility=status, reason={'visible': 'whole rectangle in viewport',
'clipped': 'rectangle intersects viewport', 'outside': 'no viewport intersection'}[status],
crops=[])
if status != 'outside':
for number, (width, height, pixels) in enumerate(images):
x, y, w, h = rect_intersection(screenshot_rect, [0, 0, width, height])
crop = [line[math.ceil(x):math.floor(x+w)]
for line in pixels[math.ceil(y):math.floor(y+h)]]
if not crop or not crop[0]:
failures.append('eligible crop outside image')
continue
if len({pixel for line in crop for pixel in line}) == 1:
failures.append('blank crop')
data = encode_png(crop)
result['crops'].append(dict(image_index=number, sha256=hashlib.sha256(data).hexdigest(),
png_bytes=data))
result['mechanical_pass'] = not failures
result['failures'] = failures
rows.append(result)
return dict(rows=rows, errors=errors, mechanical_pass=not errors and all(r['mechanical_pass'] for r in rows),
expected_row_count=len(drawing_rectangle_rows(report)))
def write_frame_review(directory, frame, provenance):
directory = Path(directory)
directory.mkdir(parents=True, exist_ok=True)
manifest = copy.deepcopy(frame)
manifest['images'] = provenance
for row in manifest['rows']:
for crop in row['crops']:
name = 'row-%04d-image-%d.png' % (row['row_index'], crop['image_index'])
(directory/name).write_bytes(crop.pop('png_bytes'))
crop['path'] = name
data = (json.dumps(manifest, sort_keys=True, ensure_ascii=False, indent=2) + '\n').encode()
(directory/'manifest.json').write_bytes(data)
digest = hashlib.sha256(data).hexdigest()
(directory/'manifest.sha256').write_text(digest + '\n')
return manifest, digest
def reviewed_pixel_categories(manifest, digest, verdict_path):
"""The worker never writes verdicts; absent independent review earns nothing."""
if not Path(verdict_path).is_file():
return set()
verdict = json.loads(Path(verdict_path).read_bytes())
require(verdict['manifest_sha256'] == digest, 'review manifest SHA mismatch')
require(verdict['reviewer'] == 'independent-opus-direct-image', 'independent image reviewer required')
eligible = [r for r in manifest['rows'] if r['eligibility'] != 'outside']
require([v['row_index'] for v in verdict['rows']] == [r['row_index'] for r in eligible],
'review row coverage')
for row, decision in zip(eligible, verdict['rows']):
require(all(decision[k] is True for k in ('category', 'state', 'position')), 'review row rejected')
if not manifest['mechanical_pass']:
return set()
return {r['category'] for r in eligible if r['mechanical_pass']}
def mirrored_inventory(directory):
"""Read every indexed byte; preserve original receipt paths as authority."""
directory = Path(directory).resolve()
index = json.loads((directory/'MIRROR_INDEX.json').read_bytes())
require(Path(index['mirror']).resolve() == directory, 'mirror root mismatch')
paths, mapping = set(), []
source = Path(index['source'])
for row in index['files']:
name = Path(row['path'])
require(not name.is_absolute() and '..' not in name.parts and str(name) not in paths,
'invalid/duplicate mirror path')
paths.add(str(name))
local = directory/name
require(local.resolve().is_relative_to(directory) and not local.is_symlink(), 'mirror escape')
data = local.read_bytes()
digest = hashlib.sha256(data).hexdigest()
require(digest == row['sha256'] and len(data) == row['bytes'], 'mirror hash/size mismatch')
mapping.append(dict(original=str(source/name), mirror=str(local), sha256=digest))
prior = index['previous_inventory']
prior_name = Path(prior['path'])
require(not prior_name.is_absolute() and '..' not in prior_name.parts
and (directory/prior_name).resolve().is_relative_to(directory)
and not (directory/prior_name).is_symlink(), 'previous inventory escape')
require(sha(directory/prior['path']) == prior['sha256'], 'previous mirror inventory hash')
old = json.loads((directory/prior['path']).read_bytes())
require(all(row in index['files'] for row in old['files']), 'previous mirror entries changed')
return index, mapping
def inspect_offline_mirror(directory):
"""Preparation diagnostics, deliberately separate from the acceptance gate.
Frozen incomplete draw audits cannot acquire missing rows by relabelling
source-derived rectangles as observed engine output.
"""
directory = Path(directory).resolve()
index, mapping = mirrored_inventory(directory)
by_original = {row['original']: row for row in mapping}
def resolve(original):
require(original in by_original, 'unindexed original path')
return Path(by_original[original]['mirror'])
pair = directory/'os-pair/A'
clicks = [json.loads((pair/name/'cua-receipt.json').read_bytes())
for name in ('writer-request-0001', 'writer-request-0003')]
results, inspected = [], []
for name in ('writer-request-0002', 'writer-request-0004'):
folder = pair/name
request = json.loads((folder/'request.json').read_bytes())
receipt = json.loads((folder/'cua-receipt.json').read_bytes())
require(sha(folder/'request.json') == receipt['request_sha256'], 'offline request binding')
require(receipt['target_pid'] == request['target_pid'], 'offline screenshot PID')
report, audit = decode(request['report']), decode(request['rectangles'])
images = []
for number, suffix in enumerate(('', '-after')):
conversion_path = folder/('root-early-conversion'+suffix+'.json')
conversion = json.loads(conversion_path.read_bytes())
shot = receipt['screenshots'][number]
require(resolve(conversion['raw_path']) == directory/shot['path'], 'offline raw path binding')
image = inspect_conversion(conversion, shot, resolve_path=resolve)
for stream in ('stdout', 'stderr'):
require(sha(Path(str(conversion_path)+'.'+stream)) == conversion[stream+'_sha256'],
'offline converter log hash')
images.append(image)
for original in (str(Path(index['source'])/conversion_path.relative_to(directory)),
conversion['png_path']):
inspected.append(by_original[original])
frame = frame_rows(report, audit, request, receipt, images, clicks, ROOT)
provenance = []
for number, suffix in enumerate(('', '-after')):
conversion_path = folder/('root-early-conversion'+suffix+'.json')
conversion = json.loads(conversion_path.read_bytes())
provenance.append(dict(whole_image_sha256=conversion['png_sha256'],
raw_sha256=conversion['raw_sha256'],
conversion_sha256=sha(conversion_path),
request_sha256=sha(folder/'request.json'),
receipt_sha256=sha(folder/'cua-receipt.json')))
review_dir = ROOT/'docs/plans/original-completion-2026-10-02/execution/p23-03/offline-r07-review'/name
manifest, digest = write_frame_review(review_dir, frame, provenance)
credited = reviewed_pixel_categories(manifest, digest, review_dir/'independent-verdict.json')
present = {r['category'] for r in frame['rows'] if r['eligibility'] != 'outside'}
overlays = [dict(cell=r['cell'], rect=r['rect']) for r in report['traffic']
if (r['traffic']['current_density'] > 0 or r['traffic']['temporary_block'])
and not any(a['category'] == 'traffic' and a['id'] == ','.join(map(str, r['cell']))
for a in audit['rows'])]
results.append(dict(request=name, layer=report['layer'], manifest_sha256=digest,
manifest_path=str(review_dir/'manifest.json'), rows=manifest['rows'],
mechanical_pass=frame['mechanical_pass'], errors=frame['errors'],
unaudited_traffic_overlays=overlays,
pending_categories=[c for c in CATEGORIES if c not in present],
pixel_categories=sorted(credited), independent_review='pending'))
return dict(task_id='P23-03', acceptance='pending', status='blocked',
inventory_count=len(mapping), path_map=mapping, inspected_eight=inspected,
frames=results, root_native_os_full_regression_independent_review='pending')
def enum_names(root, relative, name):
@@ -1171,9 +1454,18 @@ def inspect_os_requests(directory, layout, role, pid, root=ROOT):
# Screenshot actions observe a stable report; input before/after
# screenshots are provenance only and never relabelled as this frame.
if request['action'] == 'screenshot':
checked = compare_rectangles(report, decode(request['rectangles']), request['local_to_viewport'],
request['viewport_to_screen'], request['local_to_screen'], image, root)
pixel_categories.update(c.split('/')[0] for c in checked)
clicks = [document(json.loads(path(name).read_bytes())['input_receipt'])
for name in listing['requests']]
frame = frame_rows(report, decode(request['rectangles']), request, cua, [image], clicks, root)
review_dir = request_path.parent/('review-image-' + str(number))
manifest, manifest_sha = write_frame_review(review_dir, frame, [dict(
whole_image_sha256=binding['png_sha256'], raw_sha256=shot['raw_sha256'],
conversion_sha256=sha(path(binding['conversion'])) if conversion else None,
request_sha256=digest, receipt_sha256=sha(path(ack['input_receipt'])))])
require(frame['mechanical_pass'], 'frame mechanical checks: ' + str(frame['errors'])
+ str([r['failures'] for r in frame['rows'] if not r['mechanical_pass']]))
pixel_categories.update(reviewed_pixel_categories(
manifest, manifest_sha, review_dir/'independent-verdict.json'))
records.append(dict(request=request, ack=ack, observed=observed, cua=cua, request_sha256=digest))
require(len(seen) == len(bindings), 'unattributed screenshot bindings')
return records, pixel_categories
@@ -1301,9 +1593,15 @@ def main(argv=None):
parser.add_argument('--verify-only', action='store_true')
parser.add_argument('--project-root', type=Path, default=ROOT)
parser.add_argument('--diagnostics', type=Path)
parser.add_argument('--offline-mirror', type=Path)
parser.add_argument('--layout-a', type=Path)
parser.add_argument('--layout-b', type=Path)
args = parser.parse_args(argv)
if args.offline_mirror:
require(not any((args.verify_only, args.diagnostics, args.layout_a, args.layout_b)),
'offline preparation must not be combined with acceptance checks')
print(json.dumps(inspect_offline_mirror(args.offline_mirror), ensure_ascii=False))
return 2
if args.verify_only:
build = os.environ.get('BUILD_OUTPUT_DIR')
if not build:
+210 -21
View File
@@ -288,27 +288,6 @@ class InfrastructureTests(unittest.TestCase):
if change == 'id': q[0]['ack']['sequence'] = 2
with self.assertRaises(ValueError): check.inspect_resume(writer, r, saved, q, members)
def test_rectangle_pixel_and_transform_negatives(self):
source = 'scripts/ui/pixel_people.gd'
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"', (check.ROOT/source).read_text())))
report = dict(rooms={}, landing_badges=[], cabins=[], resting_staff={}, badges=[],
actor_drawings=[dict(key='staff/s', staff=True, at=[1, 1], scale=1)])
row = dict(category='staff', id='staff/s', rect=[1, 1, 16, 18], viewport_rect=[1, 1, 16, 18],
screen_rect=[1, 1, 16, 18], style_source=source, style_colors=colors)
audit = dict(rows=[row])
matrix = [1, 0, 0, 1, 0, 0]
image = (24, 24, [[(113, 157, 148)]*24 for _ in range(24)])
self.assertEqual(check.compare_rectangles(report, audit, matrix, matrix, matrix, image), ['staff/staff/s'])
for change in ('rectangle', 'pixels', 'transform', 'coverage', 'palette'):
with self.subTest(change=change):
a, m, img = copy.deepcopy(audit), matrix[:], image
if change == 'rectangle': a['rows'][0]['rect'][0] += 1
if change == 'pixels': img = (24, 24, [[(0, 0, 0)]*24 for _ in range(24)])
if change == 'transform': m[4] = 10
if change == 'coverage': a['rows'].clear()
if change == 'palette': a['rows'][0]['style_colors'] = ['000000']
with self.assertRaises(ValueError): check.compare_rectangles(report, a, matrix, m, matrix, img)
def test_interpolation_history_tampering(self):
state = dict(systems=dict(runtime=dict(guests=dict(guests=[]), staff=dict(staff=[]),
elevators=dict(shafts=[], trips=[], current_minute=0))))
@@ -568,5 +547,215 @@ class ComparisonTests(unittest.TestCase):
check.compare_layouts(a, b)
class OfflineGeometryTests(unittest.TestCase):
"""Synthetic calibration examples; no OS or acceptance credit."""
def setUp(self):
self.calibration = dict(window_size=[100, 80], window_position=[240, 150],
screenshot_pixels=[200, 190], backing_scale=2,
canvas_stretch=1, titlebar_pixels=30)
self.request = dict(window_size=[100, 80], window_position=[240, 150],
screen_scale=2, content_scale_factor=1, target_pid=123)
self.clicks = [dict(target_pid=123, events=[dict(action='click',
coordinates=[20, 70], calibration=copy.deepcopy(self.calibration),
point=dict(screen=[10, 20], viewport=[10, 20],
viewport_to_screen=[1, 0, 0, 1, 0, 0]))])]
def transform(self):
return check.screenshot_transform(self.calibration, self.request, [200, 190], self.clicks)
def test_uses_measured_scale_origin_not_desktop_position(self):
self.assertEqual(check.affine_rect(self.transform(), [10, 20, 5, 7]), [20, 70, 10, 14])
def test_shifted_titlebar_fails_independent_click(self):
self.calibration['titlebar_pixels'] += 1
self.calibration['screenshot_pixels'][1] += 1
self.clicks[0]['events'][0]['calibration'] = copy.deepcopy(self.calibration)
with self.assertRaises(ValueError):
check.screenshot_transform(self.calibration, self.request, [200, 191], self.clicks)
def test_wrong_click_offset_fails(self):
self.clicks[0]['events'][0]['coordinates'][1] -= 30
with self.assertRaisesRegex(ValueError, 'click screenshot offset'):
self.transform()
def test_wrong_pid_cannot_calibrate(self):
self.clicks[0]['target_pid'] += 1
with self.assertRaisesRegex(ValueError, 'missing independent click'):
self.transform()
def test_nonfinite_and_false_scale_rejected(self):
for scale in (False, float('nan'), 0, -1):
self.calibration['backing_scale'] = scale
with self.assertRaisesRegex(ValueError, 'invalid screenshot calibration'):
self.transform()
def test_all_visibility_cases_are_accounted_for(self):
self.assertEqual(check.rectangle_eligibility([2, 3, 4, 5], [10, 10]),
('visible', [2, 3, 4, 5]))
self.assertEqual(check.rectangle_eligibility([-2, 3, 4, 5], [10, 10]),
('clipped', [0, 3, 2, 5]))
self.assertEqual(check.rectangle_eligibility([10, 3, 4, 5], [10, 10])[0], 'outside')
self.assertEqual(check.rectangle_eligibility([2, 3, 0, 5], [10, 10])[0], 'outside')
def test_invalid_rectangles_rejected(self):
for rect in ([0, 0, -1, 4], [float('nan'), 0, 1, 4]):
with self.assertRaisesRegex(ValueError, 'invalid clipping rectangle'):
check.rectangle_eligibility(rect, [10, 10])
def test_noise_is_measured_and_does_not_assert_class(self):
before = (2, 2, [[(10, 20, 30)]*2 for _ in range(2)])
after = copy.deepcopy(before)
after[2][1][1] = (10, 27, 30)
noise = check.paired_crop_noise(before, after, [0, 0, 2, 2])
self.assertEqual(noise, dict(samples=4, max_channel_delta=7,
mean_channel_delta=1.75, unchanged=3))
self.assertNotIn('pass', noise)
self.assertNotIn('state', noise)
def test_wrong_dimensions_and_empty_crop_rejected(self):
image = (1, 1, [[(0, 0, 0)]])
with self.assertRaisesRegex(ValueError, 'paired image dimensions'):
check.paired_crop_noise(image, (2, 1, []), [0, 0, 1, 1])
with self.assertRaisesRegex(ValueError, 'empty noise crop'):
check.paired_crop_noise(image, image, [1, 0, 1, 1])
def test_report_positions_and_source_provenance_are_recomputed(self):
source = 'scripts/ui/pixel_people.gd'
report = dict(rooms={}, landing_badges=[], cabins=[], resting_staff={}, badges=[],
actor_drawings=[dict(key='staff/s', staff=True, at=[1, 1], scale=1)])
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
audit = dict(rows=[dict(category='staff', id='staff/s', rect=[1, 1, 16, 18],
style_source=source, style_colors=colors)])
check.validate_drawing_rows(report, audit)
for change in ('shift', 'identity', 'missing', 'palette'):
tampered = copy.deepcopy(audit)
if change == 'shift': tampered['rows'][0]['rect'][0] += 1
if change == 'identity': tampered['rows'][0]['category'] = 'guest'
if change == 'missing': tampered['rows'] = []
if change == 'palette': tampered['rows'][0]['style_colors'] = ['000000']
with self.subTest(change=change), self.assertRaises(ValueError):
check.validate_drawing_rows(report, tampered)
class FrameReviewTests(unittest.TestCase):
def setUp(self):
OfflineGeometryTests.setUp(self)
self.request.update(local_to_viewport=[1, 0, 0, 1, 0, 0],
viewport_to_screen=[1, 0, 0, 1, 0, 0],
local_to_screen=[1, 0, 0, 1, 0, 0])
self.report = dict(layer=0, viewport=[100, 80], rooms={}, cabins=[],
landing_badges=[], badges=[], resting_staff={}, traffic=[],
actor_drawings=[dict(key='staff/s', staff=True, at=[1, 1], scale=1, state=0)])
source = 'scripts/ui/pixel_people.gd'
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
self.audit = dict(rows=[dict(category='staff', id='staff/s', rect=[1, 1, 16, 18],
viewport_rect=[1, 1, 16, 18], screen_rect=[1, 1, 16, 18],
style_source=source, style_colors=colors)])
self.image = (200, 190, [[(x % 256, y % 256, 0) for x in range(200)] for y in range(190)])
def frame(self):
return check.frame_rows(self.report, self.audit, self.request,
dict(calibration=self.calibration), [self.image], self.clicks)
def test_blank_crop_fails_without_threshold(self):
self.image = (200, 190, [[(0, 0, 0)] * 200 for _ in range(190)])
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertIn('blank crop', result['rows'][0]['failures'])
def test_missing_extra_and_unaudited_traffic_fail(self):
for change in ('missing', 'extra', 'traffic'):
with self.subTest(change=change):
original = copy.deepcopy(self.audit)
if change == 'missing': self.audit['rows'].clear()
if change == 'extra': self.audit['rows'] *= 2
if change == 'traffic':
self.report['traffic'] = [dict(cell=[-6, 2, 0], rect=[1, 1, 5, 5],
traffic=dict(current_density=1, temporary_block=False))]
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertEqual(len(result['rows']), len(self.audit['rows']))
self.assertIn('offline rectangle coverage', result['errors'])
self.audit = original
def test_dense_or_blocked_traffic_row_closes_audit_gap(self):
source = 'scenes/main/world_preview.gd'
colors = list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text())))
for density, blocked in ((1, False), (0, True), (0, False)):
with self.subTest(density=density, blocked=blocked):
self.report['traffic'] = [dict(cell=[-6, 2, 0], rect=[1, 1, 5, 5],
traffic=dict(current_density=density, temporary_block=blocked))]
active = density > 0 or blocked
missing = self.frame()
self.assertEqual(missing['mechanical_pass'], not active)
if active:
self.assertIn('offline rectangle coverage', missing['errors'])
self.audit['rows'].append(dict(category='traffic', id='-6,2,0',
rect=[1, 1, 5, 5], viewport_rect=[1, 1, 5, 5],
screen_rect=[1, 1, 5, 5], style_source=source, style_colors=colors))
complete = self.frame()
self.assertTrue(complete['mechanical_pass'], complete['errors'])
self.audit['rows'].pop()
def test_wrong_state_enum_and_name_fail(self):
source = 'scripts/ui/pixel_tower_art.gd'
self.report['actor_drawings'] = []
room = dict(rect=[1, 1, 16, 18], state=3, state_name='NO_STAFF', operation=0)
self.report['rooms'] = {'r': room}
self.audit['rows'][0].update(category='room', id='r', style_source=source,
style_colors=list(dict.fromkeys(check.re.findall(r'Color\("([0-9a-fA-F]{6})"',
(check.ROOT/source).read_text()))))
self.assertEqual(self.frame()['rows'][0]['operation'], 'INACTIVE')
for state, name in ((99, 'NO_STAFF'), (3, 'OPEN'), (True, 'NO_ACCESS')):
room.update(state=state, state_name=name)
with self.assertRaises(ValueError): self.frame()
def test_frame_rejects_affine_and_calibration_shift(self):
self.request['local_to_screen'][4] += 1
with self.assertRaisesRegex(ValueError, 'affine composition'): self.frame()
self.request['local_to_screen'][4] -= 1
self.clicks[0]['events'][0]['coordinates'][1] += 1
with self.assertRaisesRegex(ValueError, 'click screenshot offset'): self.frame()
def test_eligible_crop_fully_outside_image_fails(self):
for key in ('viewport_to_screen', 'local_to_screen'):
self.request[key][4] = 300
self.audit['rows'][0]['screen_rect'][0] += 300
result = self.frame()
self.assertFalse(result['mechanical_pass'])
self.assertIn('eligible crop outside image', result['rows'][0]['failures'])
def test_manifest_crop_and_independent_review_binding(self):
with tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
manifest, digest = check.write_frame_review(directory, self.frame(),
[dict(whole_image_sha256='a'*64, raw_sha256='b'*64, conversion_sha256='c'*64)])
self.assertEqual(check.sha(directory/'manifest.json'), digest)
crop = manifest['rows'][0]['crops'][0]
self.assertEqual(check.sha(directory/crop['path']), crop['sha256'])
self.assertEqual(check.png_pixels((directory/crop['path']).read_bytes())[:2], (32, 36))
verdict_path = directory/'independent-verdict.json'
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), set())
verdict = dict(manifest_sha256=digest, reviewer='independent-opus-direct-image',
rows=[dict(row_index=0, category=True, state=True, position=True)])
for change in ('wrong_sha', 'missing_row', 'extra_row', 'rejected_state'):
bad = copy.deepcopy(verdict)
if change == 'wrong_sha': bad['manifest_sha256'] = '0'*64
if change == 'missing_row': bad['rows'] = []
if change == 'extra_row': bad['rows'] *= 2
if change == 'rejected_state': bad['rows'][0]['state'] = False
verdict_path.write_text(json.dumps(bad))
with self.subTest(change=change), self.assertRaises(ValueError):
check.reviewed_pixel_categories(manifest, digest, verdict_path)
verdict_path.write_text(json.dumps(verdict))
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), {'staff'})
manifest['mechanical_pass'] = False
self.assertEqual(check.reviewed_pixel_categories(manifest, digest, verdict_path), set())
if __name__ == '__main__':
unittest.main()