From 4ced623b55e64db169114c5536fb476a5073bcd8 Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 8 Aug 2026 04:29:51 +0300 Subject: [PATCH] lint: ruff-clean testbed (blocking file write to thread, unused vars) --- .opencode/session-goal.md | 21 +++++++++++++++++++++ testbed/bridge.py | 2 +- testbed/demo.py | 10 +++++++--- testbed/room/render.py | 13 ++++++------- testbed/room/world.py | 2 +- testbed/tests/test_bridge.py | 1 - testbed/tests/test_render.py | 8 ++++---- testbed/tests/test_world.py | 4 ++-- 8 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 .opencode/session-goal.md diff --git a/.opencode/session-goal.md b/.opencode/session-goal.md new file mode 100644 index 0000000..199c945 --- /dev/null +++ b/.opencode/session-goal.md @@ -0,0 +1,21 @@ +# Session Goal + +реализуй полностью. автономно + +## Plan +1. Read protocol spec (docs/aicc-core.md) and testbed design (docs/testbed-design.md) +2. Inspect aicc-py SDK at ~/Desktop/aicc-py +3. Build testbed bridge skeleton (world, capsule, bridge with tools) +4. Implement tools: proprioception, vision, move, turn, look_at, interact +5. Add headless rendering for vision frames +6. Write agent demo loop +7. Run conformance suite (9/9 green) +8. Verify demo end-to-end, write README, commit per milestone + +## Progress +- DONE: world engine (room, capsule physics/collision, beacon, audio) — testbed/room/world.py +- DONE: headless raycaster renderer (vision 160x120 + aligned depth grid) — testbed/room/render.py +- DONE: RoomBridge with all world tools + echo/boom/bump — testbed/bridge.py +- DONE: conformance runner — 9/9 green against testbed bridge (testbed/conformance.py) +- DONE: commits for skeleton + bridge milestones +- NEXT: unit tests (world/render/bridge), demo agent loop (ollama LLM + scripted fallback), README, setup.sh, BUILDLOG diff --git a/testbed/bridge.py b/testbed/bridge.py index fbe4c47..e409aa1 100644 --- a/testbed/bridge.py +++ b/testbed/bridge.py @@ -13,7 +13,7 @@ import asyncio import base64 import io import math -from typing import Any, Literal +from typing import Any from aicc.bridge import Bridge from aicc.protocol import TickMode, ToolClass diff --git a/testbed/demo.py b/testbed/demo.py index 564c27e..8b4343a 100644 --- a/testbed/demo.py +++ b/testbed/demo.py @@ -417,7 +417,7 @@ async def run_scripted_agent( detour_turns += 1 t = (await client.call_tool("turn", {"yaw_deg": 45.0})).output summary["tool_calls"] += 1 - log("tool", f'turn({{"yaw_deg": 45.0}}) [detour]') + log("tool", 'turn({"yaw_deg": 45.0}) [detour]') log("bridge", f"ok {json.dumps(t)}") else: detour_steps -= 1 @@ -516,8 +516,12 @@ async def run_demo(args: argparse.Namespace) -> dict[str, Any]: frame = (await client.call_tool("vision", {})).output if args.frame: raw = base64.b64decode(frame["png_b64"]) - with open(args.frame, "wb") as fh: - fh.write(raw) + + def _write_frame() -> None: + with open(args.frame, "wb") as fh: + fh.write(raw) + + await asyncio.to_thread(_write_frame) print(f"\n[final frame saved] {args.frame}") print( f"\n[demo done] steps={summary['steps']} tool_calls={summary['tool_calls']} " diff --git a/testbed/room/render.py b/testbed/room/render.py index eec91da..8accca7 100644 --- a/testbed/room/render.py +++ b/testbed/room/render.py @@ -13,7 +13,7 @@ import math from PIL import Image -from testbed.room.world import ROOM_HEIGHT, ROOM_SIZE, Box, Room +from testbed.room.world import ROOM_HEIGHT, ROOM_SIZE, Room # Palette FOG = (14, 14, 20) @@ -83,10 +83,10 @@ class Raycaster: row_top = self._row_of(ROOM_HEIGHT, t_wall, eye, tan_pitch) row_bot = self._row_of(0.0, t_wall, eye, tan_pitch) - r_top = max(0, int(math.ceil(min(row_top, row_bot)))) - r_bot = min(h, int(math.floor(max(row_top, row_bot)))) + r_top = max(0, math.ceil(min(row_top, row_bot))) + r_bot = min(h, math.floor(max(row_top, row_bot))) - base = c * 3 + c * 3 for r in range(h): v = self.tan_fy * (1.0 - 2.0 * (r + 0.5) / h) down = v + tan_pitch @@ -252,7 +252,7 @@ class Raycaster: return _fog(col, dist) def _shade_floor(self, wx: float, wz: float, t: float) -> tuple[int, int, int]: - cell = int(math.floor(wx)) + int(math.floor(wz)) + cell = math.floor(wx) + math.floor(wz) col = FLOOR_A if cell % 2 == 0 else FLOOR_B fx = wx - math.floor(wx) fz = wz - math.floor(wz) @@ -285,8 +285,7 @@ class Raycaster: vv = (b.height - eye) / along - tan_pitch row_c = (1.0 - vv / self.tan_fy) / 2.0 * h r_px = b.radius / along / self.tan_fx * w / 2.0 - if r_px < 1.2: - r_px = 1.2 + r_px = max(r_px, 1.2) glow = r_px * 3.4 pulse = 1.0 diff --git a/testbed/room/world.py b/testbed/room/world.py index 17f3028..a385eaf 100644 --- a/testbed/room/world.py +++ b/testbed/room/world.py @@ -7,7 +7,7 @@ agent except through the sensor tools in ``testbed.bridge``. from __future__ import annotations import math -from dataclasses import dataclass, field +from dataclasses import dataclass ROOM_SIZE = 16.0 ROOM_HEIGHT = 3.0 diff --git a/testbed/tests/test_bridge.py b/testbed/tests/test_bridge.py index cb0f621..67321a1 100644 --- a/testbed/tests/test_bridge.py +++ b/testbed/tests/test_bridge.py @@ -15,7 +15,6 @@ from testbed.bridge import ( VISION_WIDTH, build_bridge, ) -from testbed.room.world import Room @pytest.fixture diff --git a/testbed/tests/test_render.py b/testbed/tests/test_render.py index 2d1927e..9d53665 100644 --- a/testbed/tests/test_render.py +++ b/testbed/tests/test_render.py @@ -21,7 +21,7 @@ def test_wall_nearby_is_bright_gray(): room = Room() room.capsule.yaw_deg = 180.0 # face north wall 1.5m away px = Raycaster().render(room)[0].load() - r, g, b = px[80, 60] + r, g, _b = px[80, 60] assert abs(r - g) < 8 and r > 80 # gray wall, little fog at 1.5m @@ -30,11 +30,11 @@ def test_beacon_glow_visible_when_facing_it(): room.capsule.x, room.capsule.z, room.capsule.yaw_deg = 11.0, 11.0, 45.0 img, _ = Raycaster().render(room) px = img.load() - r, g, b = px[80, 60] + r, _, b = px[80, 60] assert b > r # inactive beacon glows cyan room.beacon.active = True px = Raycaster().render(room)[0].load() - r, g, b = px[80, 60] + r, _, b = px[80, 60] assert r > b # active beacon glows warm yellow @@ -42,7 +42,7 @@ def test_beacon_occluded_by_crate(): room = Room() # Beacon behind crate_red from spawn: center pixel must not be cyan. px = Raycaster().render(room)[0].load() - r, g, b = px[80, 60] + _r, _g, b = px[80, 60] assert b < 90 diff --git a/testbed/tests/test_world.py b/testbed/tests/test_world.py index f908813..8af0701 100644 --- a/testbed/tests/test_world.py +++ b/testbed/tests/test_world.py @@ -4,7 +4,7 @@ import math import pytest -from testbed.room.world import ROOM_SIZE, Beacon, Box, Room +from testbed.room.world import ROOM_SIZE, Room def test_spawn_state(): @@ -79,7 +79,7 @@ def test_turn_clamps_pitch(): def test_look_at_beacon(): room = Room() - yaw, pitch = room.look_at_beacon() + yaw, _pitch = room.look_at_beacon() dx = room.beacon.x - room.capsule.x dz = room.beacon.z - room.capsule.z assert yaw == pytest.approx(math.degrees(math.atan2(dx, dz)))