SIGN IN SIGN UP

Initial public release: sensorwatch hardware sensor monitor (#1)

* Initial public release: sensorwatch hardware sensor monitor

Rename the original MSI PSU monitor into sensorwatch — a general-purpose
HWiNFO64 shared-memory sensor monitor for Windows — and add the PSU-efficiency
study as the first worked example.

- Python monitor: reads Global\HWiNFO_SENS_SM2 via ctypes, filters by
  sensor-name patterns, logs JSON Lines with daily rotation + retention.
- Generalized the default sensor filter to capture-all (PSU shown as a
  commented example) so the tool reads as a general sensor monitor.
- Docs: README, SECURITY.md threat model, and planned C-core coding standards.
- examples/psu-efficiency: dataset (JSONL + Parquet), charts, and analysis
  showing the MSI MEG Ai1600T exceeds 80 PLUS Titanium at every measured load
  point (peak 94.5%, zero samples below 92%).
- MIT license and CONTRIBUTING guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address PR review: harden SHM reader, validate config, fixups

- hwinfo_shm: bounds-check the untrusted header (counts/offsets/element sizes)
  and parse a single VirtualQuery-sized `bytes` copy via `struct.unpack_from`, so
  a malformed or spoofed mapping returns None instead of crashing the process
  (SECURITY.md §1.3/§8.1, now marked implemented). Guard the kernel32 setup so
  the module imports cleanly off-Windows. Decode HWiNFO strings as cp1252 (fixes
  the temperature unit "°C") and strip control characters. Use
  WinDLL(use_last_error=True) + get_last_error().
- config: type-validate/coerce interval_seconds & retention_days; reject a
  non-list include/exclude instead of iterating characters; also look for a
  config next to the package (wheel installs), then the project root.
- __main__: register SIGTERM cross-platform (plus SIGBREAK on Windows); guard the
  sleep loop against a zero/non-int interval.
- logger: re-run retention on daily rollover so a long-lived process purges old
  files without a restart; keep the monitor alive on write OSError.
- examples/psu-efficiency: note the dataset is a post-processed PSU-specific
  export whose flat schema differs from the tool's nested JSONL output.
- Require Python >=3.12,<4.0; add uv.lock (pendulum + transitive deps).

Verified live against a running HWiNFO64: reads the MSI MEG Ai1600T (16 readings)
and the full reader->logger pipeline writes the documented nested JSONL on
CPython 3.12.13.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address round-2 nits: fail-fast off-Windows, strip patterns, tighten offset check

- __main__: exit immediately on non-Windows instead of looping and logging the
  same error every interval (Copilot).
- config: strip surrounding whitespace from include/exclude patterns so a
  pattern like " MEG Ai1600T " still matches (Copilot).
- hwinfo_shm: reject section offsets below HEADER_SIZE so an offset pointing into
  the header can't be parsed as sensor/entry data (kimi).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Leonard Janke <lcjanke2020@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A
Agent for Leonard Janke committed
833bc5abe22ba4b31b4667b3c17dc6d9c4e83e8e
Parent: d06d672
Committed by GitHub <noreply@github.com> on 6/27/2026, 8:59:01 PM