---
name: feedback-system-process-invisible
description: A non-elevated "is it already running?" check cannot see SYSTEM-owned processes, so it silently returns "down" and you launch a duplicate. Bit me on 2026-08-23.
metadata:
  type: feedback
---

From a NON-ELEVATED shell, `Get-CimInstance Win32_Process` returns SYSTEM-owned
processes with a **blank `CommandLine`**. Any guard-style check of the form

```powershell
Get-CimInstance Win32_Process -Filter "Name like '%python%'" |
  Where-Object { $_.CommandLine -like '*live_monitor*' }
```

therefore matches NOTHING for a process launched by a SYSTEM scheduled task —
it reports "down" for something that is running fine, and the next step launches
a duplicate.

**Why:** most tasks here were upgraded to SYSTEM (`upgrade_tasks_to_system.ps1`)
so they fire without a logged-on user — see [[project-single-machine-consolidation]].
That fix is what makes the running processes invisible to a non-elevated check.

**How to apply:**
- Never conclude a pipeline process is down from a non-elevated CommandLine
  match. Cross-check with something SYSTEM cannot hide: the process's own
  artifacts — lock file (`research/.mm_maker_live.lock`), log mtime,
  `live_data/<today>.csv` mtime — or the guard log.
- Before starting anything by hand, read the guard log
  (`logs/monitor_guard.log`, `logs/mm_maker_live_guard.log`,
  `logs/pus_maker_guard.log`). The guards run every 5-15 min and log every
  restart; a fresh line there means it is already handled. Prefer letting the
  guard do it.
- A blank `CommandLine` on a python PID is a positive signal it is SYSTEM-owned
  and therefore probably a scheduled-task process, not an orphan. Identify it by
  start time vs the guard logs before killing anything.

## And you cannot KILL them either (2026-08-23)

Same root cause, worse consequence. A SYSTEM-owned process cannot be stopped
from a non-elevated shell: `Stop-Process -Force` returns **"Access is denied"**
and `taskkill /F /PID` fails the same way.

This matters because **editing AUTO_TRADE_* / stake config does nothing until
live_monitor is restarted** ([[feedback-restart-live-monitor-after-config]]), and
live_monitor is started by the SYSTEM-registered `SoccerMonitorGuard`. So after
a config change the config is written but INACTIVE, and nothing in a normal
session can complete the restart. live_monitor has no stop-file or self-exit
path (checked — only the maker has STOP_MAKER).

**The user must run this in an ELEVATED PowerShell:**

```powershell
Get-CimInstance Win32_Process -Filter "Name like 'python%'" |
  Where-Object { $_.CommandLine -like '*live_monitor*' } |
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
Start-ScheduledTask -TaskName 'SoccerMonitorGuard'
```

Elevation fixes both halves at once: an admin shell can read the CommandLine of
SYSTEM processes (so the filter matches) and can terminate them.

**Say this up front** when a task involves a live_monitor config change — do not
report the change as done, because it is not live until that restart happens.
A worthwhile fix would be a stop-file check in live_monitor's main loop, which
would make restarts possible without elevation.

**What happened 2026-08-23:** power cut at ~04:57, box rebooted 08:31. I checked
at 08:41:58, saw no live_monitor, and started one at 08:43:16. The guard had
already restarted it at 08:42:02 (pid 27356, SYSTEM, hidden). Two live_monitor
processes ran for ~90s. Killed the hand-started one; `live_data/2026-08-23.csv`
checked clean (6071 rows, 6071 unique, 0 duplicate lines), so no data damage —
but this is the same class of bug as the duplicate-maker incidents that
double-traded real money on 2026-08-16/17. See [[feedback-dedupe-both-sides]].
