feat(scanner): complete localized artifact quality checkpoint

This commit is contained in:
AzuTear
2026-07-11 15:59:19 +02:00
parent 639b0b7f59
commit 8b9f948c6b
215 changed files with 35440 additions and 7273 deletions
+627 -9
View File
@@ -19,6 +19,19 @@ This document contains Architecture Decision Records.
| ADR-011 | Retire alternate OCR comparison paths after current scanner baseline | Superseded | 2026-07-09 |
| ADR-012 | Separate live scan results, artifact inventory, and value evaluation | Accepted | 2026-07-09 |
| ADR-013 | Move high-speed scanning into the native helper and vendor IK inventorylists | Accepted | 2026-07-09 |
| ADR-014 | Separate roll efficiency from build fit and project only legal roll bounds | Accepted | 2026-07-10 |
| ADR-015 | Adopt a scanner-first Galaxy UI and explicit feedback primitives | Accepted | 2026-07-10 |
| ADR-016 | Default to the owned inventory and keep scan feedback session-bound | Accepted | 2026-07-10 |
| ADR-017 | Stream native capture jobs into bounded evaluation workers | Accepted | 2026-07-10 |
| ADR-018 | Gate Build-Fit behind a versioned evidence contract before scoring | Accepted | 2026-07-10 |
| ADR-019 | Repair five-star +0 main values only from structural rarity evidence | Accepted | 2026-07-10 |
| ADR-020 | Target only exact supported Genshin process names | Accepted | 2026-07-10 |
| ADR-021 | Require explicit profile assumptions and source-bound aggregate context | Accepted | 2026-07-10 |
| ADR-022 | Rank only source-bound Build-Fit evidence with profile expiry | Accepted | 2026-07-11 |
| ADR-023 | Fail-closed visual rarity gate and read-only non-five-star inventory | Accepted | 2026-07-11 |
| ADR-024 | Default renderer copy to English while preserving the English scanner boundary | Accepted | 2026-07-11 |
| ADR-025 | Make artifact deletion an app-local tombstone workflow | Accepted | 2026-07-11 |
| ADR-026 | Persist first-observed native run timing on one shared clock | Accepted | 2026-07-11 |
## ADR-001: Build A Local Electron App First
@@ -377,9 +390,9 @@ Adopt a split scan/result/inventory model:
- Add artifact detail evaluation before promoting broad recommendations.
- Add upgrade projection only as a detail-level feature, with worst/middle/best
projected value scores and clear uncertainty labeling.
- Keep the producer/consumer screenshot queue as a later implementation phase:
one game-control worker may click/scroll/capture, while OCR/parse/evaluation
workers can process bounded queued jobs once the UI/data contracts are stable.
- Use one game-control producer for click/scroll/capture and bounded downstream
OCR/parse/evaluation workers. Publish only fully evaluated entries into the
current-session result rail.
### Consequences
@@ -416,22 +429,627 @@ steps. Each native run writes `manifest.json`, `capture-jobs.jsonl`, and
`status.json`; downstream workers must consume those files instead of asking the
renderer to do per-artifact scanner work.
The first downstream worker is a post-capture processor that reads
The first downstream worker is a native result processor that tails
`capture-jobs.jsonl` and writes both `scan-results.json` and
`processing-report.json`. `scan-results.json` is the durable result contract:
one entry per captured artifact card with extraction status, artifact identity
when parsed, review state, and deferred value status. `processing-report.json`
remains the diagnostic OCR/parse report. The worker OCRs/parses after capture
and does not persist by default; DB writes require explicit opt-in after native
crop OCR is validated with live evidence.
when parsed, review state, and versioned value evaluation. `processing-report.json`
remains the diagnostic OCR/parse report. The worker may OCR, parse, and evaluate
while capture is still producing jobs, then drains the remaining queue after a
done or stopped producer. It does not persist by default; DB writes require
explicit opt-in after native crop OCR is validated with live evidence.
### Consequences
- Capture throughput can be optimized without renderer roundtrips per artifact.
- The scanner data source now matches IK's artifact names and set/piece keys.
Other vendored IK lists are data only until those values are actually scanned.
- Evaluation can remain deferred without blocking capture speed.
- Evaluation remains downstream and cannot block capture speed.
- Live safety stays read-only: no memory reads, hooks, injection, game-file
modification, deleting, feeding, enhancing, or spending resources.
- Non-16:9 layouts currently block in native preflight until layout support is
expanded.
## ADR-014: Separate Roll Efficiency From Build Fit And Project Only Legal Roll Bounds
### Status
Accepted
### Context
A universal Artifact quality score is misleading without a character, role,
team, and build target. However, the visible substat values do contain one
objective signal: how efficient their legal roll tiers were. Extraction
confidence is a third concept and must not be collapsed into either one.
Under-leveled Artifacts also invite false precision. A projection cannot know
which substat receives the next roll or which legal tier is selected.
### Decision
Implement `roll-efficiency-v1` as a context-free `0-100` score derived only
from rarity-specific legal roll values, legal total roll counts, and displayed
rounding. Persist reason codes and per-substat breakdown. Keep build fit
explicitly `deferred`; do not add set, main-stat preference, locked state, or
equipped state to roll efficiency.
Review, incomplete, or inconsistent results receive `review` or `unknown` and
no normal score. For under-leveled Artifacts, show a detail-only
Worst/Middle/Best bound from remaining +4 steps and legal roll tiers, only for
an unambiguously identified 5-star Artifact when all four current substats are
known. Label it as non-guaranteed; 4-star or rarity-ambiguous data stays
unavailable in V1.
### Consequences
- Users can compare roll-tier luck without being told that every high-roll
Artifact fits every build.
- Build-aware recommendation scoring remains a separate future contract.
- Existing saved native results can be evaluated without rescanning.
- Offline replay can hash derived results and detect non-determinism.
- Projection is conservative and unavailable when the fourth substat or clean
extraction is missing.
## ADR-015: Adopt A Scanner-First Galaxy UI And Explicit Feedback Primitives
### Status
Accepted. The original Builds lock is narrowed by ADR-022: the surface may now
show only source-bound, read-only evidence suggestions, never a general build
or optimizer claim.
### Context
The application exposed scanner setup, technical pipeline state, inventory,
review, prototype recommendations, overlay, and diagnostics with similar visual
weight. The default scan path was harder to understand than the underlying
workflow, while the Builds and triage surfaces could imply confidence that the
current Build-Fit contract and review data do not support.
The renderer also lacked one consistent contract for loading, mutation
feedback, focus, and motion. Local status text alone made successful promotion,
review, import, or export actions easy to miss.
### Decision
Adopt a scanner-first information architecture and tokenized Galaxy visual
system:
- Group Scanner, Artifacts, Review, and the explicitly labeled Builds preview
as the main workspace. Keep Overlay and Diagnostics as secondary tools.
- Lead the Scanner page with app/Genshin readiness and one primary start/stop
action. Keep source selection, scan scope, and manual capture under advanced
options while preserving all preflight and safety gates.
- Treat Review as scan-data correction. Do not derive or display trash, feed,
deletion, or universal quality judgments from extraction uncertainty.
- Keep Builds clearly bounded until the versioned Build-Fit contract exists.
Under ADR-022 it may show only source-bound, read-only evidence suggestions;
`roll-efficiency-v1` remains visible in Artifact detail but is not relabeled
as build suitability.
- Centralize semantic colors, surfaces, focus, depth, spacing, and motion in
Galaxy design tokens. Use shared skeleton, spinner, and toast primitives for
content loading and explicit mutation outcomes.
- Preserve durable progress and error state in the owning view. Toasts are
transient confirmation only. Respect `prefers-reduced-motion` and keep state
understandable through text/icons without relying on animation or color.
### Consequences
- A first-time user can follow the scan-to-review journey without opening
diagnostics or understanding the native pipeline.
- Technical evidence remains available but no longer dominates the default
inventory and scan surfaces.
- Loading and mutation feedback becomes consistent across features without
changing the scanner, review, or persistence authority boundaries.
- New renderer views must reuse the shared tokens and feedback semantics and
pass keyboard, reduced-motion, overflow, and desktop visual acceptance.
## ADR-016: Default To The Owned Inventory And Keep Scan Feedback Session-Bound
### Status
Accepted. The real Settings-UI Artifact-limit path is live accepted at 5/5, the
packaged row-limit path at one detected eight-column row is accepted at 8/8,
and the packaged full-owned-inventory baseline is accepted at 2,211/2,211 over
70 pages with current-package reprocessing at 136 Review (6.15%).
### Context
A small numeric default makes the main scan action behave like a sample even
when the user's intent is to import the whole owned Artifact collection. At the
same time, using the inventory capacity as the target would be incorrect: it is
not the number of owned Artifacts, and the native scanner does not yet detect
the physical end of the list reliably enough to stop an oversized target
without risking repeated bottom rows.
The Scanner also showed progress in a separate card while the larger left work
surface displayed onboarding or a capture. That split made the most important
running state harder to follow. Loading previous stored/native results into the
right rail at startup further blurred the distinction between this run and the
long-lived Artifact collection.
Reopening the inventory with `B` could theoretically replace many upward wheel
events, but it also introduces menu-toggle state, tab-selection coordinates,
and another guarded key/click sequence. It has not been live benchmarked as a
more reliable reset.
### Decision
- Default the user-facing scan scope to the entire currently owned Artifact
inventory.
- Read and validate the current owned count at scan start. Use that `current`
value as the hard target basis; never substitute the inventory capacity
`total`.
- If the current owned count is unavailable or invalid, block a full-inventory
scan with a reviewable reason instead of guessing.
- Offer one optional limit with either Artifacts or rows. Convert rows through
the detected grid column count and clamp both forms to the owned count and the
2,400-Artifact safety bound.
- Keep scope selection session-local so a new app launch returns to the full
owned inventory default.
- During a run, use the left main work surface for capture phase and
captured-versus-target progress. Keep the independently advancing OCR/parse/
evaluation progress beside the live results on the right. Remove the
duplicate standalone progress card.
- Keep the right result rail current-session only and empty on app launch.
Persisted history remains available in the Artifacts view.
- Retain the bounded, foreground-guarded wheel-to-top reset as the production
path. Treat `B` plus Artifact-tab reopening only as a future live A/B
experiment.
### Consequences
- The primary action matches the common collection-import intent without
hiding a partial numeric default.
- A row limit remains understandable while the helper still receives one
bounded Artifact count.
- Full-inventory start now depends on a trustworthy owned-count read and fails
safely when that evidence is missing.
- The Scanner separates ephemeral run feedback from the durable Artifact
collection and has one clear progress surface.
- The accepted 5/20/50/100 evidence validates the wheel reset and bounded native
engine. Real packaged Settings-UI runs additionally validate Artifact limit 5,
one detected row at 8/8, streaming overlap at 20/20, and the complete owned
target at 2,211/2,211 over 70 pages. The complete corpus passes the current
Review gate at 136/2,211 (6.15%), zero errors, and zero writes. A `B`-based
reset remains only an unaccepted experiment.
## ADR-017: Stream Native Capture Jobs Into Bounded Evaluation Workers
### Status
Accepted. Packaged 20-result and 2,211-result runs prove that evaluated result
cards become visible while native capture is still running; deterministic
service/UI tests cover ordering, deltas, reconciliation, and reduced motion.
### Context
Native capture already appends and flushes one line per crop to
`capture-jobs.jsonl`, but Electron previously opened that queue only after the
helper had captured the complete target. Users therefore saw no results during
long runs and then waited for a second, fully sequential phase. The right-side
result rail also could not explain evaluation independently from capture.
Starting the whole processor repeatedly on every poll would duplicate OCR,
race durable files, and make ordering non-deterministic. Treating a temporary
end-of-file as completion would lose jobs that the still-running producer adds
later.
### Decision
- Start one single-flight processor as soon as the active native run first
exposes a non-empty `runDir`.
- Tail complete JSONL records while the native producer is running. A temporary
empty queue means `waiting`, not completion; a partial final line is retried.
- Deduplicate jobs by sequence, run at most four OCR/parse/evaluation workers,
and publish completed results in canonical capture-sequence order.
- A result reaches the renderer only after extraction review gating and
`roll-efficiency-v1` evaluation have produced its final safe status.
- Keep capture and evaluation counters independent. The left workspace reports
capture progress; the right result surface reports evaluated/target plus
parsed, review, and error counts.
- Load live results as monotonic sequence deltas and reconcile against the full
durable result set before declaring a successful session complete.
- Do not finish processing until capture is terminal and every observed job is
drained. A user stop ends game input immediately but keeps already captured
jobs available for evaluation; the final session outcome remains `stopped`.
- Persist intermediate ordered `scan-results.json` snapshots so a renderer
refresh or process boundary does not make completed work disappear.
### Consequences
- Long scans provide useful, reviewable results before capture ends.
- Capture speed is isolated from OCR latency while bounded concurrency prevents
unbounded CPU/memory growth.
- Single-flight processing, sequence deltas, and final reconciliation prevent
duplicate cards, stale-run leakage, and false-complete summaries.
- The current-session rail can keep all results in top-to-bottom capture order;
newly mounted cards use motion only as an insertion cue and respect reduced
motion.
- Live acceptance must measure actual phase overlap, not infer streaming from a
correct final result count.
- A streaming end-to-end claim must use one shared wall clock from native start
through final result reconciliation. Capture and processing durations are
retained as separate diagnostics and must never be added when they overlap.
## ADR-018: Gate Build-Fit Behind A Versioned Evidence Contract Before Scoring
### Status
Accepted. The contract, validator, native-result adapter, deterministic five-
piece evidence verifier, four sourced profiles, safety tests, legacy production-
path separation, and the separate read-only ranker are implemented. ADR-022
defines the visible ranking/expiry policy; the V1 assessments remain score-free.
### Context
The repository already contained an early preset scorer that could emit
character recommendations and builds from local Artifact records. Its weights,
thresholds, inferred characters, and partial builds were useful as a prototype,
but they had no versioned provenance or validated Build-Fit semantics. Hiding
those suggestions in the Builds UI was not enough while real account snapshots
still calculated them internally.
Roll-Efficiency, OCR confidence, and character/build suitability are different
concepts. A high legal-roll score does not prove that a Set, Main Stat, or
Substat mix fits a target, while low or Review extraction data must never enter
downstream fit logic.
### Decision
- Introduce `build-fit-contract-v1`, `build-fit-input-v1`, and
`build-fit-assessment-v1` as separate shared contracts.
- Require stable identity/revision, game-versioned provenance, explained legal
Set plans, variable-slot Main-Stat priorities, relative Substat weights,
optional full-build aggregate targets, and explicit conflict policies.
- Enforce V1 safety floors of 80% overall extraction confidence and 70% on all
required identity/value fields. Contracts may be stricter but cannot weaken
those floors.
- Require final parsed/non-Review data and a canonical IK Set key. Missing or
uncertain evidence produces reason-coded blockers.
- Map safe facts and conflicts into structured evidence. Verify complete
five-piece slot/Set shape and sourced aggregate context without ranking it,
and keep V1 output at `score: null` plus `recommendationStatus: deferred`
until a sourced profile corpus and ranking formula are validated.
- Record Roll-Efficiency as separate context and never fold it into Build-Fit
eligibility or imply that it is a fit score.
- Stop running real local account snapshots through the legacy scorer. Keep
that implementation limited to explicit demo/test fixtures.
### Consequences
- Sourced profiles and ranking fixtures can evolve on the combination verifier
without changing the scanner/OCR authority boundary.
- Review, low-confidence, incomplete, or non-canonical data fails closed before
any character recommendation.
- The Builds page can show source-bound evidence candidates while remaining
explicit about scope, uncertainty, and missing non-Artifact context.
- No user-facing fit score exists yet; `eligible` means only safe input for a
future ranker.
- Complete-build aggregate targets stay `pending` unless an explicit non-
Artifact contribution references known contract sources; no character,
weapon, or team baseline is guessed.
- The detailed contract and next gates are documented in
[BUILD_FIT_CONTRACT_V1.md](BUILD_FIT_CONTRACT_V1.md).
## ADR-019: Repair Five-Star +0 Main Values Only From Structural Rarity Evidence
### Status
Accepted. The rule is implemented in the OCR parser, covered by positive and
ambiguity-preserving tests, and validated against the complete 2,211-crop corpus.
### Context
The first full-inventory parser pass routed 490 results to Review. Of the 388
low-confidence Main-Value cases, 360 were level 0 and already had four parsed
Substats. A lower-rarity Artifact cannot begin at level 0 with four Substats, so
that combination is structural evidence for five-star rarity. Without that
evidence, a +0 Main Value can be valid at several rarities and must stay
reviewable.
### Decision
- Derive the canonical five-star +0 Main Value only when `level === 0` and
exactly four Substats were parsed.
- Mark the repaired Main Value with explicit parser confidence; do not silently
generalize the rule to three, two, or incomplete Substats.
- Keep all ambiguous rarity cases in Review and retain reason-coded analysis of
the saved corpus.
### Consequences
- Current-package reprocessing reduced Review from 490 to 136 without
reclassifying any previously clean result into Review.
- 360 Main Values were repaired from structural evidence; ambiguous three-
Substat +0 Artifacts remain visible for review.
- Future rarity extraction can replace this inference, but it must preserve the
same fail-closed behavior when rarity evidence is uncertain.
## ADR-020: Target Only Exact Supported Genshin Process Names
### Status
Accepted. Both the native helper and PowerShell fallback use the exact whitelist;
the final packaged no-Genshin safety smoke passed with no source and no errors.
### Context
A broad process-name match containing `Genshin` allowed the assistant process
itself to look like a game target after the real client closed. Reusing a cached
HWND without validating its owning process could preserve the same unsafe state.
### Decision
- Recognize only `GenshinImpact` and `YuanShen` as supported game processes.
- Revalidate every cached HWND against the exact whitelist before returning it;
clear invalid cache state immediately.
- Apply the same behavior to the PowerShell fallback and keep the allow-list
covered by helper/static tests.
### Consequences
- Closing Genshin produces `genshinFound=false`, HWND `0`, an empty target
process, and no capture source even while the assistant remains open.
- New official client process names require an explicit reviewed allow-list
change instead of being picked up accidentally.
## ADR-021: Require Explicit Profile Assumptions And Source-Bound Aggregate Context
### Status
Accepted. The contract requires target assumptions and source-bound aggregate
context; the profile corpus, expiry gate, and Golden/adversarial context tests
are implemented.
### Context
Character recommendations vary with constellation, weapon, teammates, rotation,
and game version. A single ER threshold or Main-Stat order without those
assumptions would look authoritative while silently applying the wrong build
context. Artifact contributions alone also cannot prove a total-build stat such
as Energy Recharge because character and weapon values are outside the scan.
### Decision
- Require every V1 target to list non-empty, unique assumptions alongside its
role and description.
- Store curated candidates in a versioned corpus with game version, review time,
source version, and direct reference.
- Start narrowly with Furina off-field/Solo Hydro C0-C1 from the KQM Furina
Quick Guide labeled `Luna II`; do not generalize its 200%+ ER requirement to
other Hydro counts, C2+, no-Burst teams, weapons, or rotations.
- Treat Substat weights as documented ordinal source order only, never as damage
multipliers or a ranking formula.
- Evaluate a full-build aggregate target only when a complete non-Artifact value
references an allowed curated/user/imported source. Otherwise keep it
`pending`.
- Cross-check profile character and Set keys against vendored IK 6.7.0 data.
### Consequences
- Profiles remain auditable without turning hidden team/weapon assumptions into
Artifact-derived facts.
- Team, weapon, Favonius, and rotation inputs cannot be smuggled in as hidden
constants; callers must provide them explicitly.
- Profile expansion now carries a clear maintenance cost: source review, version
update, catalog validation, Golden fixtures, and adversarial safety cases.
## ADR-022: Rank Only Source-Bound Build-Fit Evidence With Profile Expiry
### Status
Accepted. `build-fit-evidence-ranking-v1`, four profile fixtures, explicit
source expiry, session-only aggregate context, and the read-only Builds surface
are implemented and offline-tested. Packaged renderer acceptance remains open.
### Context
The score-free V1 verifier can prove that five scanned Artifacts are structurally
safe and satisfy a profile's facts, but it intentionally cannot emit a damage
score. Leaving the Builds page locked forever would strand the validated
evidence, while turning Roll-Efficiency, raw OCR confidence, or arbitrary
substat weights into a fit score would overstate what the data proves.
Guide advice also changes with game versions. A version label and review date
alone do not prevent an old profile from silently continuing to rank an account.
Finally, native results are the only renderer-visible data source that preserves
both canonical IK Set IDs and per-field confidence; store records do not.
### Decision
- Keep `build-fit-assessment-v1` and
`build-fit-combination-assessment-v1` score-free (`score: null`).
- Add `build-fit-evidence-ranking-v1` as a separate, bounded, deterministic,
read-only ranker. It considers only complete eligible five-piece combinations
and returns at most three non-overlapping profile suggestions.
- Make the visible `evidenceCoverage` a product-rule coverage measure: sourced
Set-plan tier, variable Main-Stat priority, and ordinal Substat presence. It
is not a DPS, optimizer, Roll-Efficiency, or OCR-confidence score.
- Treat OCR confidence strictly as a hard gate. Do not use roll values, roll
efficiency, character ownership, team, weapon, rotation, or unrecorded
constants as ranking inputs.
- Require `provenance.validUntil` on every profile. Expired profiles fail closed
until a maintainer refreshes their direct source review.
- Permit required aggregate targets only from explicit, user-confirmed,
session-only non-Artifact context that references a declared local/user
source. Missing context keeps the profile deferred; it is never guessed or
persisted.
- Read Builds data only from the newest complete native result run. The Builds
surface does not scan, mutate review/store data, or send game input.
### Consequences
- The app can expose useful, inspectable profile candidates without pretending
that it is a complete optimizer.
- Users see why a candidate ranked and why a profile is deferred, including
missing full-build context or conflicts.
- Profile maintenance has an explicit renewal deadline and source fixture cost.
- A renderer/package acceptance is still required before this UI is called
live-accepted; scanner live evidence is not reused as UI evidence.
## ADR-023: Visuelle Seltenheit fail-closed und Nicht-5★-Ansicht ohne Spielaktion
### Status
Accepted
### Context
Die bisherige Roll-Efficiency-Auswertung kennt rarity-spezifische Regeln, hatte
bei neuen nativen Kartencrops aber keine direkte, persistierte Evidenz für die
sichtbare Sternreihe. Eine aus Level, Main-Value oder Substats abgeleitete
Seltenheit ist für einzelne etablierte Legacy-Regeln nützlich, darf aber eine
fehlende oder widersprüchliche aktuelle Sternreihe nicht stillschweigend in ein
5★-Ergebnis verwandeln.
Gleichzeitig sind explizit erkannte 14★-Artefakte für die Sammlung und
manuelle Sichtung relevant. Daraus folgt jedoch keine sichere
Bergungsentscheidung: Sperr-/Ausgerüstet-Status, Crop, Detaildaten und die
Spieloberfläche müssen weiterhin durch den Nutzer geprüft werden. Automatische
Bergung oder Quick Select wäre eine irreversible Spielaktion und widerspricht
dem Scanner-Sicherheitsrahmen aus ADR-004, ADR-010 und ADR-013.
### Decision
- Aktuelle native Capture-Jobs schreiben die direkte visuelle Stern-Evidenz als
`starCount`, `starConfidence` und `starSource` in den dauerhaften
Ergebnispfad.
- Nur explizit bestätigte 5★-Evidenz darf in `roll-efficiency-v1` eingehen.
Explizit bestätigte 14★-Ergebnisse erhalten `valueStatus: "excluded"` und
keinen Wert, keine Projektion und keine Store-Promotion.
- Wenn visuelle Stern-Evidenz vorliegt, aber `starCount` fehlt, ungültig oder
widersprüchlich ist, wird nicht auf 5★ geraten. Das Ergebnis bleibt `Review`
und seine Evidenz bleibt sichtbar.
- Legacy-Ergebnisse ohne das neue visuelle Sternfeld werden durch diese
Entscheidung nicht rückwirkend als visueller Beweis ausgegeben; für sie
gelten bis zum Rescan die bestehenden strukturellen Regeln.
- Die Inventory-Ansicht bietet einen separaten schreibgeschützten Filter
`Nicht 5★` nur für explizit erkannte 14★-Ergebnisse. Er zeigt Crop/Bild und
Detaildaten zur manuellen Prüfung, nicht die Behauptung "sicher bergbar".
- Es gibt weder eine Scan-Checkbox noch einen Ablauf für automatische Bergung
oder Quick Select. Diese Aktion bleibt verboten und aufgeschoben; ein
zukünftiger Vorschlag bräuchte eine neue explizite Sicherheits- und
Produktentscheidung und dürfte den bestehenden Nicht-Mutationsrahmen nicht
umgehen.
### Consequences
- Nicht-5★-Artefakte bleiben als vollständige, nachvollziehbare
Scan-Ergebnisse sichtbar, ohne die Wertung oder Empfehlungen zu verzerren.
- Die UI trennt klar zwischen `excluded` (direkt erkannte 14★) und `Review`
(unsichere Evidenz), statt beide als schwache 5★-Artefakte darzustellen.
- Replay-, Detail- und Promotion-Pfade müssen Stern-Evidenz, Ausschluss und
Review deterministisch erhalten.
- Der einzige zulässige nächste Schritt für einen Nutzer in der `Nicht 5★`-
Ansicht ist die manuelle Prüfung im Spiel; die App sendet dafür keine
Bergungs-, Auswahl- oder sonstige mutierende Eingabe.
## ADR-024: Default Renderer Copy To English While Preserving The English Scanner Boundary
### Status
Accepted
### Context
The application previously exposed a largely German renderer while its only
validated OCR/crop profile is the English Genshin UI. Treating the two language
concerns as one setting would either make a German-speaking user unable to
choose their application language or incorrectly imply that German Genshin OCR
is supported.
### Decision
- Make English the default renderer locale for a fresh, missing, or invalid
local preference.
- Offer German as a user-selectable Settings preference and persist it locally
under one application-scoped key.
- Keep message catalogs structurally aligned and route renderer copy through the
locale provider rather than hard-coded feature strings.
- Keep the scanner contract explicit: changing the application language changes
application copy only; Smart Capture remains validated for English Genshin.
- Preserve stable semantic UI hooks for renderer acceptance so tests do not
depend on a particular translated label.
### Consequences
- New users receive an English interface by default while German remains
available without a restart.
- The document language and accessible renderer labels track the selected
locale.
- Future Genshin OCR-language support requires separate crop, parser, corpus,
and live-acceptance evidence; it cannot be inferred from this setting.
## ADR-025: Make Artifact Deletion An App-Local Tombstone Workflow
### Status
Accepted
### Context
A wrong OCR read or wrong screenshot needs a way to disappear from the local
Artifact inventory. Directly mutating the game's inventory is prohibited, and
rewriting native `scan-results.json` would destroy the raw evidence needed for
replay, debugging, and corpus review. A delete control also needs to prevent an
active scan from racing a local cleanup.
### Decision
- Expose a confirmed local-delete control only in artifact detail.
- For native results, append an immutable entry to `deleted-results.jsonl` and
filter it at load time instead of rewriting `scan-results.json`.
- Delete a crop only after its resolved path is proved to be a PNG contained by
the selected native run directory.
- Block deletion while the target native run or its processor is active; make a
repeat deletion idempotent.
- Allow Store deletion only for one exact local record: either a Store-only row
or an explicitly selected record linked to the deleted native result.
- Keep the whole workflow behind main-process IPC. It must never focus Genshin,
call the input helper, or dispatch a game action.
### Consequences
- Users can correct local inventory mistakes without jeopardizing the game or
losing raw scan evidence.
- Tombstones become part of the local run contract and loaders/replay tooling
must apply them deliberately.
- The UI must communicate that the action removes app-local data only, and
confirmation remains mandatory because local data and screenshots can be
removed.
## ADR-026: Persist First-Observed Native Run Timing On One Shared Clock
### Status
Accepted
### Context
Native capture and downstream OCR/parse work overlap. Earlier reports could
show phase rates but did not retain one durable, validated endpoint-to-endpoint
clock for the current run. Adding capture and processing durations would double
count their overlap and produce a misleading end-to-end claim.
### Decision
- Write atomic `run-timing.json` records using
`native-scanner-run-timing-v1` in each native run directory.
- Record the first valid observation of request start, native scanner start,
capture start/end, processing start/end, durable result write, and final
result reconciliation. Later polling or retries cannot replace a marker.
- Derive request-to-durable and request-to-reconciled milliseconds directly from
their timestamps and validate marker ordering.
- Require a complete valid timing record and final count reconciliation for a
live streaming/end-to-end claim.
### Consequences
- Capture, processing, and end-to-end rate can be reported as distinct metrics
without double counting overlap.
- A historical timing observation cannot stand in for current-build live
evidence.
- Timing files are durable diagnostic evidence and must be included in native
smoke validation, not merely displayed in the renderer.