# Boid flock evaluation — original findings

Assistant review on 2026-09-12, against baseline `30dcf4c` (also present in
`bb12f77`). User requested “Review the other evals as well, fix when needed”.
This record preserves the original judgments; follow-up dispositions belong in
the coordinated batch record. Paths and line numbers below refer to the baseline.

Pinned Odin subsystem command passed all 13 tests in 13.11 ms:
`odin test examples/boid_flock/subsystem -o:speed -out:examples/boid_flock/.gododin/review-subsystem-tests`.
No Godot process was launched during this source review.

- **F1 — blocker: the run gate can pass without rendering.** `test.sh:110–117`
  returns after a headless PASS whose verification is explicitly skipped. The
  promised subsequent windowed tier never runs. Lines 112/149 swallow engine
  exit status; lines 96/157 accept a screenshot from a previous run; lines 65–68
  choose the newest publication directory without checking accepted/current
  source identity. Missing tools also return success at lines 35–47.
  Success condition: mandatory configured prerequisites, current accepted artifact,
  distinct explicit tiers, real exit/error checks, fresh capture and zero owners.
- **F2 — should-fix: interactive and failure exits leak staging.** `main.gd:84–85`
  and `237–242` quit without shutdown; no exit hook exists. Native `flock.odin:66–69`
  can free only the pure arena. Normal Escape/close and failure paths therefore
  leave the retained foreign owner alive. Success: each exit invokes cooperative
  cleanup, with zero foreign values and instances in the final Host receipt.
- **F3 — should-fix: setup/resize failure ownership is unsound.** Native
  `flock.odin:119–127` leaks local staging when simulation allocation fails.
  `280–299` changes engine capacity before an old-owner retirement failure yet
  claims it undoes the resize; the engine remains new-sized against old staging.
  `frames_submitted` and verification windows also remain stale after resize.
  Success: partial setup retains or retires each owner; resize adopts a coherent
  new extent and retains any failed retirement for cleanup; verify refuses until
  a frame has been submitted for the current extent.
- **F4 — should-fix: the native scene also runs a hidden GDScript flock.**
  `main.tscn:59–62` merely hides Baseline while `gd_flock.gd:63–64` steps regardless
  of visibility. Default native play and the native eval both execute 400 hidden
  GDScript agents. Success: inactive mode never processes; eval asserts this.
- **F5 — should-fix: the comparison is a different simulation and population.**
  `gd_flock.gd:95–127` integrates in place while Odin gathers acceleration before
  integrating all agents (`subsystem/flock.odin:552–715`). It omits the total
  acceleration clamp at native lines 673–679 and seeds with a different RNG
  (`gd_flock.gd:44–57`). The cap of 500 versus native 10,000 contradicts “same
  visible work” (`README.md:42–44`). Success: matched initialization, two passes,
  bounded rules and same-count comparison; explicitly state numerical tolerance
  and separately retain the original native 1,000/10,000 workload.
- **F6 — should-fix: mode/count UI can error or misreport.** `main.gd:124` uses
  `%PredatorHint` without the scene setting `unique_name_in_owner`. Count changes
  apply only via `drag_ended` (`131–140`), excluding keyboard/wheel changes.
  Returning from baseline does not apply its requested count to native; baseline
  stats derive population from the slider (`172`) instead of actual state.
  Success: each control action has an applied state, actual counts are displayed,
  switching modes performs no invalid node lookup, and errors are surfaced.
- **F7 — should-fix: invalid live parameters poison simulation state.** Native
  `flock.odin:151–159` accepts NaN weights, infinite values and overflow during
  f64→f32 narrowing. Pure `steering_valid:189–196` validates only perception/speed,
  allowing invalid weights/predator coordinates to produce NaN state. Success:
  finite full live-parameter admission before mutation, including narrowed values.
- **F8 — should-fix: correctness and warm-allocation claims lack their oracles.**
  Hash tests check placement/permutation, while replay uses the same algorithm.
  `README.md:136` calls a physics oracle impossible, although an independent
  small-flock all-pairs one-step comparison is possible. Structural hash checks
  do not detect warm allocation regressions (`README.md:114–116`). Success:
  all-pairs differential cases across cell/wall/perception changes and instrumented
  zero allocations/frees for warm step, writer and queries.
- **F9 — should-fix: offline eval silently tolerates failed work and rewrites
  evidence.** `eval/main.odin:109–110` ignores return values in the measured loop;
  malformed/unknown arguments at 28–40 silently select defaults. `test.sh:61`
  always invokes `--write`, replacing the historical receipt; the writer also
  hardcodes host identity. Success: bounded strict arguments, all work asserted,
  emitted measurements retained separately, original receipt immutable.
- **F10 — nit: “bitwise” checks are numeric float comparisons.**
  `subsystem/flock.odin:803,836` uses `!=`, so +0 and -0 compare equal. Success:
  compare u32 representations and include a signed-zero regression.
- **F11 — nit: README facts overreach or diverge.** `README.md:106–107` names
  158.1/6705.9 µs while its linked receipt records 146.221/6484.661. Density at
  lines 183–184 is 0.09259 agents/unit³, not 0.037. A single MultiMesh submission
  does not imply one total draw call when shadow passes are enabled (90–91,
  scene:83). Success: link measurements without duplicated mutable numbers and
  bound renderer/CPU claims to actual measurements.

The pure Odin storage/ownership layout and deterministic iteration are otherwise
clear, and the existing same-seed digest assertion is real evidence for replay.
It does not prove physics correctness, visual quality, or total scene performance.
