Skip to content

core: a typed verify_scene takes only the usage measurements it needs - #1270

Merged
wass08 merged 2 commits into
mainfrom
perf/verify-scene-typed-checks
Nov 11, 2026
Merged

wass08 merged 2 commits into
mainfrom
perf/verify-scene-typed-checks

Conversation

@wass08

@wass08 wass08 commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

With the usage checks on (setSdfChecks(true)), verify_scene took every usage measurement on every call, whatever type it asked for. On a large building the circulation measurement (passages, turning circles, pockets) is nearly all of the cost, so a question about skirting or a blocked door paid for it too, and a run_batch of several typed checks paid for it once per call.

Two changes in packages/core:

  1. A typed question takes only the usage measurements its type needs. usageIssues now lists its measurements with the finding types each gives (types option), and the usage check passes the type asked for. A usage type takes its own measurement; any other type takes none; usage_room takes the one behind the findings a room entry holds. A misspelt usage type still takes all of them, so its answer names the types there are.
  2. The path solver's heap allocates nothing per pop. Same comparisons in the same order, so the same paths; it only removes the per-step temporaries.

Measured on a saved six-storey residential scene (1,244 nodes) on an Apple-silicon laptop, usage checks on:

Call Before After
Full check (no type) 15.7 s 11.2 s
type that is not a usage finding (door_blocked, rooms_no_skirting, item_overlap, …) 14.3–15.3 s 0.3 s
usage_clash, usage_opening_blocked, usage_bed_clearance, usage_fixture_clearance, usage_door_over_stair 13.9–15.3 s 0.3–0.4 s
usage_door_swing 14.8 s 1.4 s
usage_entry_narrow 14.4 s 1.6 s
usage_passage_narrow, usage_pocket, usage_turning_narrow, usage_room 14.9–15.3 s 8.0–8.9 s

The circulation types still cost seconds: that measurement is where the time goes, and this PR only stops other questions from paying for it.

Results. On that scene the full report and the model's reading of it are byte-identical before and after, and so are the findings and their count for each of the 15 types asked. One thing differs: an answer with no findings lists the other types found (types), and that list now holds the types of what the question measured. For a type that is not a usage finding it no longer lists usage types.

How to test

  1. cd packages/core && bun test src/agent-operations/verify-scene-typed.test.ts: on a small two-room scene whose report holds six usage types beside the ordinary ones, each typed answer equals the findings of that type in the whole report; a room with a type answers the same; a misspelt usage type answers with every type; the report for a non-usage type holds no usage findings.
  2. bun test src/spatial/usage-field src/agent-operations src/agent-tools (1,806 pass) and, in packages/mcp, bun test src/tools/verify-scene.test.ts src/tools/scene-query.test.ts (12 pass).
  3. To see the timings: load a large multi-storey scene, call setSdfChecks(true), and time AGENT_OPERATIONS.verify_scene(nodes, { type: 'door_blocked' }, context) against {}.

Screenshots / screen recording

N/A — non-visual change

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

🤖 Generated with Claude Code


Note

Medium Risk
Changes which usage measurements run for typed queries and how empty-result metadata lists types; heap refactor must preserve path results but is covered by existing usage-field tests.

Overview
When verify_scene is called with a type, usage checks no longer run the full circulation and fixture suite on every request. usageIssues maps each measurement to the finding types it produces and runs only matching measurements; non-usage types skip usage work entirely, usage_room still folds to pocket/turning types, and unknown usage types fall back to measuring everything (so answers can list valid types).

The usage scene check wires this through askedTypes(input.type) before calling usageIssues.

The grid path Heap is also tweaked so pop returns only the cell index and exposes the priority via heap.key, avoiding per-step tuple allocation in widestPath, travel, and shortestRoute.

A new verify-scene-typed.test.ts asserts typed reports match the full report per type, room+type behavior, misspelling fallback, and that non-usage types emit no usage findings.

Reviewed by Cursor Bugbot for commit 2d5dc8a. Bugbot is set up for automated code reviews on this repo. Configure here.

wass08 and others added 2 commits November 11, 2026 11:02
… needs

With the usage checks on, every verify_scene call took every usage
measurement, whatever type it asked for. The circulation measurement
(passages, turning circles, pockets) is nearly all of the cost on a large
building, so a question about skirting or a blocked door paid for it too.

usageIssues now lists its measurements with the finding types each gives,
and the usage check passes the type asked for: a usage type takes its own
measurement, any other type takes none. A misspelt usage type still takes
all of them, so its answer names the types there are.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
pop returned a new pair and every sift step swapped through two temporary
arrays. It now returns the value, leaves the key on the heap, and moves
the sifted entry once. Same comparisons in the same order, so the same
paths.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@wass08
wass08 merged commit 4bd7225 into main Nov 11, 2026
9 checks passed
@wass08
wass08 deleted the perf/verify-scene-typed-checks branch November 11, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant