Improve scanner repeatability guardrails

This commit is contained in:
AzuTear
2026-07-09 10:21:13 +02:00
parent 13fd46c104
commit c10f17b4ef
13 changed files with 356 additions and 39 deletions
+43 -5
View File
@@ -268,10 +268,20 @@ Latest live timing evidence on 2026-07-08:
signature `2026-07-08-direct-gdi-reviewfix` completed `20/20`, `18` stored,
`0` review, `2` duplicates, `0` misses, `7973 ms` elapsed, or
`399 ms/artifact`. 3 artifacts/second is not proven.
- Follow-up 3 artifacts/second attempts on 2026-07-09:
after the distinctive partial piece parser fix, the best clean repeatability
run reached `336 ms/artifact` with `20/20` parsed, `0` review, `0` misses,
`318 ms` average capture roundtrip, and `138 ms` roundtrip overhead. Later
runs with crop priority and image-payload cleanup stayed clean but ranged
around `346-351 ms/artifact`; the strict `333 ms/artifact` budget remains
unproven.
- Rejected speed experiments:
detail-region capture, `GAA_OCR_WORKERS=5`, DataURL-to-buffer decode, and
substat OCR `PSM.SINGLE_COLUMN` were all live/benchmark tested and were slower
than the direct-GDI baseline. Keep `GAA_OCR_WORKERS=4` for current runs.
than the direct-GDI baseline. Later checks also rejected skipping
`analyzePaimonMenu`, skipping lock-state as a production shortcut, reducing
the artifact-level crop scale, and `GAA_OCR_WORKERS=6` as the default.
Keep `GAA_OCR_WORKERS=4` for current runs.
- Quality-gated current-vs-IK comparison:
`npm run scan:goal:compare:validated` produced
`outputs/live-soak/2026-07-08T18-38-35/scan-performance-assessment.json`
@@ -449,15 +459,17 @@ uses the default `current` scan engine; use `scan:goal:ik` for a native
IK-traineddata scan pass. Use `scan:goal:compare` to run both scan engines
back-to-back with the same limits and one combined CSV. The CSV is the quickest evidence for
`averageMsPerParsed`, `activeAverageMsPerParsed`, `averageCaptureMs`,
`averageCaptureRoundTripMs`, `averageCaptureRoundTripOverheadMs`,
`captureP50Ms`, `captureP90Ms`, `averageOcrMs`, `ocrP50Ms`, `ocrP90Ms`,
`averageCardReadyMs`, `averageScrollReadyMs`, `artifactsPerMinute`, and
`projectedMsFor100`.
The run also writes `scan-performance-assessment.json`, which groups results by
limit, picks the best qualified engine, and labels the dominant bottleneck as
OCR, capture, card-ready, or scroll-ready. A qualified winner must finish the
run, parse the requested count, keep miss rate under 2%, and keep review rate
at or below 15%; review and miss rates are penalized before active average speed
is used as the tie-breaker. For IK-target claims, check `goal100Decision`; it
OCR, capture-roundtrip-overhead, capture, card-ready, or scroll-ready. A
qualified winner must finish the run, parse the requested count, keep miss rate
under 2%, and keep review rate at or below 15%; review and miss rates are
penalized before active average speed is used as the tie-breaker. For IK-target
claims, check `goal100Decision`; it
must read `qualified-comparison: winner=<engine>`, and
`goal100.comparisonComplete` must be `true` so a single-engine 100-artifact run
is not mistaken for a current-vs-IK comparison.
@@ -478,12 +490,38 @@ instead of the final 100-artifact proof. Add `--summary` when you want a short
report-ready PASS/FAIL output that includes the input assessment path and
assessment `createdAt` timestamp.
Optional budget flags are useful for the current speed work:
```powershell
npm run scan:assessment:validate -- --latest --summary --limit=20 --max-active-average-ms=333 --max-capture-roundtrip-overhead-ms=120
```
`--max-active-average-ms=333` is the strict 3 artifacts/second check. Use a
separate `--max-capture-roundtrip-overhead-ms` budget when deciding whether the
next optimization belongs in native capture transport instead of OCR.
Single-engine repeatability runs may be validated with `--allow-single-engine`,
but that mode is only for repeatability evidence and must not be used for IK
parity claims.
`npm run scan:goal:compare:validated` is the preferred final command: it runs
the live preflight first, then the full comparison, and then validates the
newest assessment with `--summary`. Use
`npm run scan:goal:compare:validated:wait` for the same final flow when starting
immediately after UAC.
For later-session repeatability without changing OCR engines, use:
```powershell
npm run scan:repeatability:wait
```
That command runs the current visible-inventory engine at 20, 45, and 100
artifacts, then validates the 100-artifact result as single-engine evidence.
It uses the `live-soak.ps1 -RepeatabilityRun` switch instead of passing a
comma-separated `-Limits` value through npm/cmd, because Windows argument
parsing can collapse `20,45,100` into one unsafe number. The script also refuses
limits above 1800 as a final guard.
The assessment ranking can be verified without Genshin or the Electron app:
```powershell
+5
View File
@@ -15,6 +15,7 @@ npm run eval:review-candidates # export unconfirmed review samples for human la
npm test # runs the eval gate alongside the rest of the suite
npm run scan:assessment:test # verifies quality-first scan ranking logic
npm run scan:iterate:compare:validated:wait # 20-artifact live comparison
npm run scan:repeatability:wait # 20/45/100 current-engine repeatability
npm run scan:goal:compare:validated:wait # final 100-artifact live comparison
```
@@ -22,6 +23,10 @@ The report prints exact-match rate, overall field accuracy, a per-field
breakdown (critical fields marked with `*`), and every failing case with an
`expected "..." got "..."` diff.
Repeatability runs are single-engine evidence. Use them to prove that the
visible-inventory scanner stays stable across later sessions, but keep
current-vs-IK claims on `scan:goal:compare:validated:*`.
## How it works
- `src/eval/ocrEvalHarness.ts` - pure metric functions. `runOcrEval(cases)`
+38 -4
View File
@@ -144,6 +144,37 @@ Current status after the 2026-07-09 merge to `main`:
end-to-end capture roundtrip time. Use `averageCaptureRoundTripMs` and
`averageCaptureRoundTripOverheadMs` in the next `limit=20` live iteration to
decide whether the next cut belongs in native capture transport or OCR.
- **Repeatability and capture-overhead guardrails (2026-07-09)** -
`scripts/live-soak.ps1` now writes capture roundtrip and roundtrip-overhead
timing into `scan-performance-assessment.json`. The assessment validator can
enforce optional speed budgets with `--max-active-average-ms` and
`--max-capture-roundtrip-overhead-ms`, and `npm run scan:repeatability:wait`
runs 20/45/100 current-engine passes as repeatability evidence without
presenting them as an IK comparison. `-RepeatabilityRun` now sets those limits
inside PowerShell, and the script refuses unsafe limits above 1800 so npm/cmd
argument parsing cannot accidentally turn `20,45,100` into one oversized run.
- **Distinctive partial piece recovery (2026-07-09)** - a live repeatability run
exposed four identical OCR misses where the piece name was read as
`Wontiroms Creation pan`. The parser now derives a piece only when a long OCR
fragment uniquely matches exactly one known artifact piece. This recovered the
local case as `Sharpness That Ceased Upon Wondrous Creation` /
`Disenchantment in Deep Shadow` without adding a broad fuzzy exception.
- **Repeatability live pass after parser fix (2026-07-09)** -
`outputs/live-soak/2026-07-09T09-29-11/scan-performance-assessment.json`
captured a clean current-engine 20-artifact run: `20/20` parsed, `0` review,
`0` misses, `336 ms/artifact` active average, `318 ms` average capture
roundtrip, and `138 ms` average roundtrip overhead. The strict 3 artifacts per
second budget still failed by 3 ms (`336 ms` vs `333 ms`).
- **3/s follow-up experiments (2026-07-09)** - tested and rejected several
shortcut-style optimizations because live runs got slower or added risk:
skipping Paimon-menu analysis, skipping lock-state as a production shortcut,
reducing the artifact-level crop scale, and raising the OCR worker pool to 6.
The kept low-risk changes are fast-profile OCR crop priority and avoiding a
duplicate DataURL string when the native helper already returns Base64. A
follow-up clean 20-artifact run after payload cleanup reached `351 ms/artifact`,
`331 ms` capture roundtrip, and `146 ms` roundtrip overhead, so the next
credible 3/s work is native capture transport/roundtrip reduction, not UI
recommendation work.
- **3/s live attempt (2026-07-08)** - the missing-detail-preview review trigger
was fixed and tested. The best clean 20-artifact run reached `7285 ms`
(`364 ms/artifact`, about `2.75 artifacts/second`) with 0 review and 0 misses.
@@ -218,14 +249,17 @@ resolution or without UI work best tested live:
substat OCR time, or a larger capture pipeline change that avoids full-frame
PNG/Base64 transport without hurting safety checks. The target remains
`<= 6667 ms` elapsed for 20 parsed artifacts with 0 misses and no silent OCR
review regression.
review regression. The latest clean 20-artifact repeatability run reached
`336 ms/artifact`, so 3/s remains close but unproven.
6. **Broader scan soak test** — direct-GDI current-engine runs now passed at
`20/20`, `45/45`, and `100/100` with 0 misses. Continue with repeat runs if
duplicate rate needs tuning.
`20/20`, `45/45`, and `100/100` with 0 misses. Continue with
`npm run scan:repeatability:wait` in later sessions to check duplicate rate,
scroll behavior, and capture roundtrip timing without changing defaults.
7. **Repeatability pass** — repeat the qualified current-vs-IK-traineddata run
in a later live session before making major OCR-engine defaults or speed
claims beyond this environment.
claims beyond this environment. Current-engine-only repeatability is useful
evidence, but it is not an IK parity claim.
Visible-page limits up to 20, scroll/page-transition limit 45, the final
100-artifact current-vs-IK-traineddata comparison, equipped footer live smokes,