summaryrefslogtreecommitdiff
path: root/AGENTS.md
blob: d88d7ed1bced9654bc778b185f484a1112d5705f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# AGENTS.md

Guidance for AI coding agents working in this repository.

## What this repo is

`statuspage/` generates a static status console for a FreeBSD homelab
server (`dandokmang.com`). Modular POSIX `/bin/sh` check scripts each emit
JSONL rows; an orchestrator (`render.sh`) runs them all, groups the rows by
section, and writes a static `index.html` (dark/monospace, stoplight-grid
style) that Caddy serves over WireGuard.

**Start with `statuspage/README.md`** for the full JSONL contract between
check scripts and the renderer, the jails-are-auto-discovered-not-scripted
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.

## Where code runs vs. where it's edited

This checkout is on Windows. None of the runtime commands the check
scripts depend on (`sysctl`, `jls`, `jexec`, `pfctl`, `zpool`, `wg`,
`service`, `ntpq`) exist here - they only exist on the target FreeBSD box.

- **Validate here**: `sh -n path/to/script.sh` for syntax, and dry-run
  logic by putting small shell stubs for the real commands in a temp dir
  and prepending it to `PATH` (e.g. a fake `pfctl` that echoes canned
  output). This is the only way to exercise check-script logic without
  the real box.
- **Deploy for real**: this repo's `origin` remote is
  `ssh://cgit-jail/srv/git/console.git`. The FreeBSD server has its own
  clone at `~/projects/console`, with `/usr/local/etc/statuspage`
  symlinked to `~/projects/console/statuspage`. `render.sh` runs there via
  root cron every minute, writing to `/usr/local/www/status/index.html`.
  Changes only take effect after: commit here -> push -> `git pull` on the
  server. There is no way to verify a change actually works against real
  system state from this machine - say so rather than claiming success.

## Committing shell scripts

`core.fileMode` is `false` on this checkout, because this Windows
filesystem doesn't reliably preserve the executable bit - `chmod +x`
followed by a plain `git add` still stages a `.sh` file as `100644`.

`git config core.hooksPath .githooks` (already set in this checkout, but
**not** carried by a fresh clone - re-run it once after cloning elsewhere)
activates a pre-commit hook that force-sets `+x` on every staged `*.sh`
file automatically. A non-`.sh` executable (rare - the hook only globs
`*.sh`) needs `git update-index --chmod=+x <file>` by hand, and so does
the hook file itself if it's ever edited (it can't fix its own bit).

## Gotchas already hit once - don't re-discover these

- **`ln -s` on a directory, tested on this Windows box, silently falls
  back to a real copy instead of a symlink.** Don't trust symlink
  behavior verified here; it needs confirming on the real FreeBSD box.
- **Greedy regex substring traps**: `usec` contains `sec`, so
  `sed 's/.*sec = \(...\).*/.../'` will match the *last* occurrence
  (`usec`), not the first. Anchor tightly (e.g. match the literal `{ sec
  = ` prefix) instead of relying on `.*` to stop at the right spot.
- **`ntpq`'s `rv 0 offset` prefixes non-negative values with a literal
  `+`.** A sed capture class of `[-0-9.]` silently drops the `+` and
  matches empty rather than failing loudly - always include `+` alongside
  `-` in numeric-capture character classes.
- **`grep -c pattern` exits `1` when the count is `0`**, even though it
  prints `0`. Guard command substitutions that end in `grep -c` with
  `|| var=0`, or `set -e` will kill the whole script on a legitimate
  zero-count case.
- **Most check commands (`pfctl`, `jls`, `wg`, `jexec`) need root.**
  `render.sh` runs as root via cron, so this isn't an issue in production,
  but manual testing on the box needs `doas`/`sudo`.

## Cosmetic conventions (render.sh)

- Status values are `ok` / `warn` / `down` (green/yellow/red) or `info`
  (gray, for rows that aren't a health signal - e.g. `pf.sh`'s rule
  listing). Don't repurpose the health colors for non-health rows.
- The font (`statuspage/fonts/scientifica.ttf`, a bitmap-style font) only
  ships Arrows, Geometric Shapes, Box Drawings, Mathematical
  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.