← Commit history

Initial commit: app/svcwatch

John Lauer ·b3ffd1284a ·1mo ago
2 files changed +113
README.mdadded+51
@@ -0,0 +1,51 @@+# Service Containers++One dashboard for every Adom service container: what is healthy, what is down, why, and a restart button that runs the watchdog's own start command.++![The dashboard](screenshots/dashboard.png)++## It does not probe anything++`service-watchdog.sh` already checks every container every 5 minutes and writes one verdict per check into `~/.watchdog-state`. svcwatch reads those files. It never re-probes.++That is not laziness, it is the point. Mouser's `?live=true` burns a search slot exactly like a real query, so a dashboard that probed on every page load would spend the quota the service exists to spend on real work. Reading the verdict costs nothing, so the page can refresh every 15 seconds.++It also means staleness is a real signal. If the newest verdict is more than 15 minutes old, the page says the watchdog itself has stopped. That is the failure mode that once hid a 7.3 hour OAuth Gateway outage: one stalled SSH held the watchdog's lock, every later cron cycle exited silently, and nothing anywhere said so.++## What a card tells you++Each service shows every check the watchdog runs for it, and each check says what it means rather than what it measures. "Auto-deploy from main still works" beats "git-auth ok". A failing check replaces its description with the watchdog's actual reason.++Restart runs the exact `start_cmd` from that service's row in `service-watchdog.sh`, so the button can never drift from what the watchdog would do unattended. A service with no start command in `TARGETS` gets a disabled button and a tooltip saying to add one, rather than a button that would fail.++## On a phone++![Mobile layout](screenshots/mobile.png)++One 44px header row at every width. As space runs out the header sheds the meta line, then the subtitle, then the subject name. The status LED and the healthy count go last, because they are why you opened it.++## Settings++![Settings](screenshots/settings.png)++Refresh rate, idle shutdown, and which sections show. Every row states its default.++## Commands++```+svcwatch serve [--print-url]   start the server (self-backgrounds, prints the URL)+svcwatch show                  open or refresh the Service Containers tab+svcwatch status                one-line health of every service container+svcwatch health                is svcwatch itself up+svcwatch ls                    running instances, with version drift+svcwatch stop                  shut every instance down+svcwatch ui toast "..."        raise a toast on the page+svcwatch ui sweep              run a watchdog sweep now+svcwatch ui restart <svc> --reason "..."+```++`ui restart` refuses without a written `--reason`. Restarting a shared service interrupts whoever is using it, so the reason is recorded, not decorative.++## Adding a service++svcwatch keeps no service list. It reads the `TARGETS` rows in `~/bin/service-watchdog.sh`, so adding a row there makes the card appear with its host, port, SSH target and start command already filled in.
page.jsonadded+62
@@ -0,0 +1,62 @@+{+  "slug": "svcwatch",+  "title": "Service Containers",+  "type": "app",+  "version": "1.0.0",+  "description": "One dashboard for every Adom service container: what is healthy, what is down, why, and a restart button that runs the watchdog's own start command. Reads the watchdog's verdicts off disk, so it costs no extra probes and no vendor API quota.",+  "tags": [+    "cli",+    "dashboard",+    "monitoring",+    "services",+    "watchdog"+  ],+  "dependencies": {},+  "discovery_triggers": [+    "are my services up",+    "check my service containers",+    "is mouser down",+    "is digikey down",+    "is jlcpcb down",+    "service dashboard",+    "restart a service container",+    "why is my service down",+    "service health"+  ],+  "discovery_pitch": "Reach for svcwatch when someone asks whether their service containers are healthy, which one is down, or wants to restart one.",+  "sample_prompts": [+    {+      "label": "Health check",+      "prompt": "are all my service containers up?"+    },+    {+      "label": "Diagnose",+      "prompt": "why is the oauth gateway down?"+    },+    {+      "label": "Restart",+      "prompt": "restart the mouser service"+    }+  ],+  "metadata": {+    "activate": {+      "kind": "bridge",+      "skill": "svcwatch",+      "requires": [],+      "verbPrefixes": []+    }+  },+  "scripts": {+    "install": "./install.sh",+    "uninstall": "./uninstall.sh"+  },+  "hero": {+    "type": "image",+    "path": "docs/hero.png"+  },+  "visibility": "public",+  "author": {+    "name": "John Lauer",+    "email": "[email protected]"+  }+}\ No newline at end of file