DEV Community

Cover image for I Was Supposed to Fix Bugs. I Accidentally Built Two Features Instead. PC Workman 1.7.8 - Advanced Deep Learning AI, Supply Monitor and Health Keeper.
Marcin Firmuga
Marcin Firmuga

Posted on

I Was Supposed to Fix Bugs. I Accidentally Built Two Features Instead. PC Workman 1.7.8 - Advanced Deep Learning AI, Supply Monitor and Health Keeper.

I Was Supposed to Fix Bugs. I Accidentally Built Two Features Instead.

Friday Shipped & Scarred #11, the one where "no new features" lasted about 4 hours.


The plan after v1.7.7 (which shipped 20+ patches over one week): maintenance only. Fix the tester list. Test things.
Don't build anything.

I opened Setup & Drivers to verify a fix. My own PC had two GPU entries.

RTX - the one currently in the machine.
And GT 1030 - removed over two years ago.
Driver entries still in the registry, taking up space, doing nothing. Windows keeps dead hardware on life support forever.

I thought: if MY machine has this, everyone's does.

Three hours later, Ghost Driver Detection was in the codebase.


Ghost Drivers: Why WMI Lies To You

The obvious approach for "which devices are actually connected" is WMI. It's wrong.

WMI Win32_PnPEntity returns phantom devices too, that's exactly the problem I was trying to detect. You can't ask the ghost if it's a ghost.

What actually works: pnputil /enum-devices --connected.
PnPUtil queries the kernel's live device tree, not the registry cache.

# core/startup_watcher.py — _get_pnp_connected_names()
result = subprocess.run(
    ["pnputil", "/enum-devices", "--connected", "/class", guid],
    capture_output=True, timeout=10,
    creationflags=subprocess.CREATE_NO_WINDOW,
)
# Parse "Instance ID: ..." blocks - only hardware that's physically here right now

Enter fullscreen mode Exit fullscreen mode

The detection logic is a set diff:

  1. Registry drivers -> all installed entries for a device class
  2. Connected (pnputil) -> what's actually plugged in right now
  3. Gap -> ghost Any driver entry older than 20 months not in the connected set gets flagged. Red badge. Age info. One-click removal via pnputil /remove-device.

The feature shipped fast because the registry-reading infrastructure for the Drivers tab already existed.
I just needed the diff logic and a new card in Optimization Center.

Background App Hibernation:

Two Modes, Different Tradeoffs
Feature #14 of 16 planned for Optimization Center. Started as a bug investigation into idle process detection, turned into a full feature.

Detecting "idle" without false positives

The naive version: flag any process with CPU < 1% for 15 minutes. Problem: that includes background services, compiler daemons, git processes — anything that legitimately idles. The user shouldn't see those.

The actual filter in app_activity_tracker.py:

# Only surface apps that were ever in the foreground this session.
# If it was never in the foreground, it's a service — skip it.
if pid not in known_fg_pids:
    continue

# CPU guard: need 3 consecutive samples all below CPU_IDLE_PCT = 3.0%
# "below threshold" ≠ "not doing background work"
if len(samples) < CPU_SAMPLES_NEED:  # CPU_SAMPLES_NEED = 3
    continue
cpu_avg = sum(samples[-CPU_SAMPLES_NEED:]) / CPU_SAMPLES_NEED
if cpu_avg >= CPU_IDLE_PCT:
    continue
Enter fullscreen mode Exit fullscreen mode

The foreground window tracking uses
GetForegroundWindow and GetWindowThreadProcessId via ctypes, polled every 15 seconds. No external deps, just pure Windows API.

@staticmethod
def _foreground_pid() -> int:
    hwnd = ctypes.windll.user32.GetForegroundWindow()
    pid  = ctypes.c_ulong(0)
    ctypes.windll.user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
    return pid.value
The two sleep behaviors
LOW PRIORITY — SetPriorityClass(IDLE_PRIORITY_CLASS) via kernel32.

IDLE_PRIORITY_CLASS = 0x00000040

def _set_priority(pid: int, priority_class: int) -> bool:
    h = ctypes.windll.kernel32.OpenProcess(PROCESS_SET_INFORMATION, False, pid)
    if not h:
        return False
    try:
        return bool(ctypes.windll.kernel32.SetPriorityClass(h, priority_class))
    finally:
        ctypes.windll.kernel32.CloseHandle(h)
Process still runs. Gets CPU scheduling only when everything else is idle. Safe for apps you might need soon — Discord, Spotify.

FREEZE — psutil.Process.suspend(), which calls NtSuspendProcess internally.

if behavior == "freeze":
    proc.suspend()   # NtSuspendProcess under the hood
else:
    _set_priority(pid, IDLE_PRIORITY_CLASS)
Enter fullscreen mode Exit fullscreen mode

Zero CPU usage. Stays in RAM. Instant proc.resume() on wake. Good for things like updater processes that sit there all day doing nothing.

Turbo integration
The behaviors persist to hibernation_prefs.json per exe name. When TURBO mode activates (the existing power plan + service stop system in v1.7.7), hibernation behaviors apply automatically:

# optimization_services.py — _tpp_run()
ok = _pp_set(_TPP["turbo_guid"])
if ok:
    _TPP["active"] = True
    hibm = COMPONENTS.get("core.hibernation_manager")
    if hibm:
        hibm.apply_turbo_behaviors()   # applies all configured per-exe behaviors
Enter fullscreen mode Exit fullscreen mode

And reverses on Turbo deactivate:

def _tpp_restore():
    ok = _pp_set(original_guid)
    if ok:
        _TPP["active"] = False
        hibm = COMPONENTS.get("core.hibernation_manager")
        if hibm:
            hibm.restore_turbo_apps()   # wakes everything that was frozen
Enter fullscreen mode Exit fullscreen mode

Protected list of 30+ system process names (svchost.exe, MsMpEng.exe, dwm.exe, etc.) that never appear as hibernation candidates regardless of CPU or idle time.

The Parser Bug That Corrupted Polish Words

parser.py had an accent normalization step — a mapping of incomplete Polish fragments to their full forms, for users who don't type diacritics:

_ACCENT_MAP = [
    ("temperatur",   "temperatura"),  # fix: "jak jest temperatur" → "temperatura"
    ("wydajnosc",    "wydajność"),
    ("pamieci",      "pamięci"),
    # ...
]

def _normalize_accents(self, text: str) -> str:
    for stripped, accented in self._ACCENT_MAP:
        text = text.replace(stripped, accented)  # ← THE BUG
    return text
"temperatur" is a substring of "temperatura". When a user typed "temperatura cpu" (the complete word), str.replace matched the fragment inside it:

"temperatura" → "temperaturaa"
The double-a broke every pattern match. "temperatura cpu" was routing to hw_cpu instead of temperature because the multi-word phrase "temperatura cpu" no longer matched anything in the vocabulary.
Enter fullscreen mode Exit fullscreen mode

Fix: word-boundary matching.

def _normalize_accents(self, text: str) -> str:
    for stripped, accented in self._ACCENT_MAP:
        text = re.sub(r'\b' + re.escape(stripped) + r'\b', accented, text)
    return text
Enter fullscreen mode Exit fullscreen mode

\b only matches "temperatur" as a** standalone word*. "temperatura" **passes through untouched.*

This was caught during the 20-question intent routing test I ran post-audit.
"temperatura cpu" was scoring hw_cpu with 33% confidence.
Traced it to "temperaturaa cpu" matching nothing.

The Cache That Was Rebuilding on Every Message
Same file. Different problem. The folded pattern cache (used for accent-insensitive matching) was being built inside parse():

# OLD — runs on every single message
def parse(self, text):
    folded_patterns_cache = {
        intent: [self._ascii_fold(p) for p in patterns]
        for intent, patterns in INTENT_PATTERNS.items()
    }
    # ... scoring ...
Enter fullscreen mode Exit fullscreen mode

INTENT_PATTERNS has 82 intents, some with 30+ patterns each. Every user message rebuilt this entire dict from scratch. O(n×m) per call.

Fix: lazy class-level cache.

# NEW - built once, reused forever
class IntentParser:
    _folded_cache: Dict[str, List[str]] = {}

    def _get_folded_cache(self) -> Dict[str, List[str]]:
        if not self._folded_cache:
            IntentParser._folded_cache = {
                intent: [self._ascii_fold(p) for p in patterns]
                for intent, patterns in INTENT_PATTERNS.items()
            }
        return self._folded_cache
INTENT_PATTERNS is static at import time. There's no reason to rebuild it on message #47.
Enter fullscreen mode Exit fullscreen mode

82/82 - What Full Intent Coverage Actually Means
The hck_GPT AI engine routes messages using a hybrid system:
keyword scoring and Naive Bayes blend TO confidence score
and rule engine if ≥ 0.65, Ollama LLM if below.

Each intent has two config entries in hybrid_engine.py:

_CONTEXT_WINDOWS — how far back the AI looks for that intent type:

_CONTEXT_WINDOWS = {
    "hw_cpu":          5,      # last 5 minutes — live snapshot
    "temperature":     10,     # last 10 minutes
    "temp_comparison": 10080,  # last 7 days — trend comparison
    "weekly_trends":   10080,
    "session_digest":  480,    # 8-hour session summary
    "fan_speed":       5,
    # ... 82 total
}
_INTENT_HINTS - what Ollama is told to focus on per intent type:

_INTENT_HINTS = {
    "temperature":  "User is asking about system temperatures - be specific: CPU, GPU, and threshold warnings.",
    "temp_comparison": "User asks if PC is running hotter than usual - compare current temps to 7-day and 30-day historical averages.",
    "fan_speed":    "User is asking about fan RPM - show all fan sensors, current RPM, and if any fans are stalled.",
    "ram_flush":    "User wants to free up RAM - explain what's safe to close, give current top RAM consumers with MB values.",
    # ... 82 total
}
Enter fullscreen mode Exit fullscreen mode

Before this week: 34/82 had context windows. 54/82 had hints. Every unregistered intent fell through to a 30-minute default window and empty guidance.

Now all 82 have both. A query about "temperatur cpu" gets a 10-minute window (relevant recent data) and a hint telling the LLM exactly what to check.
A trend query like "is my cpu hot more than average" (temp_comparison) gets 7 days of data and the right comparison guidance.

The before/after on intent detection after fixing the parser
bug and filling the maps:

Query   Before  After   Context
temperatur cpu  hw_cpu (broken) temperature ✓ 10m
is my pc more warm than normal? hw_all RULE 5m  temp_comparison ✓ 10080m
make roast about my pc  unknown fun_roast ✓   30m
morning brief   unknown morning_brief ✓   10080m
is my cpu overclocked?  hw_cpu  overclock_check ✓ 5m
Test suite after all changes: 21/21.
Enter fullscreen mode Exit fullscreen mode

The hck_GPT Panel Startup Bug
One-liner symptoms: panel appears at the very top of the window on fresh launch. Toggle Max View Mode once and it snaps to the correct bottom position.

Root cause:

parent.after(350, lambda: self._animate(0, self.collapsed_h, duration_ms=700))
Enter fullscreen mode Exit fullscreen mode

The animation runs 350ms after panel creation. It reads parent.winfo_height() to compute y = parent_h - current_h.

But 350ms isn't enough on the first launch - the window hasn't been laid out yet, so winfo_height() returns 0.
Then y = 0 - 34 = -34, clamped to 0. Panel at the top.

Max View Mode triggered a geometry change, which forced a re-layout, which gave correct winfo_height().

Fix:

def _animate(self, start_h, end_h, duration_ms=200, on_end=None):
    parent_h = self.parent.winfo_height()
    if parent_h < 50:
        # Window not rendered yet — retry in 80ms
        self.frame.after(80, lambda: self._animate(start_h, end_h, duration_ms, on_end))
        return
    # ... normal animation
Polls until the parent has an actual height. No arbitrary sleeps, no one-shot 350ms guess.
Enter fullscreen mode Exit fullscreen mode

The Numbers

2 unplanned features shipped (Ghost Drivers, Background App Hibernation)
15/16 Optimization Center features live
82/82 intents with context windows + LLM hints (was 34/54)
14 vocabulary patterns fixed or added
1 parser bug causing word corruption
1 startup positioning bug in hck_GPT panel
21/21 automated tests passing
I was supposed to fix bugs. I fixed the bugs. I also shipped two features. I have no explanation.

Stack & Links

PC Workman is a real-time Windows system monitor with embedded AI assistant (hck_GPT). Open source, Python 3.9+ / Tkinter, Windows 10+.

GitHub: github.com/HuckleR2003/PC_Workman_HCK
Medium (narrative version): link
Support: Coffee or Github :)
Marcin Firmuga - HCK_Labs - solo dev, Poland.
11 months. Still shipping.

About the Author

I’m Marcin Firmuga. Solo developer and founder of HCK_Labs.

I created PC Workman, an open-source, AI-powered PC resource monitor who learns, after time, your natural PC behavior (spikes, voltage, temps, usages) built entirely from scratch on dying hardware during warehouse shifts in the Netherlands.

Before this: game translations, PC technician internships, warehouse operations in multiple countries, and countless failed projects I never finished.

But this one? This one stuck.
1000+ hours of code. 4 complete UI rebuilds. 16,000 lines deleted.
3 AM all-nighters.Energy drinks and toast.

And my own hck_GPT AI, building for months to give a PC Workman a brain and heart.
And finally, an app I wouldn’t close in 5 seconds. That’s the difference between building and shipping.

Top comments (0)