Which acquisition path does the privileged collector pin to for SMART/Health and identity reads: the official libnvme Python bindings (SWIG; attribute getters deliver normalized sysfs values), shelling out to nvme CLI JSON output (untrimmed strings, adds a binary dependency), or staying on smartctl -j plus a sysfs read for subnqn? Decide against dependency weight (ADR 0004's exact lockfile), privilege needs, packaging, and normalization consistency with the identity-key rules in the controller-identity research.
Parent map: [Chart Fenris's persistent TUI monitoring redesign](https://git.bongbetic.com/xavierk/Fenris/issues/1)
## Question
Which acquisition path does the privileged collector pin to for SMART/Health and identity reads: the official libnvme Python bindings (SWIG; attribute getters deliver normalized sysfs values), shelling out to `nvme` CLI JSON output (untrimmed strings, adds a binary dependency), or staying on `smartctl -j` plus a sysfs read for `subnqn`? Decide against dependency weight (ADR 0004's exact lockfile), privilege needs, packaging, and normalization consistency with the identity-key rules in the [controller-identity research](https://git.bongbetic.com/xavierk/Fenris/src/branch/research/controller-identity/docs/research/controller-identity.md).
xavierk
added this to the Wayfinder: Fenris persistent TUI monitoring redesign milestone 2026-08-31 15:16:05 +00:00
Slot-fill pointer from [Define cross-cutting acceptance criteria](https://git.bongbetic.com/xavierk/Fenris/issues/13): the accepted criteria at [docs/spec/acceptance-criteria.md](https://git.bongbetic.com/xavierk/Fenris/src/branch/main/docs/spec/acceptance-criteria.md) reserve **SLOT-B** for this decision. Fill the slot in the same commit as your resolution (same practice as ADR amendments).
xavierk
self-assigned this 2026-08-31 17:12:10 +00:00
Pin: counters and thermal evidence solely from smartctl -a -j <device>; controller identity (subnqn, sn, mn, fr, transport) solely from sysfs. No third path anywhere in the codebase.
Hard pin, no fallback: any acquisition failure fails the whole run (ADR 0005 retry/freshness absorbs it); never a partial sample — a transient read failure must not push a healthy drive down the degraded-identity path.
Normalization once, at write time: one function — strip trailing spaces/newlines, no case folding, empty-after-strip → blank; smartctl fields consumed as-is.
vid/ssvid: PCI sysfs node when present, null otherwise; transport from the NVMe class dir. Metadata only, never key components.
Prerequisites: make install verifies smartctl and fails cleanly otherwise; no Python dependency and no OS package beyond smartmontools (ADR 0004 §9 lockfile untouched).
Rejected: libnvme bindings (SWIG module not on PyPI — would couple the exact-lockfile venv to the system Python and distro packaging) and nvme CLI JSON (new OS package, untrimmed strings, subnqn from Identify rather than the kernel — the identity ladder would drop a rung on empty-NQN controllers).
Fills SLOT-B in the accepted criteria as AC-1–AC-5, in the same commit (b2ef130) as ADR 0006, per ticket #13's practice. Environment facts on record: the NVMe class sysfs dir carries model/serial/firmware_rev/subsysnqn/transport; vid/ssvid exist only at the PCI node; the dev host has libnvme's C library but no python3-libnvme.
Resolved in live grilling — all recommendations accepted and confirmed.
**Decision — [ADR 0006](https://git.bongbetic.com/xavierk/Fenris/src/branch/main/docs/adr/0006-collector-acquisition-path.md): smartctl counters, sysfs identity.**
1. **Pin**: counters and thermal evidence solely from `smartctl -a -j <device>`; controller identity (`subnqn`, `sn`, `mn`, `fr`, `transport`) solely from sysfs. No third path anywhere in the codebase.
2. **Hard pin, no fallback**: any acquisition failure fails the whole run (ADR 0005 retry/freshness absorbs it); never a partial sample — a transient read failure must not push a healthy drive down the degraded-identity path.
3. **Normalization once, at write time**: one function — strip trailing spaces/newlines, no case folding, empty-after-strip → blank; smartctl fields consumed as-is.
4. **vid/ssvid**: PCI sysfs node when present, null otherwise; `transport` from the NVMe class dir. Metadata only, never key components.
5. **Prerequisites**: `make install` verifies `smartctl` and fails cleanly otherwise; no Python dependency and no OS package beyond smartmontools (ADR 0004 §9 lockfile untouched).
Rejected: libnvme bindings (SWIG module not on PyPI — would couple the exact-lockfile venv to the system Python and distro packaging) and `nvme` CLI JSON (new OS package, untrimmed strings, `subnqn` from Identify rather than the kernel — the identity ladder would drop a rung on empty-NQN controllers).
Fills SLOT-B in [the accepted criteria](https://git.bongbetic.com/xavierk/Fenris/src/branch/main/docs/spec/acceptance-criteria.md) as AC-1–AC-5, in the same commit (b2ef130) as ADR 0006, per ticket #13's practice. Environment facts on record: the NVMe class sysfs dir carries `model`/`serial`/`firmware_rev`/`subsysnqn`/`transport`; `vid`/`ssvid` exist only at the PCI node; the dev host has libnvme's C library but no `python3-libnvme`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Parent map: Chart Fenris's persistent TUI monitoring redesign
Question
Which acquisition path does the privileged collector pin to for SMART/Health and identity reads: the official libnvme Python bindings (SWIG; attribute getters deliver normalized sysfs values), shelling out to
nvmeCLI JSON output (untrimmed strings, adds a binary dependency), or staying onsmartctl -jplus a sysfs read forsubnqn? Decide against dependency weight (ADR 0004's exact lockfile), privilege needs, packaging, and normalization consistency with the identity-key rules in the controller-identity research.Slot-fill pointer from Define cross-cutting acceptance criteria: the accepted criteria at docs/spec/acceptance-criteria.md reserve SLOT-B for this decision. Fill the slot in the same commit as your resolution (same practice as ADR amendments).
Resolved in live grilling — all recommendations accepted and confirmed.
Decision — ADR 0006: smartctl counters, sysfs identity.
smartctl -a -j <device>; controller identity (subnqn,sn,mn,fr,transport) solely from sysfs. No third path anywhere in the codebase.transportfrom the NVMe class dir. Metadata only, never key components.make installverifiessmartctland fails cleanly otherwise; no Python dependency and no OS package beyond smartmontools (ADR 0004 §9 lockfile untouched).Rejected: libnvme bindings (SWIG module not on PyPI — would couple the exact-lockfile venv to the system Python and distro packaging) and
nvmeCLI JSON (new OS package, untrimmed strings,subnqnfrom Identify rather than the kernel — the identity ladder would drop a rung on empty-NQN controllers).Fills SLOT-B in the accepted criteria as AC-1–AC-5, in the same commit (
b2ef130) as ADR 0006, per ticket #13's practice. Environment facts on record: the NVMe class sysfs dir carriesmodel/serial/firmware_rev/subsysnqn/transport;vid/ssvidexist only at the PCI node; the dev host has libnvme's C library but nopython3-libnvme.