Follow-up to the AttachThreadInput change: verified against an isolated repro
(a foreground-stealing window + the helper spawned exactly like the app) that
AttachThreadInput + clearing the foreground-lock timeout was NOT sufficient on
this Windows build - SetForegroundWindow still returned false and Genshin stayed
in the background.
The missing condition is "the calling process received the last input event".
Injecting a benign no-op input (a 0,0 relative mouse move, no cursor movement, no
menu-mnemonic side effect) right before SetForegroundWindow satisfies it. With the
nudge the repro now returns focused:true / setForegroundResult:true from a
background process while another app holds the foreground - the exact auto-scan
start scenario. Applied to both the C# sidecar and the PowerShell fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auto-scan aborted immediately with "Genshin konnte nicht in den Vordergrund
geholt werden". Root cause: the focus call runs in the background input/capture
helper process, and Windows' foreground lock silently refuses SetForegroundWindow
from a process that is neither foreground nor the last input source. When the user
clicks "Auto-Scan starten" the Electron window is foreground, so the helper's plain
SetForegroundWindow is dropped and focus stays false.
Fix (both the C# sidecar and the PowerShell fallback): before SetForegroundWindow,
attach our thread's input queue to the target (and current-foreground) window
thread with AttachThreadInput and clear SPI_..FOREGROUNDLOCKTIMEOUT, then restore.
This is the same technique Inventory Kamera and other reliable automators use; it
is what our helper was missing after the old ALT-tap workaround was removed on the
wrong assumption that equal integrity level is sufficient (that only covers UIPI
input injection, not foreground changes).
Sidecar recompiled + republished; electron build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
npm run dev failed with ERR_MODULE_NOT_FOUND for dist-electron/services/inputHelper.
Root cause: the electron program includes src runtime files (repositories,
layoutProfile, ocrPreprocess), so tsc's inferred rootDir is the project root and
it emits the entry at dist-electron/electron/main.js (with src at
dist-electron/src). package.json "main" still pointed at a stale flat
dist-electron/main.js fossil from an older build layout, whose extensionless
imports don't resolve under NodeNext ESM.
- package.json main -> dist-electron/electron/main.js.
- predev/build copy preload.cjs into dist-electron/electron/ (next to main.js,
where main.ts resolves it via __dirname).
- main.ts loads ../../dist/index.html (one level deeper now) for the packaged
window + overlay.
Verified: clean electron build emits only the nested layout; electron . loads the
main process past module resolution (only ERR_CONNECTION_REFUSED for the dev
server, expected standalone); npm run build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements ADR-009 (structure + preprocessing; exact IK fixed coordinates still
need calibration against a reference 16:9 screenshot).
- src/lib/layoutProfile.ts: pure, unit-tested geometry for the artifact screen -
detail rect, the four detail crops, inventory rect/count crop, 5-col grid,
16:9 detection, aspect label, and an off-16:9 support warning. Single source of
truth; electron/main.ts now delegates all crop/grid geometry to it and keeps
colour detection only as the detail-rect fallback.
- src/lib/ocrPreprocess.ts: pure, unit-tested Otsu binarization with inversion
(artifact text is the bright foreground) over a BGRA bitmap.
- main.ts: OCR now reads an upscaled + binarized copy of each crop; the original
crop is retained for the diagnostics UI. CaptureResult carries layout info
{ aspect, isSixteenNine, warning }.
NOTE: image preprocessing changes the OCR input and cannot be validated by the
text-level eval harness; it needs a live Genshin 16:9 capture to confirm/tune
(threshold, invert, upscale factor). 88 tests + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements ADR-008. native/input-helper is a self-contained .NET 9 console exe
speaking the identical JSON-over-stdin/stdout protocol as the old PowerShell
helper (ping/cursor/runtime/focus/click/scroll/bounds/capture), so the
InputHelperService interface is unchanged.
- Win32 interop compiled once (native exe), not per call.
- PerMonitorV2 DPI via manifest so click/capture coordinates stay correct on
mixed-DPI multi-monitor setups.
- capture returns base64 PNG bytes inline (imageBase64) instead of writing a
temp file per frame; the client handles both base64 and the PowerShell path.
- InputHelperClient prefers the exe and falls back to the embedded PowerShell
helper when the exe is absent, so the app still runs without the .NET build.
- main.ts resolves the exe (INPUT_HELPER_EXE env -> packaged resources/input-helper
-> native/input-helper/bin/publish). electron-builder ships it via extraResources.
- npm run helper:build; README documents the build + fallback.
Verified end-to-end through the compiled client: sidecar spawns, runtime info
and a base64 primary-screen capture return correctly. Build stays green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Import the existing Electron + React + TypeScript app as the version-control
baseline before the scanner rework (C# input/capture sidecar, resolution-anchored
layout profiles, OCR preprocessing, eval harness, rescan-merge, GOOD interop).
Housekeeping in this commit:
- Remove orphaned temp_inputhelper_block.ts (duplicate of the input-helper script).
- Ignore .claude/scheduled_tasks.lock local session state.
- Add .gitattributes to normalize line endings (LF in repo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>