Conversation
PSheon
marked this pull request as draft
September 11, 2026 05:41
…onstant The left panel is a 960x540 resize of the source frame and every track box was drawn at box / 2.0 -- 1920/960 written as a number. The blur boxes beside them already scaled by the probed source size, so on any non-1080p clip the two disagreed on one panel: a 1280-wide FTI clip drew the boxes at two thirds of the people, a 3840-wide one drew them at twice their size. analytics.world carries the source size for placement; it now carries the panel ratio too, and the demo draws through it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…not a +8 constant pick_daytime_slot turned a UTC slot into store-local with (hour + 8) % 24 and the static-plate index repeated +8 in prose. A US-Central factory (UTC-5) passed the daytime gate by coincidence -- its 10 UTC capture read as 18 local -- and its real daytime, 15 UTC, would have been refused as 23. cameras.json now carries utc_offset_hours (8 when absent, so every existing file means what it meant), static_plates records it in index.json, and onboard_camera passes it through. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…-pins The sweep pinned one camera by name (camera == "Taichung-cam01") and took the 70.4 constant as every other camera's primary row, so floor_calibrate.py's measured vfov had no consumer: on FTI-MDF-cam821 the 62.8 the floor's right angles gave had to be written into the calib by hand. The tile pin is now data (BUILTIN_PINS), --vfov-pins reads the instrument's own pins file over it, the camera's pin is its primary vfov and always joins the sweep, and vfov_source / k1_source say where each number came from. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… metres it reads Every ruler reads through the camera's metres; what makes one a witness is where its reference length came from. The 1.70 m prior is anchored. A catalogue tile chosen because the store's cameras agree on it is not: on FTI's 600 mm raised floor DA-V2's raw metres read 0.85 and 0.74 m, standard_tile picked 0.80, and the two cameras agreed with each other rather than the floor. A store-median counter is relative by construction. Rulers now carry `anchored`; person_ruler is None on an unmeasured or bootstrap calibration instead of anchoring factor 1 to the reading under test; and combine() returns an explicit unanchored verdict when no ruler is anchored, in place of 'within 10% of the current metres'. scale_rulers marks the consensus tile unanchored. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…oning tool Thirty tools and the two scripts the chain loads derived their root from their own file and nothing else, so runs/commission01, runs/site30k_qa and datasets/studioa_static could only ever be the checkout's own. Commissioning a second site (FTI, 2026-09-10) meant copying src/ tools/ scripts/ into a checkout-shaped directory. scene_mesh.py already read SYNCAI_ROOT; every tool now takes the same override, shipped.py resolves its checkpoints through syncai_hydranet.paths.repo_root so they move with the site, and a test keeps a bare Path(__file__) root out of the chain. The site name inside the paths is unchanged: that is the next commit's problem, not this one's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
image_size_px is the frame the intrinsics were fitted at, half the plate's source by convention, and every consumer that rescaled boxes into it assumed the source was 1920x1080 -- a mismatch returned metres, not an error. An FTI camera commissioned from a 1280x720 stream and another from 3840x2160 both did (2026-09-11). static_plates now records each clip's probed size beside its slot, onboard_camera carries it into the calib as source_size_px, from_onboard_calib keeps it in camera.json (optional: a v3 file reads as before), validate() refuses a source of another aspect, and demo_video says so when the clip it is given is not the stream the camera was commissioned from. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
freeze() copied src/, scene_mesh.py, pyproject.toml and uv.lock by name while capture_inputs also identified rebuild_geometry.py, so the snapshot's identity never matched its source and stage0_baseline.py failed on every camera before reaching a scene (FTI-SMT-cam912, 2026-09-16). The copy now walks the identity record itself -- inputs and code alike -- so the two lists cannot drift apart, and a test freezes a fixture site and asserts the snapshot identifies as it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pick_daytime_slot kept a shop's 08-18 local window as a constant. A factory on night shifts is lit at 05:22 local, and that was FTI-SMT-cam912's only capture: the gate refused it as night and onboarding stopped (2026-09-16). cameras.json now carries daytime_hours_local [start, end] (08-18 when absent, so every existing site means what it meant; start > end is a window across midnight), static_plates records it in index.json and onboard_camera passes it through. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PSheon
force-pushed
the
fix/stage0-gaps
branch
from
September 16, 2026 09:46
cd5e0b1 to
d2159a6
Compare
…clip The chain for a second site lived in a shell script under runs/ of a copied checkout (FTI batch_one.sh, 2026-09-10), with the bootstrap rule as inline Python nobody could test and the demo render welded on. The tool runs the README's steps in the README's order against SYNCAI_ROOT and ends in stage0_baseline.py's freeze, so the chain and the review candidate share one entry point. The bootstrap -- scale 1.0 on raw DA-V2 metres when no person box exists -- needs --allow-bootstrap and is flagged in the calib; no floor plane is a refusal. --dry-run prints the plan and touches nothing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PSheon
force-pushed
the
fix/stage0-gaps
branch
from
September 16, 2026 09:49
d2159a6 to
e7f4941
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
Six gaps in Stage 0 that a second site exposed (FTI factory, 2026-09-10/11; record in
/home/paul/hydranet_fti_stage0/runs/REVIEW.md). One commit each; every commit stands alone and carries its test.fix(demo_video)/ 2.0— a 1920-wide source as a constant; 2/3 off on 1280, 2× on 3840analytics.world.panel_box: the panel/source ratio per axis, used by the demofix(commissioning)pick_daytime_slothardcoded UTC+8; a US-Central site passed the daytime gate by coincidencecameras.jsoncarriesutc_offset_hours(8 when absent);static_platesrecords it;onboard_camerapasses itfeat(onboard)floor_calibrate's measured vfov had no consumer--vfov-pinsreads the instrument's pins file overBUILTIN_PINS; the pin is the camera's primary row and joins the sweep;vfov_source/k1_sourcesay where each number came fromfix(rulers)person_ruleranchored factor 1 to a bootstrap scaleRuler.anchored;person_ruleris None on unmeasured/bootstrap;combinereturns an explicit unanchored verdict instead of "within 10%";scale_rulersmarks the consensus tile unanchoredfeat(tools)SYNCAI_ROOT(the patternscene_mesh.pyalready used);shipped.pyresolves checkpoints throughpaths.repo_root; a test keeps barePath(__file__)roots out of the chainfeat(camera_json)CameraFile.source_size_px(optional; v3 files read unchanged), recorded bystatic_plates, carried byonboard_camera, kept byfrom_onboard_calib, aspect-checked invalidate(), anddemo_videosays when the clip is not the commissioned streamdocs(figures)CI-equivalent locally:
ruff format --check,ruff check,scripts/coverage_ratchet.sh— 3581 passed, 16 skipped; the two figure-staleness failures were cleared by the last commit. One local-only failure is not this branch:test_map_anything_evalasserts the 8 shipped cameras and this box now holds 9 (Tao-Hsin-cam15, another session) plustest1; CI has noruns/and skips it.Deliberately not in this PR
commission_camera.py,floor_calibrate.py,geometry_cache.py,rebuild_geometry.py,ground_control.py): the vfov instrument's no-crossing fallback (cam632's 48→50° sign flip is a plane-pick flip reported as "no crossing"), a labelled bootstrap route for personless cameras incommission_camera, anddepth_scalein recipe-built caches (scale_rulers.applyrefuses them) all land there. Listed in REVIEW.md with evidence; to follow once that work is committed.datasets/studioa_static,runs/commission01): root is now switchable, the literal names are not — apathsconfig is the next step, after the dirty tools land.GeomTeacher'sruns/zones01dependency (it only uses the walkable polygonpropose_zonesderives): same file as above.walltoday), absolute object rulers beyond the tile catalogue, cross-camera registration into one world, and thresholds on overlay IoU (Gate D, in flight elsewhere).Evidence the changes act on
demo_video, check frame 112).floor_calibratemeasured 62.8°; applied by hand before,--vfov-pinsnow.🤖 Generated with Claude Code