# Automation Inventory

Last audited: 2026-04-04 15:55 EDT
Owner: Timmy sidecar / Timmy home split
Purpose: document every known automation that can restart services, revive old worktrees, reuse stale session state, or re-enter old queue state.

## Why this file exists

The failure mode is not just "a process is running".
The failure mode is:
- launchd or a watchdog restarts something behind our backs
- the restarted process reads old config, old labels, old worktrees, old session mappings, or old tmux assumptions
- the machine appears haunted because old state comes back after we thought it was gone

This file is the source of truth for what automations exist, what state they read, and how to stop or reset them safely.

## Source-of-truth split

Not all automations live in one repo.

1. timmy-config
   Path: ~/.timmy/timmy-config
   Owns: sidecar deployment, ~/.hermes/config.yaml overlay, launch-facing helper scripts in timmy-config/bin/

2. timmy-home
   Path: ~/.timmy
   Owns: Kimi heartbeat script at uniwizard/kimi-heartbeat.sh and other workspace-native automation

3. live runtime
   Path: ~/.hermes/bin
   Reality: some scripts are still only present live in ~/.hermes/bin and are NOT yet mirrored into timmy-config/bin/

Rule:
- Do not assume ~/.hermes/bin is canonical.
- Do not assume timmy-config contains every currently running automation.
- Audit runtime first, then reconcile to source control.

## Current live automations

### A. launchd-loaded automations

These are loaded right now according to `launchctl list` after the 2026-04-04 phase-2 cleanup.
The only Timmy-specific launchd jobs still loaded are the ones below.

#### 1. ai.hermes.gateway
- Plist: ~/Library/LaunchAgents/ai.hermes.gateway.plist
- Command: `python -m hermes_cli.main gateway run --replace`
- HERMES_HOME: `~/.hermes`
- Logs:
  - `~/.hermes/logs/gateway.log`
  - `~/.hermes/logs/gateway.error.log`
- KeepAlive: yes
- RunAtLoad: yes
- State it reuses:
  - `~/.hermes/config.yaml`
  - `~/.hermes/channel_directory.json`
  - `~/.hermes/sessions/sessions.json`
  - `~/.hermes/state.db`
- Old-state risk:
  - if config drifted, this gateway will faithfully revive the drift
  - if Telegram/session mappings are stale, it will continue stale conversations

Stop:
```bash
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.hermes.gateway.plist
```
Start:
```bash
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.hermes.gateway.plist
```

#### 2. ai.hermes.gateway-fenrir
- Plist: ~/Library/LaunchAgents/ai.hermes.gateway-fenrir.plist
- Command: same gateway binary
- HERMES_HOME: `~/.hermes/profiles/fenrir`
- Logs:
  - `~/.hermes/profiles/fenrir/logs/gateway.log`
  - `~/.hermes/profiles/fenrir/logs/gateway.error.log`
- KeepAlive: yes
- RunAtLoad: yes
- Old-state risk:
  - same class as main gateway, but isolated to fenrir profile state

#### 4. ai.timmy.kimi-heartbeat
- Plist: ~/Library/LaunchAgents/ai.timmy.kimi-heartbeat.plist
- Command: `/bin/bash ~/.timmy/uniwizard/kimi-heartbeat.sh`
- Interval: every 300s
- Logs:
  - `/tmp/kimi-heartbeat-launchd.log`
  - `/tmp/kimi-heartbeat-launchd.err`
  - script log: `/tmp/kimi-heartbeat.log`
- State it reuses:
  - `/tmp/kimi-heartbeat.lock`
  - Gitea labels: `assigned-kimi`, `kimi-in-progress`, `kimi-done`
  - repo issue bodies/comments as task memory
- Current behavior as of this audit:
  - stale `kimi-in-progress` tasks are now reclaimed after 1 hour of silence
- Old-state risk:
  - labels ARE the queue state; if labels are stale, the heartbeat used to starve forever
  - the heartbeat is source-controlled in timmy-home, not timmy-config

Stop:
```bash
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.timmy.kimi-heartbeat.plist
```

Clear lock only if process is truly dead:
```bash
rm -f /tmp/kimi-heartbeat.lock
```

#### 5. ai.timmy.claudemax-watchdog
- Plist: ~/Library/LaunchAgents/ai.timmy.claudemax-watchdog.plist
- Command: `/bin/bash ~/.hermes/bin/claudemax-watchdog.sh`
- Interval: every 300s
- Logs:
  - `~/.hermes/logs/claudemax-watchdog.log`
  - launchd wrapper: `~/.hermes/logs/claudemax-launchd.log`
- State it reuses:
  - live process table via `pgrep`
  - recent Claude logs `~/.hermes/logs/claude-*.log`
  - backlog count from Gitea
- Current behavior as of this audit:
  - will NOT restart claude-loop if recent Claude logs say `You've hit your limit`
  - will log-and-skip missing helper scripts instead of failing loudly
- Old-state risk:
  - any watchdog can resurrect a loop you meant to leave dead
  - this is the first place to check when a loop "comes back"

### B. quarantined legacy launch agents

These were moved out of `~/Library/LaunchAgents` on 2026-04-04 to:
`~/Library/LaunchAgents.quarantine/timmy-legacy-20260404/`

#### 6. com.timmy.dashboard-backend
- Former plist: `com.timmy.dashboard-backend.plist`
- Former command: uvicorn `dashboard.app:app`
- Former working directory: `~/worktrees/kimi-repo`
- Quarantine reason:
  - served code from a specific stale worktree
  - could revive old backend state by launchd KeepAlive alone

#### 7. com.timmy.matrix-frontend
- Former plist: `com.timmy.matrix-frontend.plist`
- Former command: `npx vite --host`
- Former working directory: `~/worktrees/the-matrix`
- Quarantine reason:
  - pointed at the old `the-matrix` lineage instead of current nexus truth
  - could revive a stale frontend every login

#### 8. ai.hermes.startup
- Former plist: `ai.hermes.startup.plist`
- Former command: `~/.hermes/bin/hermes-startup.sh`
- Quarantine reason:
  - startup path still expected missing `timmy-tmux.sh`
  - could recreate old webhook/tmux assumptions at login

#### 9. com.timmy.tick
- Former plist: `com.timmy.tick.plist`
- Former command: `/Users/apayne/Timmy-time-dashboard/deploy/timmy-tick-mac.sh`
- Quarantine reason:
  - pure dashboard-era legacy path

### C. running now but NOT launchd-managed

These are live processes, but not currently represented by a loaded launchd plist.
They can still persist because they were started with `nohup` or by other parent scripts.

#### 8. gemini-loop.sh
- Live process: `~/.hermes/bin/gemini-loop.sh`
- Source of truth: `timmy-config/bin/gemini-loop.sh`
- State files:
  - `~/.hermes/logs/gemini-loop.log`
  - `~/.hermes/logs/gemini-skip-list.json`
  - `~/.hermes/logs/gemini-active.json`
  - `~/.hermes/logs/gemini-locks/`
  - `~/.hermes/logs/gemini-pids/`
  - worktrees under `~/worktrees/gemini-w*`
  - per-issue logs `~/.hermes/logs/gemini-*.log`
- Default-safe behavior:
  - only picks issues explicitly assigned to `gemini`
  - self-assignment is opt-in via `ALLOW_SELF_ASSIGN=1`
- Old-state risk:
  - skip list suppresses issues for hours
  - lock directories can make issues look "already busy"
  - old worktrees can preserve prior branch state
  - branch naming `gemini/issue-N` continues prior work if branch exists

Stop cleanly:
```bash
pkill -f 'bash /Users/apayne/.hermes/bin/gemini-loop.sh'
pkill -f 'gemini .*--yolo'
rm -rf ~/.hermes/logs/gemini-locks/*.lock ~/.hermes/logs/gemini-pids/*.pid
printf '{}\n' > ~/.hermes/logs/gemini-active.json
```

#### 9. timmy-orchestrator.sh
- Live process: `~/.hermes/bin/timmy-orchestrator.sh`
- Source of truth: `timmy-config/bin/timmy-orchestrator.sh`
- State files:
  - `~/.hermes/logs/timmy-orchestrator.log`
  - `~/.hermes/logs/timmy-orchestrator.pid`
  - `~/.hermes/logs/timmy-reviews.log`
  - `~/.hermes/logs/workforce-manager.log`
  - transient state dir: `/tmp/timmy-state-$$/`
- Default-safe behavior:
  - reports unassigned issues by default
  - bulk auto-assignment is opt-in via `AUTO_ASSIGN_UNASSIGNED=1`
  - reviews PRs via `hermes chat`
  - runs `workforce-manager.py`
- Old-state risk:
  - if `AUTO_ASSIGN_UNASSIGNED=1`, it will mutate Gitea assignments and can repopulate queues
  - still uses live process/log state as an input surface

### D. Hermes cron automations

Current cron inventory from `cronjob(list, include_disabled=true)`:

Enabled:
- `a77a87392582` — Health Monitor — every 5m

Paused:
- `9e0624269ba7` — Triage Heartbeat
- `e29eda4a8548` — PR Review Sweep
- `5e9d952871bc` — Agent Status Check
- `36fb2f630a17` — Hermes Philosophy Loop

Old-state risk:
- paused crons are not dead forever; they are resumable state
- LLM-wrapped crons can revive old routing/model assumptions if resumed blindly

### E. file exists but NOT currently loaded

These are the ones most likely to surprise us later because they still exist and point at old realities.

#### 10. com.tower.pr-automerge
- Plist: `~/Library/LaunchAgents/com.tower.pr-automerge.plist`
- Points to: `/Users/apayne/hermes-config/bin/pr-automerge.sh`
- Not loaded at audit time
- Separate Tower-era automation path; not part of current Timmy sidecar truth

## State carriers that make the machine feel haunted

These are the files and external states that most often "bring back old state":

### Hermes runtime state
- `~/.hermes/config.yaml`
- `~/.hermes/channel_directory.json`
- `~/.hermes/sessions/sessions.json`
- `~/.hermes/state.db`

### Loop state
- `~/.hermes/logs/claude-skip-list.json`
- `~/.hermes/logs/claude-active.json`
- `~/.hermes/logs/claude-locks/`
- `~/.hermes/logs/claude-pids/`
- `~/.hermes/logs/gemini-skip-list.json`
- `~/.hermes/logs/gemini-active.json`
- `~/.hermes/logs/gemini-locks/`
- `~/.hermes/logs/gemini-pids/`

### Kimi queue state
- Gitea labels, not local files, are the queue truth
- `assigned-kimi`
- `kimi-in-progress`
- `kimi-done`

### Worktree state
- `~/worktrees/*`
- especially old frontend/backend worktrees like:
  - `~/worktrees/the-matrix`
  - `~/worktrees/kimi-repo`

### Launchd state
- plist files in `~/Library/LaunchAgents`
- anything with `RunAtLoad` and `KeepAlive` can resurrect automatically

## Audit commands

List loaded Timmy/Hermes automations:
```bash
launchctl list | egrep 'timmy|kimi|claude|max|dashboard|matrix|gateway|huey'
```

List Timmy/Hermes launch agent files:
```bash
find ~/Library/LaunchAgents -maxdepth 1 -name '*.plist' | egrep 'timmy|hermes|tower'
```

List running loop scripts:
```bash
ps -Ao pid,ppid,etime,command | egrep '/Users/apayne/.hermes/bin/|/Users/apayne/.timmy/uniwizard/'
```

List cron jobs:
```bash
hermes cron list --include-disabled
```

## Safe reset order when old state keeps coming back

1. Stop launchd jobs first
```bash
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.timmy.kimi-heartbeat.plist || true
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.timmy.claudemax-watchdog.plist || true
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.hermes.gateway.plist || true
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.hermes.gateway-fenrir.plist || true
```

2. Kill manual loops
```bash
pkill -f 'gemini-loop.sh' || true
pkill -f 'timmy-orchestrator.sh' || true
pkill -f 'claude-loop.sh' || true
pkill -f 'claude .*--print' || true
pkill -f 'gemini .*--yolo' || true
```

3. Clear local loop state
```bash
rm -rf ~/.hermes/logs/claude-locks/*.lock ~/.hermes/logs/claude-pids/*.pid
rm -rf ~/.hermes/logs/gemini-locks/*.lock ~/.hermes/logs/gemini-pids/*.pid
printf '{}\n' > ~/.hermes/logs/claude-active.json
printf '{}\n' > ~/.hermes/logs/gemini-active.json
rm -f /tmp/kimi-heartbeat.lock
```

4. If gateway/session drift is the problem, back up before clearing
```bash
cp ~/.hermes/config.yaml ~/.hermes/config.yaml.bak.$(date +%Y%m%d-%H%M%S)
cp ~/.hermes/sessions/sessions.json ~/.hermes/sessions/sessions.json.bak.$(date +%Y%m%d-%H%M%S)
```

5. Relaunch only what you explicitly want

## Current contradictions to fix later

1. README and DEPRECATED were corrected on 2026-04-04, but older local clones may still have stale prose.
2. The quarantined launch agents now live under `~/Library/LaunchAgents.quarantine/timmy-legacy-20260404/`; if someone moves them back, the old state can return.
3. `gemini-loop.sh` and `timmy-orchestrator.sh` now have source-controlled homes in `timmy-config/bin/`, but any local forks or older runtime copies should be treated as suspect until redeployed.
4. Keep docs-only PRs and script-import PRs on clean branches from `origin/main`; do not mix them with unrelated local history.

Until those are reconciled, trust this inventory over older prose.

### Memory & Audit Capabilities (Added 2026-04-06)

| Capability | Task/Helper | Purpose | State Carrier |
| :--- | :--- | :--- | :--- |
| **Continuity Flush** | `flush_continuity` | Pre-compaction session state persistence. | `~/.timmy/continuity/active.md` |
| **Sovereign Audit** | `audit_log` | Automated action logging with confidence signaling. | `~/.timmy/logs/audit.jsonl` |
| **Fallback Routing** | `get_model_for_task` | Dynamic model selection based on portfolio doctrine. | `fallback-portfolios.yaml` |
