---
name: GuruRMM operational rules — dev ownership, parity, builds, alerts, identify-by-IP, UNC
description: Six rules for working with GuruRMM. (1) RMM dev is Mike's domain — Howard does NOT code RMM (368/0 commits); GuruScan carve-out is Howard's. (2) Agent parity — Win+Linux+macOS in the same change. (3) Builds go through the Gitea webhook pipeline, never SSH. (4) Skip #bot-alerts for internal infra/build/dev; only alert on client/ticket impact. (5) Identify agents by IP, don't recon all candidates. (6) UNC paths in user_session need [char]92 — backslash literals get halved.
type: feedback
---

Technical reference (server / API / user_session / pipeline / agent sandbox): [[reference_gururmm]]. Project state + dev principles + pending setup: [[project_gururmm]].

---

## 1. RMM dev / bugs / roadmap are Mike's — never route them to Howard

GuruRMM code, bugs, roadmap, and architecture are **Mike's** domain. Do NOT send RMM dev/bug coord messages to Howard.

**Evidence (Mike, 2026-05-26):** GuruRMM repo has **368 commits by Mike, 0 by Howard.** I had escalated a stale roadmap bug (BUG-001) to Howard via a coord note; Mike corrected: *"Howard hasn't done ANY code work on RMM."* The `/feature-request` skill encodes the real model: Howard *submits* feature requests → Mike does the dev.

**How to apply:**
- RMM bug / dev / roadmap item → it's Mike's. Since Mike is usually the user, surface to him directly; don't send a coord note (a note to yourself is pointless).
- The broader principle: Howard defers backend / server / agent / DB / infra to Mike by default ("I don't like messing with things"). When wrapping an implementation with follow-up server-side items, note them as "deferred to Mike", not Howard's pending tasks. Don't proactively suggest Howard implement server or agent changes.

**GuruScan carve-out (`projects/msp-tools/guru-scan/`):**
- GuruScan IS Howard's project. Coord notes about GuruScan correctly go to Howard.
- Don't conflate GuruScan with GuruRMM because the names rhyme or GuruScan may integrate with RMM.
- **Leave GuruScan alone until Howard asks.** Don't proactively review, audit, or modify its code — even after a sync pulls in big GuruScan changes (Mike, 2026-05-27, after I offered to review Howard's `GuruScan.psm1` refactor unprompted).

See [[user_howard]].

---

## 2. Agent parity — Win + Linux + macOS in the same change

"Add feature X to the agent" means all three platforms in the same commit. Delivering Windows-only and leaving Linux/macOS for later is not acceptable — same as not finishing the task (Mike, 2026-05-15).

**Apply:**
- If the implementation differs by platform, write all three variants.
- If a real implementation isn't feasible on a platform yet, ship a working **stub + `// TODO(platform): <os> — <reason>`** in the same commit.
- A silent no-op without a stub and TODO is treated as a bug.
- Full matrix in `.claude/CODING_GUIDELINES.md` "GuruRMM Agent — Platform Parity".

---

## 3. Builds go through the Gitea webhook pipeline — never SSH manually

Never run `build-agents.sh` directly via SSH. All builds happen through the normal pipeline (push to `main` triggers it).

**Why:** manual runs execute as the SSH user (`guru`) instead of root, breaking log writes, artifact cleanup, and service restarts.

**To trigger a build without a real change:** push an empty commit:
```bash
git commit --allow-empty -m "chore: trigger build"
```

---

## 4. Skip #bot-alerts for internal infra / build / dev / recon

The `/rmm` skill says "post a one-line #bot-alert after every dispatch." Mike's clarification (2026-05-29): post a `#bot-alert` ONLY when the RMM command **directly affects a client endpoint or a ticket** (remediation, client machine change, ticket-linked work).

For internal infra (Gitea runner install, PLUTO build VM setup), CI/build orchestration, dev tooling, recon/inventory — **SKIP the alert**. Keeps the channel signal-high; it's a client/ticket activity feed, not a build log.

**Apply:** before dispatching via `/rmm` or the API, ask "does this touch a client or a ticket?" If no, do NOT call `post-bot-alert.sh`. Overrides the skill's blanket "alert after every dispatch" rule. See also [[reference_pluto_build_server]].

---

## 5. Identify the agent by IP, don't recon every candidate

When a task names a machine by its external IP (e.g. an auth-failure source from a server log), identify the RMM endpoint by **matching that IP** — don't dispatch recon to every candidate agent.

Mike pushed back twice 2026-05-30 for probing both Pavon machines to find which had a stray GuruConnect client when the offending external IP was already known. Matching IP is one lookup; reconning all candidates is noisy and slow.

**Apply:** get the source IP from the relevant server's logs first. Until GuruRMM stores agent IPs natively (todo `7459428e`, 2026-05-30 — no `local_ip`/`external_ip` fields yet), narrow candidates by site/client first, then have only the candidates report their external IP (`Invoke-RestMethod ipify`) and match. Once the server stamps `external_ip` from `X-Forwarded-For`, query `/api/agents` directly.

---

## 6. UNC paths in user_session need `[char]92` — backslash literals get halved

Never use `"\\CS-SERVER\..."` string literals in PowerShell scripts dispatched via GuruRMM `user_session` context. The backslash gets halved somewhere in the encoding pipeline, producing `\CS-SERVER\...` (a local path) instead of the UNC `\\CS-SERVER\...`.

The `user_session` execution wrapper processes escape sequences in the script text differently than `system` context, stripping one backslash from `\\`. `system` context (offline hive reg query) showed correct `\\CS-SERVER` output, so the issue is `user_session`-specific.

**Apply:** always build UNC paths explicitly when using `user_session`:
```powershell
$bs = [char]92
$base = "${bs}${bs}CS-SERVER${bs}homes${bs}Username"
```
Constructs `\\CS-SERVER\homes\Username` correctly regardless of context.
