Restore matchability of spot-crop (unity) annotations on the React Encounter page#1656
Open
JasonWildMe wants to merge 9 commits into
Open
Restore matchability of spot-crop (unity) annotations on the React Encounter page#1656JasonWildMe wants to merge 9 commits into
JasonWildMe wants to merge 9 commits into
Conversation
React Encounter page gates the New Match button on an isTrivial/bbox geometry proxy, which hides genuinely matchable whole-image spot-crop annotations (matchAgainst=true, acmId set). Spec proposes serializing the real matchability signal and gating the UI on it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop SearchPages ImageModalStore from scope (shared ImageModal is Encounter-only; SearchPages uses ImageGalleryModal, no New Match button) - Reword root cause: unity annotations are dropped by isTrivial, not by an empty bbox (getBbox returns a positive full-image box for unity features) - Document residual geometry-proxy consumers (match-results re-selection, edit, task-id) as a known out-of-scope limitation - Generalize: gate supports any annotation meeting matchAgainst && acmId Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…legation test) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Encounter.opensearchDocumentSerializer now emits matchAgainst and acmId per annotation so the React Encounter page can gate matching on real eligibility instead of an isTrivial/bbox geometry proxy. Additive, served live via jsonForApiGet (no reindex). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Computes matchability from raw annotations (matchAgainst && acmId), filtered by encounterId, without the isTrivial/bbox filter of encounterAnnotations. ImageModalStore delegates to it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ImageCard and ImageModal now enable New Match when the image has an annotation with matchAgainst && acmId, instead of the isTrivial/bbox geometry proxy that hid matchable whole-image spot-crop annotations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use a?.acmId != null instead of truthiness so an annotation with matchAgainst=true and acmId="" is treated as matchable, matching Annotation.hasAcmId() / MatchEligibilityQuery. (Codex review) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1656 +/- ##
==========================================
+ Coverage 51.49% 51.51% +0.01%
==========================================
Files 311 311
Lines 12261 12268 +7
Branches 3956 3850 -106
==========================================
+ Hits 6314 6320 +6
- Misses 5665 5666 +1
Partials 282 282
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Problem
On the React Encounter page, a spot-mapping crop annotation displays with no annotation boundary and a grayed-out "New Match" button, even though the annotation is genuinely matchable (
matchAgainst=true,acmIdset, validiaClass/viewpoint) and shows as matchable inobrowse.jsp.Root cause
Spot-mapping crops are created by
SubmitSpotsAndImage.javaas whole-image "unity" annotations (new Annotation(species, mediaAsset)→ a single unity feature) and are deliberately markedmatchAgainst=true.Annotation.isTrivial()returnstruefor any unity feature.The React Encounter page gated the "New Match" button on a geometry proxy (
!isTrivial && bbox width/height > 0) computed live inEncounter.opensearchDocumentSerializer(), and never consulted the real eligibility fields (matchAgainst,acmId) — which weren't even serialized in the encounter API response. The April-2026 "filter invalid bounding boxes" change therefore swept up these legitimately-matchable whole-image crops.Confirmed against the DB for the reported annotation
2d0da5d7-…: unity feature (FEATURE.TYPE_ID_OIDNULL),ANNOTATION.WIDTH/HEIGHT = 0,matchAgainst=true,acmIdset, MediaAsset = the crop.Fix
Serialize the real matchability signal and gate the button on it, mirroring the backend rule (
matchAgainst=true AND acmId IS NOT NULL):Encounter.opensearchDocumentSerializer): emitmatchAgainstandacmIdper annotation. Additive; served live viajsonForApiGet→Base.opensearchDocumentAsJSONObject(no reindex, no OpenSearch mapping change).EncounterStore.hasMatchableAnnotationsgetter reading the raw annotations (matchAgainst === true && acmId != null, filtered byencounterId), delegated byImageModalStore.ImageCardandImageModalgate the New Match button on it instead of theisTrivial/bbox proxy.The
encounterAnnotationsgetter, the boundary-drawingrectsfilter, andNewMatchStore.annotationIds(which already includes the annotation, filtered only byencounterId) are intentionally unchanged. This is strictly more correct: genuine placeholder annotations (matchAgainst=false) stay hidden, while any legitimately matchable whole-image annotation reappears.Out of scope (known limitations)
encounterAnnotationsgetter stays filtered), so a user cannot later re-open past match results for one from the annotation-selection UI. New Match itself works end-to-end (the initiate flow navigates straight to the fresh task's results). Deferred to avoid disturbing the edit/select/task-id flows.SubmitSpotsAndTransformImage.java(a different crop path that builds a real bounding-box feature and does not setmatchAgainst) is unaffected and out of scope.Testing
EncounterApiTest#encounterApiGetTestextended to assertmatchAgainst+acmIdare serialized. PASS.hasMatchableAnnotations(true for amatchAgainst+acmIdunity annotation even whenisTrivial; false whenmatchAgainstfalse /acmIdmissing / differentencounterId; delegation viaImageModalStore) and for the New Match button enable/disable inImageCardandImageModal. All new tests PASS.origin/main(a known CI blind spot where Jest failures don't gate) — this change introduces zero new failures.Docs
Design spec and implementation plan included under
docs/superpowers/. Reviewed by Codex at the spec, plan, and final-diff stages (converged, no Major/Critical findings).🤖 Generated with Claude Code