← All reports

2026-11-12

task46: zero-cost checks C1, C2a, C2b, C3, C6, C7 (12 Nov 2026)

Weights checked: R2 models/sailscan-v39-rawkp8-l-full-candidate.pt (sha f8a8f024). Data: v39's own manifest ds-v30 (sha 684010b9, 5,459 records), frozen holdout 332 ids. Pod: SAILSCAN, 1x RTX 4090, ~36 min, ~$0.53, terminated and verified gone. No training, no retrain started. Raw logs in t46/res/out/.

ID Answer
C1 recipe Ultralytics 8.4.92, trained 19 Oct 2026, yolo26l-pose, kpt_shape [8,3]. SGD lr0 0.01, 100 epochs max (95 ran, patience 20), imgsz 960, batch 16, seed 0, deterministic. fliplr 0.5, flipud 0.3, degrees 20, mosaic 1.0, close_mosaic 10, scale 0.5, translate 0.1, shear 0, perspective 0, hsv 0.015/0.7/0.9, erasing 0.4, randaugment, pose 12, kobj 1, box 7.5, cls 0.5, dfl 1.5, rle 1.0. Shipped file = best.pt (its saved metrics equal results.csv epoch 75, the best-fitness epoch, not the last, epoch 95). Pose mAP50-95 best 0.705 vs last 0.698.
C1 sigmas Default. kpt_oks_sigmas is not in data.yaml. The library (8.4.92 loss.py, pose/val.py) uses COCO sigmas only when nkpt == 17, else ones/nkpt = 0.125 for our 8 points. No code reads another value. train.py has an --edge-sigma-scale patch, default 1.0 and not passed for v39, so inactive. (I could not instantiate the criterion object, since the E2E loss wrapper hides it, so this is from source plus yaml, not a printed tensor.)
C1 flip_idx data.yaml flip_idx: [7,6,5,4,3,2,1,0] (reversed list, one list for both flips).
C2a stored labels Raw stored order, v39 manifest, in the frame of each label's imageRef, first point right of last (x): train 5,684/16,367 stripes = 34.7%; test 432/1,207 = 35.8%. By source (train): ext-archive 3,430/10,510 (32.6%), app 1,782/4,458 (40.0%), human-retrace 472/1,399 (33.7%). Test: app 186/405, app-live-holdout 52/113, ext-archive 194/689. Scrambled (>2 px backward step along chord): train 49 (0.3%), test 2. App-labels' finer split (customer correction vs reviewer) is not in the manifest source field, so it is not split. This does not reach the model directly: train.py flips each stripe to ascending x at export (exported files: 0 descending, but 3.2% train / 1.3% test stripes have a small non-monotone x step).
C2b augmentation order 2,000 samples, v39 args. Share of stripes with reversed point order: no aug 0.00%; fliplr only 0.00%; flipud only 29.07%; rotation only 0.39% (degrees 20, so >90 deg reversal never happens); all augs on 29.85% (mosaic off 29.32%); fliplr+flipud forced = 100% (mechanism check). Cause: flipud reuses flip_idx and reorders points, though an up-down flip does not change left-to-right order. About 3 in 10 training stripes are seen with point k trained as point 7-k.
C3 visibility v39 raw output on the 332 test photos (1,155 stripes). The per-point visibility score is meaningful: overall median 0.985. Where the kink-trim rule removed points (fired on 9 stripes): removed points median vis 0.013, 93% below 0.5, vs kept points on the same stripes median 0.978 (12% below 0.5). Hook-spur fix fired 0 times and the fold-back/geometry check 0 times on these 332 raw outputs. Stripes touching the frame edge (77): edge points median vis 0.42 vs interior 0.99. So yes: the points the trim removes are the low-visibility ones, and the model already says which are off the photo. Training side: mosaic leaves >=1 point flagged invisible on 7,022 of 12,432 augmented stripes (56%); without mosaic 11%. Caveat: raw model only, no sidecar preprocessing or full chain; kink-trim n is small.
C6 training set Manifest 5,459 records; after holdout and frozen exclusions 5,095 (ext-archive 3,220, app 1,410, human-retrace 465). Actually exported by v39's train.py: train 3,732 images / 11,997 stripes, val 609 / 1,979, test 332 / 1,094. Empty-label images: 0. Duplicates: the audit's 421 is not reproduced but duplicates remain: exact copies 284 groups, 540 excess images (of 4,673); near-duplicates (dHash <=4) 541 clusters, 1,754 photos, 1,213 excess; 879 near-dup pairs cross splits (718 train-val, 128 train-test). Bottom-edge stripes (any point within 1% of bottom): train 0.53%, val 1.11%, test 0.18%. Left edge 5.9%, right 4.7%, top 0.8%.
C7 draft shown draft (the argmax). draftStable is computed in server/stripeMetrics.js but no file in app/, src/ or desktop/ reads it, so customers never see it.

Corrections to Section 1: - 1.5 is confirmed and larger than guessed, but the mechanism is flipud, not rotation (rotation 0.4%). - Stored labels are reversed ~35%, not "stored left to right"; export normalizes it. - C6 "421 duplicates": by exact md5 and dHash the count is different (above); the 421 came from a CLIP-based FiftyOne run I did not redo.

Not run (out of scope for task46): C4, C5, C8, all retrains.