Bird song journal scene (BirdWeather) - #327
Open
mariusandra wants to merge 13 commits into
Open
Conversation
Split out of #259. Platform work for JavaScript repo apps: - JS app runtime: HTTP requests (bounded fetch with headers and binary responses), asset management, streams, and gated settings access for repo code apps - JS transpiler: template interpolations and comparisons no longer eat object literals; native/JS transpiler parity test Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Split out of #259; stacked on the JS app runtime extensions it uses. - repo/apps/code/birdJournal: iNaturalist sightings become OpenAI-generated field-journal plates - Sample scene under repo/scenes/samples/Bird field journal - End-to-end mock-server scene test (test_bird_journal_scene.nim) - Regenerated frontend/src/generated/repoApps.ts and the add-scene / apps-drawer visual snapshots for the new app and sample scene Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # backend/app/api/templates.py # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--dark--full.png # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--dark--mid.png # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--dark--mobile.png # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--light--full.png # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--light--mid.png # e2e/frontend-visual/snapshots/chromium/visual.spec.ts/frame-scenes--add-scene--light--mobile.png
A sibling of the Bird field journal that sources its birds from what BirdWeather's listening stations actually heard rather than from what somebody photographed. The BirdWeather public API is GraphQL, so the app posts a single query per poll: topSpecies for the roster and window counts, plus an aliased detections field for the newest local detection per species. Species carry a licensed reference photo, which is what the plate is drawn from. Species.latestDetections is deliberately unused — it is global, so it reports stations on other continents for a local bounding box. Either a latitude/longitude/radius box or explicit station IDs select what to listen to; stations win, because passing both intersects them. Species heard fewer than minDetections times are skipped, since BirdNET guesses at the edge of its confidence produce one-off species. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A real 480x800 render of the scene through the interpreter, with a Great Tit plate drawn from BirdWeather's licensed reference photo and live detection numbers from the Brussels box the placeholder coordinates describe. Like the other sample previews it is a PNG under a .jpg name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Summary
A fork of #262 that sources its birds from BirdWeather instead of iNaturalist: a sibling sample scene under
repo/scenes/samples/Bird song journal, so the two can ship side by side. #262 draws birds somebody photographed nearby; this one draws birds that BirdWeather's listening stations actually heard.Stacked on
bird-field-journal-scenewithmainmerged in, so the diff below also carries #262's commits. Once #262 merges this reduces to the new scene alone. TheframeosVersionexport stamping #262 added has since landed on main independently, so that conflict is resolved in main's favour.The BirdWeather side
Their public API is GraphQL (
POST /graphql, no auth for reads), so the app sends one query per poll:topSpecies— the species roster with detection counts over the window.SpeciescarriesimageUrlplusimageCredit/imageLicense, which is what the plate is drawn from and what the stored attribution records.detections— the newest local detection per species, for the "last 19:40 at PUC-23115" half of the caption, plus the totals shown while the collection is still filling.Species.latestDetectionslooks like the obvious source for that second part and is not used: it is global, so a Belgian bounding box gets told about a station in the UK. Verified against the live API.Either a latitude/longitude/radius box or explicit station IDs select what to listen to. Stations win when both are set, because BirdWeather intersects them. Species heard fewer than
minDetectionstimes in the window are skipped — BirdNET guesses at the edge of its confidence produce one-off species that aren't worth a plate.The plate style now asks for the bird mid-song with a small hand-drawn sonogram in the margin, which is what the preview shows.
Test plan
nim c -r src/frameos/tests/test_bird_song_journal_scene.nim— passes. Mock BirdWeather serves two well-heard species plus one below the detection floor and one with no reference photo; asserts only the usable two are logged, one plate drawn + verified per render, HTML credits stored as plain attribution,pollMinuteskeeping later renders off the network, the collection cycling, and a configured station ID replacing the bounding box in the query.backend:pytest app/api/tests/test_repositories.py— 19 passed, with the new template asserted in the samples repository.Notes
test_repo_scenes_esp32.nimdoes not compile on main right now (availableRenderBytesOverrideundeclared), so the new scene could not be checked through it. Pre-existing and untouched here.image_generationtool returns HTTP 520 for the local OpenAI key across models, while plain Responses calls and/v1/images/editsboth work. The shipped app still uses the Responses tool exactly as Bird field journal scene #262 does; the preview was generated through the Images API instead. Might be worth checking whether that's account-specific before either scene is relied on.🤖 Generated with Claude Code