detached 68ee891

fix(hints): log raw and prepared detection counts separately

commit
68ee891ede655ecbcff92bd9c049b2795df153b3
author
brice · · 2026-10-22 20:29 UTC
parent
4b3baff
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
1/1
refs
feat/hint-detector
2 files · +22 -1
M internal/adapters/hints/hints.go +2 -1
@@ -222,6 +222,7 @@ func (w *worker) scan(ctx context.Context, req ports.HintScanRequest, fr frame,
222222 t0 := time.Now()
223223 regions := tileRegions(req.Width, req.Height)
224224 dets, err := w.det.Detect(ctx, detFrame{width: req.Width, height: req.Height, stride: fr.stride, m: fr.m, regions: regions})
225+ rawN := len(dets)
225226 detectDur := time.Since(t0)
226227 if err != nil {
227228 fr.m.unmap()
@@ -241,7 +242,7 @@ func (w *worker) scan(ctx context.Context, req ports.HintScanRequest, fr frame,
241242 fr.m.unmap()
242243 }
243244 log.Info().Str("output", req.Output).Float64("capture_ms", ms(captureDur)).Float64("detect_ms", ms(detectDur)).
244- Int("regions", len(regions)).Int("raw_boxes", len(dets)).Int("targets", len(res.Targets)).Msg("hint scan")
245+ Int("regions", len(regions)).Int("raw_boxes", rawN).Int("prepared_boxes", len(dets)).Int("targets", len(res.Targets)).Msg("hint scan")
245246 return res
246247 }
247248
@@ -222,6 +222,7 @@ func (w *worker) scan(ctx context.Context, req ports.HintScanRequest, fr frame,
222 t0 := time.Now()222 t0 := time.Now()
223 regions := tileRegions(req.Width, req.Height)223 regions := tileRegions(req.Width, req.Height)
224 dets, err := w.det.Detect(ctx, detFrame{width: req.Width, height: req.Height, stride: fr.stride, m: fr.m, regions: regions})224 dets, err := w.det.Detect(ctx, detFrame{width: req.Width, height: req.Height, stride: fr.stride, m: fr.m, regions: regions})
225+ rawN := len(dets)
225 detectDur := time.Since(t0)226 detectDur := time.Since(t0)
226 if err != nil {227 if err != nil {
227 fr.m.unmap()228 fr.m.unmap()
@@ -241,7 +242,7 @@ func (w *worker) scan(ctx context.Context, req ports.HintScanRequest, fr frame,
241 fr.m.unmap()242 fr.m.unmap()
242 }243 }
243 log.Info().Str("output", req.Output).Float64("capture_ms", ms(captureDur)).Float64("detect_ms", ms(detectDur)).244 log.Info().Str("output", req.Output).Float64("capture_ms", ms(captureDur)).Float64("detect_ms", ms(detectDur)).
244- Int("regions", len(regions)).Int("raw_boxes", len(dets)).Int("targets", len(res.Targets)).Msg("hint scan")245+ Int("regions", len(regions)).Int("raw_boxes", rawN).Int("prepared_boxes", len(dets)).Int("targets", len(res.Targets)).Msg("hint scan")
245 return res246 return res
246 }247 }
247 248
M internal/adapters/hints/hints_test.go +20 -0
@@ -1,10 +1,12 @@
11 package hints
22
33 import (
4+ "bytes"
45 "context"
56 "encoding/json"
67 "errors"
78 "fmt"
9+ "github.com/bnema/zerowrap"
810 "image"
911 _ "image/png"
1012 "math"
@@ -396,3 +398,21 @@ func TestHintLateCaptureReaped(t *testing.T) {
396398 h.captured <- ports.CaptureDone{ID: creq.ID, Output: creq.Output}
397399 require.Eventually(t, func() bool { return len(h.captured) == 0 }, time.Second, time.Millisecond)
398400 }
401+
402+func TestScanLogsRawAndPreparedCounts(t *testing.T) {
403+ dets := make([]detection, maxWorkBoxes+5)
404+ for i := range dets {
405+ dets[i] = detection{x1: 10, y1: 10, x2: 30, y2: 30, score: .9}
406+ }
407+ det := newMockdetector(t)
408+ det.EXPECT().Detect(mock.Anything, mock.Anything).Return(dets, nil).Once()
409+ var out bytes.Buffer // scan logs synchronously on this goroutine
410+ ctx := zerowrap.WithCtx(context.Background(), zerowrap.New(zerowrap.Config{Level: "info", Format: "json", Output: &out}))
411+ w := &worker{det: det, dumpDir: "enabled"}
412+ w.scan(ctx, ports.HintScanRequest{Width: 100, Height: 100, Scale: 1}, frame{m: &mapping{}}, 0, ports.HintScanResult{})
413+ var fields map[string]any
414+ require.NoError(t, json.Unmarshal(out.Bytes(), &fields))
415+ require.Equal(t, float64(maxWorkBoxes+5), fields["raw_boxes"])
416+ require.Equal(t, float64(maxWorkBoxes), fields["prepared_boxes"])
417+ require.Equal(t, "hints", fields["component"])
418+}
@@ -1,10 +1,12 @@
1 package hints1 package hints
2 2
3 import (3 import (
4+ "bytes"
4 "context"5 "context"
5 "encoding/json"6 "encoding/json"
6 "errors"7 "errors"
7 "fmt"8 "fmt"
9+ "github.com/bnema/zerowrap"
8 "image"10 "image"
9 _ "image/png"11 _ "image/png"
10 "math"12 "math"
@@ -396,3 +398,21 @@ func TestHintLateCaptureReaped(t *testing.T) {
396 h.captured <- ports.CaptureDone{ID: creq.ID, Output: creq.Output}398 h.captured <- ports.CaptureDone{ID: creq.ID, Output: creq.Output}
397 require.Eventually(t, func() bool { return len(h.captured) == 0 }, time.Second, time.Millisecond)399 require.Eventually(t, func() bool { return len(h.captured) == 0 }, time.Second, time.Millisecond)
398 }400 }
401+
402+func TestScanLogsRawAndPreparedCounts(t *testing.T) {
403+ dets := make([]detection, maxWorkBoxes+5)
404+ for i := range dets {
405+ dets[i] = detection{x1: 10, y1: 10, x2: 30, y2: 30, score: .9}
406+ }
407+ det := newMockdetector(t)
408+ det.EXPECT().Detect(mock.Anything, mock.Anything).Return(dets, nil).Once()
409+ var out bytes.Buffer // scan logs synchronously on this goroutine
410+ ctx := zerowrap.WithCtx(context.Background(), zerowrap.New(zerowrap.Config{Level: "info", Format: "json", Output: &out}))
411+ w := &worker{det: det, dumpDir: "enabled"}
412+ w.scan(ctx, ports.HintScanRequest{Width: 100, Height: 100, Scale: 1}, frame{m: &mapping{}}, 0, ports.HintScanResult{})
413+ var fields map[string]any
414+ require.NoError(t, json.Unmarshal(out.Bytes(), &fields))
415+ require.Equal(t, float64(maxWorkBoxes+5), fields["raw_boxes"])
416+ require.Equal(t, float64(maxWorkBoxes), fields["prepared_boxes"])
417+ require.Equal(t, "hints", fields["component"])
418+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 26

Tags 10

↑↓ moveenter openesc close