fix: unchain track 5 frames so one bad read cannot poison the rest

The chained attempt (1530bbc) fed each run's result into the next frame's
seed, so a wrong read on one frame carried into the ones after it. Runs are
independent again: every frame is seeded from the drawn shape, frames 2-5
with it grown x1.5 about its centre for motion tolerance. REQ-189, ui-spec
and tasks.md updated to the independent contract.
This commit is contained in:
asus committed 2026-10-05 12:35:17 +07:00
1 parent 1530bbc999
commit 9c95a4a759
4 files changed
+43 -34

No files matched your search

+9 -8
View File
@@ -9,8 +9,9 @@ import ReviewSidebar from '../components/ReviewSidebar'
import ExemplarFilterPanel from '../components/ExemplarFilterPanel'
import useExemplarPool from '../hooks/useExemplarPool'
// How much bigger the seed box gets before each frame after the first, so the
// object has room to have moved. Hand-tuned, not learned (REQ-189).
// How much bigger the seed box gets for each frame after the first, so the
// object has room to have moved. Hand-tuned, not learned (REQ-189). The box
// always derives from the drawn shape — never from a previous run's result.
const SEED_GROWTH = 1.5
// SAM3 assist wants one normalized [x0, y0, x1, y1] box (REQ-043). A bbox
@@ -413,19 +414,19 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
setError('')
try {
let tracked = 0
let seed = firstBox
const failures = []
for (let i = 0; i < ahead.length; i++) {
const targetFrame = ahead[i]
// The first frame uses the drawn box untouched. After that the object
// has had time to move, so the last result seeds a wider box.
const seedBox = i === 0 ? seed : growBox(seed, SEED_GROWTH)
// Every frame is seeded from the drawn box, never from a previous
// result, so a bad read on one frame cannot carry into the next.
// Frames 2-5 get it grown about its centre — the object has had
// time to move by then.
const seedBox = i === 0 ? firstBox : growBox(firstBox, SEED_GROWTH)
try {
const created = await api.assist(targetFrame.id, {
await api.assist(targetFrame.id, {
box: seedBox, class_id: current.class_id,
})
tracked++
seed = shapeBox(created?.geometry) ?? seed
patchFrameLocally(targetFrame.id, { annotation_count: (targetFrame.annotation_count ?? 0) + 1 })
} catch (exc) {
failures.push(`frame ${index + i + 2}: ${exc.message}`)