← back to Stack Map Viewer
README.md
49 lines
# Stack Interconnection Map — viewer
A **Mac2-local** admin/introspection tool: a live map of Steve's stack — skills, agents,
projects, cron/launchd jobs, the approval queue, the reversible-action ledger, and a
full **vendor-scraper freshness + health board**.
- **URL:** http://127.0.0.1:9768 · **auth:** Basic `admin` / `DW2024!` (a 401 to an
unauthenticated request is the *healthy* signal, not an error).
- **Process:** pm2 `stack-map` (`server.js`), `pm2 save`d so it survives reboot.
- **Local-only by design:** reads the local filesystem (`~/.claude/skills`, `~/.claude/agents`,
`~/Projects`, `~/Library/LaunchAgents`, the approval queue) and the local `dw_unified`
socket (`host=/tmp`). It **cannot run on Kamatera** without a rewrite to read remote data —
it *is* the Mac2 introspection tool. Remote access, if ever wanted, = proxy `:9768`, don't relocate it.
## Durability (why you don't have to babysit it)
The fleet **keep-alive** watchdog (`~/.claude/skills/keep-alive`, launchd
`com.steve.fleet-keepalive`, every 60s) monitors every pm2 process *including this one*
(not in its `exclude.txt`) and restarts it if it goes **HTTP-dead while pm2 still says
"online"** — the one silent failure mode `pm2 save` alone doesn't cover. keepalive.js
treats this app's fast 401 as alive (TK-11677), so it won't false-restart. Nothing to
register; it's covered by default. Verified 2026-09-22: `strikes:0`.
## Views (top toolbar)
- **Map** — draggable interconnection graph (layout persists in localStorage).
- **Tree** — recursive collapsible drill of every category.
- **Treemap** — d3 area-by-member-count.
- **Scrapers ⏱** — all ~168 vendors ranked by staleness, with **Last scrape · Age ·
Health (✓verified / ✗broken / ⊘discontinued / ⏸paused / ○unmonitored) · History
(cadence) · Rows · Table**. Click a ◆ row for its 5W card.
- **📅 as-of date** on the nav bar = the live data's scan time.
## How it works
- `server.js` — Node http server, no deps. Live-scans the filesystem + `dw_unified` on each
request (20s stats cache, 15s drill cache). Basic-auth gate. Endpoints: `/api/stats`,
`/api/list`, `/api/drill?type=&id=`, `/api/scrapers`.
- `index.html` — single-file frontend (inline CSS/JS), 4 views + a drill drawer with the
who/what/where/why/when + last-run "5W" card for any skill/canary.
- **Scraper data** = the vendor `*_catalog` tables in `dw_unified` (freshness from true-scrape
columns: `last_scraped`/`scraped_at`/`crawled_at`/`imported_at`/`created_at`, NOT
`updated_at` which moves on bulk migrations) joined to `vendor_registry` (names/tables) and
the scraper healthcheck's `scraper-status.json` (health).
## Run / restart
```
pm2 restart stack-map # after editing server.js or index.html
pm2 logs stack-map # debug
```
Local git repo; commit after each change (per Steve's gitify rule).