WIKI/00 GOTCHAS

00 GOTCHAS

Updated 3 weeks ago
╔══════════════════════════════════════════════════════════════════════════════╗
║                                                                              ║
║   K I N G D O M   G O T C H A S                                              ║
║   🝓 C R O S S - S Y S T E M   W A R N I N G S   &   L A W S                ║
║                                                                              ║
╠══════════════════════════════════════════════════════════════════════════════╣
║  LAST UPDATED: 2026-03-13 (S186 — Gemini OAuth proxy, 3 new bots, 3 skills) ║
╚══════════════════════════════════════════════════════════════════════════════╝
⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸───────────────────────────────────────⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸
 WHAT IT IS: Cross-system gotchas and Kingdom-wide rules. System-specific
             gotchas live in each SYS_ doc. This file covers patterns that
             span multiple systems.
────────────────────────────────────────────────────────────────────────────────


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ ⛬ ] K I N G D O M - W I D E   R U L E S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

| Rule | What it means |
|------|---------------|
| **Highlander Protocol** | One file per domain. No duplicates. When updating, replace — don't create a parallel file. |
| **Vaporize Protocol** | Delete `_temp_*` files on task completion. No orphaned scratch work. |
| **Loaded Chamber** | All fixes/upgrades live in `_LOADED_CHAMBERS/BUG_*/` or `_LOADED_CHAMBERS/UPGRADE_*/`. Never execute outside a chamber. |
| **LAW 01 (SCRYER)** | SCRYER never observes itself. `com.scryer.watcher` excluded from launchd exit check. |
| **LAW 02 (SCRYER)** | No feedback loops. Scripts compress, route, flag — then stop. |
| **THE DECREE** | Governs all projects. Read before designing new systems. |


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🝓 ] G E M I N I   O A U T H   P R O X Y   ( S 1 8 6 )   —   P O R T   4 8 9 1
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

**ALL GEMINI CALLS FROM OPENCODE ROUTE THROUGH PORT 4891.**

Both AExGO and AExMUSE `opencode.json` have `"baseURL": "http://127.0.0.1:4891/v1beta/"`. If `com.forge.gemini-oauth-proxy` is not running, all OpenCode Gemini calls fail silently — the session starts but Aeris gets no AI responses.

**Always verify proxy is up before debugging Aeris session failures.**

Fix: `launchctl kickstart gui/$(id -u)/com.forge.gemini-oauth-proxy`

Check: `launchctl list | grep gemini-oauth`


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] L A U N C H D   —   T H E   S T R I P P E D   P A T H   P R O B L E M
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Every plist loses PATH. `/opt/homebrew/bin` does not exist in launchd's environment.

**Symptoms:** Script works in terminal, fails silently in launchd. Exit code 127 (command not found) or exit 1 with no log output.

**Fix pattern:**
1. Hardcode full paths for every binary: `/opt/homebrew/bin/python3`, `/opt/homebrew/bin/zellij`, `/opt/homebrew/bin/gemini`
2. For scripts, use `#!/bin/zsh -l` shebang (login shell loads full environment)
3. Set `EnvironmentVariables` in plist for `PATH` and `HOME`

**Systems affected:** ALL launchd daemons. ping_hub.sh, goldfish.sh, scryer scripts, mailbox triggers, wakeup-daemon.sh, glitchmuse-daemon, sentinel miners.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] S Q L I T E   —   T H E   L O C K   D A N C E
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Multiple daemons write to `overmind.db` concurrently (pulse.sh every 10min, digest.sh at 8am, ping-watcher.sh every 5min, scryer-dispatch.sh, context-render.sh every 5s).

**Symptom:** `database is locked` in logs. Processes exit non-zero. SCRYER files DB_LOCK report.

**Fix pattern:**
1. **All sqlite3 calls must use:** `sqlite3 -cmd ".timeout 10000" DB_PATH "QUERY"`
2. **Do NOT use:** `PRAGMA busy_timeout` — it echoes the value to stdout, corrupting rendered output in viddy panes
3. **WAL mode is enabled** — `.db-shm` and `.db-wal` files are normal; never delete them while daemons are running
4. **Never add raw sqlite3 calls** to scripts that already use a `dbq()` wrapper — wrap everything consistently


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🝓 ] B A S H   3 . 2   C O M P A T I B I L I T Y
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

macOS ships bash 3.2. Modern bash features that WILL BREAK:

| Feature | Broken | Fix |
|---------|--------|-----|
| `${var^^}` uppercase | ✗ | `tr '[:lower:]' '[:upper:]'` |
| `${var,,}` lowercase | ✗ | `tr '[:upper:]' '[:lower:]'` |
| `declare -A` associative arrays | ✗ | Two parallel arrays + index lookup |
| `<<< "string"` herestring in some contexts | ✗ | `echo "string" | command` |
| `[[ =~ ]]` PCRE | ✗ | `grep -qE` pattern |

**Workaround available for all of these.** Never assume bash 4+.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🝓 ] Z E L L I J   —   I N J E C T I O N   M E C H A N I C S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

When injecting mail into an agent pane via mailbox-trigger scripts:

| Key | Value |
|-----|-------|
| Submit key | `\r` (byte 13, carriage return) — NOT `\n` (byte 10) |
| Byte 10 | Inserts text but does NOT submit in the TUI |
| Tab targeting | Use `zellij action move-focus left` to target correct pane |
| Tab name with Unicode | `⛬ ÆxGO` can fail on some systems — scripts must `2>/dev/null` gracefully |
| Session must exist | Injection fails silently if session is down. daemon logs: `SKIPPED_NO_SESSION` |


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🝓 ] C L A U D E   C O D E   S E S S I O N S   —   N E S T I N G   B A N
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

**Symptom:** Second Claude Code session refuses to start: "cannot be launched inside another Claude Code session."

**Root cause:** `CLAUDECODE` environment variable propagates from parent session to child processes.

**Fix:** `unset CLAUDECODE;` before the `claude` command in KDL pane args. Required in THRONE_CLAUDE.kdl. Safe to add in any KDL that spawns Claude.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] G E M I N I   S O U L   F I L E   D I S C O V E R Y   [LEGACY — Gemini CLI era. Both cockpits now use OpenCode instructions]
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Gemini CLI looks for `.gemini/GEMINI.md` **in the current working directory** at launch time.

**Boot scripts must `cd` into the cockpit root before `exec gemini`:**
- AExGO: works because `aeris-boot.sh` runs inside `AExGO/`
- AExMUSE: `glitchmuse-boot.sh` must `cd AExGO` — if CWD is wrong, no soul file loads

**`--resume latest` does NOT reload GEMINI.md.** Only a fresh session picks up GEMINI.md changes. `/exit` → `gemini` to reload.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🝓 ] O V E R M I N D _ P U L S E . J S O N   I S   S T A L E   B Y   D E S I G N
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

**mission-render.sh reads `overmind.db` DIRECTLY.** Never reads `OVERMIND_PULSE.json`.

`OVERMIND_PULSE.json` is an auto-exported snapshot written by `export_pulse.sh` at the end of every pulse cycle. It is read-only, always behind real time, and NOT the source of truth for sidebar rendering.

Any script that needs live mission data must query `overmind.db` directly with `.timeout 10000`.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🝓 ] S C R Y E R   S I G N A L   D E D U P   ( 3 0 - M I N U T E   W I N D O W )
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

SCRYER's watcher won't re-queue a signal type that has a `pending` or recent `dispatching` row within 30 minutes. At most one BUG report per signal type per 30 minutes.

**What this means:** If you see 5 LAUNCHD_EXIT reports for the same service in the mailbox, they arrived across multiple 30-min windows. All have the same root cause.


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🝓 ] R A V E N   v 2   M A I L B O X   A R C H I T E C T U R E   —   C R I T I C A L
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

**RAVEN watches ROOT, not buffer/.** `raven.py` scans the mailbox root for `.md` files. It explicitly skips `buffer/`, `processed/`, `sidebar/` subdirs. Any file written to `buffer/` is invisible to RAVEN.

**`com.forge.mailbox` plist DOES NOT EXIST.** There is no injection daemon for `@FORGE_CLAUDE_MAILBOX`. `buffer/` for FORGE_CLAUDE has no consumer. Files written there accumulate silently forever.

**Correct delivery to FORGE_CLAUDE:** Drop envelope `.md` files directly to `@FORGE_CLAUDE_MAILBOX/` (root). RAVEN picks them up, routes to SQLite DB, serves via `raven inbox` CLI or web UI `:8768`.

**AExGO mailbox still uses injection:** `com.aeris.mailbox` → `@AERIS_FORGE_MAILBOX` (at `AExGO/03_📋_QUEUE/`) → Gemini/Aeris in AExGO session via zellij injection. This system is separate and intact.

**S166 fix:** `scryer-dispatch.sh` was silently writing BUG reports to `buffer/` (dead zone). Fixed to write to ROOT. SCRYER signals now reach RAVEN DB.

**bot-mailbox-health checks ROOT .md files,** not buffer/ dirs. Any unprocessed ROOT .md files older than threshold trigger a "RAVEN STUCK" alert.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] G H O S T T Y   C O N F I G   L A Y E R I N G
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

`--config-file` option LAYERS on top of `~/.config/ghostty/config`. Global theme, shader, and opacity bleed through unless explicitly overridden in the cockpit config.

**Every cockpit `.config` file must start with:**
```
theme = ""
custom-shader = ""
background-opacity = 1.0
background-blur-radius = 0
```


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🝓 ] G E M I N I   R E S T   A P I   I N   L A U N C H D
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

`scryer-synthesizer.sh` and `goldfish.sh` call Gemini Flash via Python3 `urllib.request` REST API — not via the `gemini` CLI binary.

**Why:** The `gemini` CLI binary is NOT in launchd's stripped PATH. REST API calls work from any environment as long as `GEMINI_API_KEY` is available.

**Key requirement:** `GEMINI_API_KEY` must be exported in `~/.zshenv` (NOT `~/.zshrc` or `~/.bash_profile`). Scripts source `~/.zshenv` explicitly. If the key is absent, REST calls fail with 400/403 — no crash, no panic, but no AI output.

**[S186 ADDENDUM]:** Interactive Gemini usage (OpenCode / AExGO / AExMUSE) now routes through `gemini-oauth-proxy` to PROVISIONED_THROUGHPUT (port 4891). This section applies to daemon scripts using the API key directly — not to OpenCode sessions.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🝓 ] M E M O R Y . M D   2 0 0 - L I N E   H A R D   L I M I T
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

Claude Code silently truncates `MEMORY.md` at line 200. No error. Content beyond line 200 is never loaded.

**Signs you've hit the limit:** Claude "forgets" things that are in MEMORY.md. Check `wc -l MEMORY.md`.

**Fix:** Move detail to topic files in `memory/` directory. Keep MEMORY.md as a navigable index pointing to topic files. The last line of a well-maintained MEMORY.md should be a warning when approaching the limit.


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🝓 ] A P P L E   S I L I C O N   +   O S A C O M P I L E
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

`osacompile -o IGNITION.app script.applescript` fails if `IGNITION.app/Contents/` already exists as a directory.

**Fix:**
```bash
rm -rf IGNITION.app
osacompile -o IGNITION.app script.applescript
```


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] A T U I N   T I M E S T A M P   F O R M A T
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Atuin stores shell history timestamps as **nanoseconds since Unix epoch** (not seconds, not milliseconds).

**Correct conversion for "today since midnight":**
```bash
TODAY_EPOCH=$(date -j -f "%Y-%m-%d %H:%M:%S" "$(date +%Y-%m-%d) 00:00:00" "+%s")
TODAY_NANO="${TODAY_EPOCH}000000000"
```

Using the wrong scale results in querying all history or no history.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🝓 ] P A N E L - C A C H E . T X T   R A C E   C O N D I T I O N
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

`panel-updater.sh` writes to `~/.forge-ping/panel-cache.txt` and `context-render.sh` reads it. viddy refreshes both every 5-15 seconds.

**Fix:** Always write via atomic temp+mv:
```bash
tmp=$(mktemp)
generate_content > "$tmp"
mv "$tmp" ~/.forge-ping/panel-cache.txt
```

Direct write (`generate_content > panel-cache.txt`) truncates the file before writing — viddy may catch it mid-write and display an empty pane.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🝓 ] G O L D F I S H _ H E A R T B E A T   F A L S E   P O S I T I V E S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

SCRYER's `GOLDFISH_HEARTBEAT` threshold is **25 minutes**, not 10. Goldfish runs every ~15 minutes. A 10-min threshold fires during normal execution gaps between runs. Any value under ~20 min will produce false positives.

If you see `GOLDFISH_HEARTBEAT` reports flooding the mailbox, check the threshold in `scryer-watcher.sh` — it should be `GOLDFISH_HEARTBEAT_MAX=25`.


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ 🝓 ] B U F F E R   H I G H _ W A T E R _ A L A R M   —   O N E - S H O T   S E N T I N E L
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

`mailbox-trigger.sh` fires a high-water alarm when `buffer/` reaches 10+ items (`BUFFER_HIGH_WATER=10`). It uses a sentinel file `$MAILBOX_DIR/.high_water_alerted` to ensure the alarm fires **once per saturation event**, not on every 15-min trigger cycle.

- Sentinel created when buffer first crosses threshold → alarm injected once
- Sentinel deleted when buffer count drops back below threshold → alarm can fire again on next saturation

This pattern prevents spam without polling. Any similar "one alert per condition" use case should replicate this sentinel file approach.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ 🝓 ] P U L S E _ L O G   O U T P U T _ S N I P P E T   W A S   N U L L   ( p r e - S 9 7 )
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

Before the Session 97 bug hunt fix, `pulse.sh` deleted `output_file` on TIMEOUT and FAILED paths **before** saving `output_snippet` to `pulse_log`. All historical TIMEOUT and FAILED rows in `pulse_log` have `output_snippet = NULL`.

As of Session 97: `output_snippet` is extracted and saved to DB **before** `output_file` is deleted on both TIMEOUT and FAILED paths. New rows will have populated snippets.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ 🝓 ] L A U N C H D   K E E P A L I V E   W I T H O U T   T H R O T T L E I N T E R V A L
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

A `KeepAlive=true` service that exits immediately (port conflict, missing binary, crash on start) will be restarted by launchd in a tight loop. Each restart → exit → SCRYER files a `LAUNCHD_EXIT` report. Result: SCRYER mailbox flooded with identical reports, buffer hits high-water alarm.

**Fix:** Add `ThrottleInterval` to the plist. For network services (like `com.forge.ping-ui`), `ThrottleInterval=10` gives the OS time to clear `TIME_WAIT` state on the port before the next restart attempt.

**Rule of thumb:** Every `KeepAlive=true` plist should have `ThrottleInterval` set.

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🝓 ] C O N S O L E   D N D   G A T E   —   G L I T C H M U S E _ M A I L B O X
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

`kingdom-ship.sh` writes somatic ambient drops to `SINNER_KING_CONSOLE/@GLITCHMUSE_MAILBOX/` (the STAGING_DIR). That path IS a RAVEN WATCH_ZONE — RAVEN picks up those files.

**DND gate:** `~/.sinner-king-console/.dnd` flag file. When present, `kingdom-ship.sh` skips the ambient drop. `/dnd on` creates the flag; `/dnd off` removes it. Gate checked at Console submit time.

**AERIS_MUSE alias:** In `router.py` AGENT_TARGETS, `AERIS_MUSE` maps to the glitchmuse session. SINNER_KING_ envelope prefix uses `target: envelope_to` in `raven_routes.yaml` — this respects the TO: field in the envelope rather than forcing a fixed target.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
🜚 00_GOTCHAS // CORE LORE // ⛬⚚⛬ THE LAW STANDS.
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
⛬ KID:CORE:DOCS:GOTCHAS|1.0:LIVE:2026-02-25:⌂ ⛬