summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbatsumaru <>2026-07-01 18:49:25 +0900
committerbatsumaru <>2026-07-01 18:49:25 +0900
commit92062d94f8150e4502ad305d74b62bbb678ded41 (patch)
tree9146ab621d59c3513ee1907b1a06de0064afcbb5
parentd35a7d3b24fa71e13e48fd85e299c12a93e6aab8 (diff)
Expand AGENTS.md: topology, one-line-fit preference, real-time triggers
Homelab topology: pulled the infrastructure context from the original handover doc (FreeBSD version, WireGuard/Caddy/ZFS/jail network layout) that isn't otherwise captured now that check.sh is gone. Design preference: documents "rows should fit on one line" as a standing preference (not a one-off ask), with checks/pf.sh's abbreviate_rule() development as the worked example of how to compress long/variable-length output - strip ruleset-specific boilerplate, verify symbol choices against the font's actual glyph coverage, prefer legible bracket-letter tags over clever-but-obscure unicode when a distinction has real meaning, and always confirm via a rendered preview rather than eyeballing character counts. When cron + static HTML stops being enough: concrete signals (need for alerting, history/trends, sub-minute or push-based updates, render time approaching the cron interval) that mean this architecture is being outgrown, so a future ask crossing one of these gets flagged explicitly instead of worked around within the current design. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-rw-r--r--AGENTS.md85
1 files changed, 85 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md
index d88d7ed..01595a3 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -16,6 +16,26 @@ design, failure-isolation behavior, and the current deployment recipe
(Caddy + DNS-01 cert via Porkbun). This file only covers what that one
doesn't: workflow and environment gotchas specific to developing here.
+## Homelab topology
+
+Context that isn't tied to any one check script but explains why they're
+shaped the way they are:
+
+- FreeBSD 15.0-RELEASE, single physical homelab server (`dandokmang.com`).
+- WireGuard interface `wg0`, network `172.16.0.0/24` - the status page is
+ reachable only from this network (see `statuspage/README.md`'s Caddy
+ config).
+- Caddy is the host's reverse proxy, fronting the jails below and (per its
+ own Caddyfile, not in this repo) the status page's `status.dandokmang.com`
+ vhost.
+- ZFS pool `zroot`.
+- VNET jails on `bridge0` / `192.168.100.0/24`: `cgit` (`192.168.100.10`)
+ and `www` (`192.168.100.20`), each running nginx on port 80.
+- Host services outside the jails: `wg0`, `caddy`, `ddclient` (dynamic DNS,
+ since the box is on a residential/dynamic IP - this is also why
+ `checks/wg-watcher.sh` exists, to catch the WAN-change-reaction daemon
+ dying silently).
+
## Where code runs vs. where it's edited
This checkout is on Windows. None of the runtime commands the check
@@ -80,3 +100,68 @@ the hook file itself if it's ever edited (it can't fix its own bit).
Operators/Symbols-A, Misc Technical/Symbols, and PUA/Powerline glyphs -
notably **not** Dingbats (✓/✗). Check glyph coverage against that list
before adding new symbols to check-script output.
+
+## Design preference: rows should fit on one line
+
+The user has repeatedly pushed back on wrapped/overflowing row text -
+this is a standing preference, not a one-off request. When a check emits
+a label or value that could be long or variable-length (rule dumps, peer
+lists, anything sourced from a system command's verbose output), assume
+it needs to be compressed to fit a ~380px column at 16px, not just left
+to wrap. `td.label`'s hanging indent (`text-indent`/`padding-left` in
+`render.sh`) exists as a fallback for when wrapping is unavoidable, not
+as the primary solution - reach for compression first.
+
+`checks/pf.sh`'s `abbreviate_rule()` is the reference example for how
+this compression was actually developed, worth following the same
+approach for any future long-text row:
+
+1. First attempt was the raw `pfctl -sr`/`-sn` output verbatim - overflowed
+ badly, multi-line wraps looked messy even with the hanging indent.
+2. Stripped tokens that are boilerplate *for this specific ruleset*
+ (`quick`, `flags S/SA`) rather than guessing generically - checked
+ against the user's real `/etc/pf.conf` first rather than assuming.
+3. Swapped `in`/`out` for `→`/`←`, generalized `from X to Y` to `X → Y`,
+ and replaced pfctl's own ASCII `->` with the same unicode arrow for
+ visual consistency - all using only the confirmed-supported Arrows
+ block (see the font gotcha above).
+4. Re-sorted the rule list by (interface, direction) for readability.
+ Display-only - doesn't touch pf's real evaluation order or
+ `quick`/first-match semantics.
+5. For the state-tracking flag (`no state`/`keep state`/`modulate
+ state`/`synproxy state` - four modes with real, different security
+ properties), the instinct was to find clever unicode from Mathematical
+ Operators/Geometric Shapes, but landed on plain bracket-letter tags
+ (`[N]`/`[K]`/`[M]`/`[S]`) instead: a distinction with real operational
+ meaning needs to be legible without a legend, and a "clever" symbol
+ that requires memorizing isn't actually more compact once you factor
+ in "what does this mean."
+6. Every step was verified against a rendered preview (Artifact tool with
+ mocked check output), not just eyeballed character counts - monospace-
+ ish bitmap font wrapping doesn't line up with raw string length in an
+ obvious way.
+
+## When cron + static HTML stops being enough
+
+The whole point of this project (see the original handover this repo
+started from) was turning a monolithic cron script into modular checks -
+it was never meant to be a general monitoring platform. If a future ask
+starts pushing on one of these, say so explicitly rather than bolting a
+workaround onto the current design:
+
+- **Alerting / notification on state change.** The current design is
+ pull-only - a human has to load the page to see anything. There's no
+ mechanism to push "X just went down" anywhere. That needs a real daemon
+ (or at minimum a separate cron job comparing renders and calling out).
+- **History or trends** (e.g. "graph load average over the last day").
+ Each render overwrites the last; nothing persists prior states. That
+ needs a time-series store, which is a different project.
+- **Faster-than-cron or push-based updates.** Cron's practical floor is
+ about a minute, and the page currently self-refreshes via `<meta
+ http-equiv="refresh">` (a full reload), not a live push. If sub-minute
+ latency or in-place updates without a full reload actually matter, that
+ means WebSockets/SSE and a long-running process, not this architecture.
+- **Check execution time approaching the 1-minute cron interval.** This
+ one's an operational red flag rather than a feature request - if
+ `render.sh` starts taking close to 60s to run, cron ticks will begin
+ overlapping/queuing. Worth watching as more checks get added.