Steering¶
Routing rules for agents and tasks. Any AI reading this knows how the fleet works.
Task Routing¶
| Task type | Route to | Notes |
|---|---|---|
| Code / development | UDev (.50) | Forge workspace, Claude Code |
| Media requests | media-server (.74) | Overseerr → Sonarr/Radarr |
| Smart home | homeassistant (.70) | Home Assistant |
| Business / invoicing | , | QuickBooks + Notion (cloud) |
| DNS / blocking | adguard (.75) | AdGuard Home |
| Hypervisor / VM ops | Finn (.67) | Proxmox |
| Background / scheduled | Task queue | tasks/pending/ → Dispatcher → Worker |
| Interactive / coding | Claude Code | VS Code session or remote-control |
Agent Roles¶
| Agent | Role | Description |
|---|---|---|
| Manager | The brain | Persistent Opus session. Creates tasks, reviews results, writes briefings. Does NOT spawn workers directly. |
| Dispatcher | The muscle | Bash script (scripts/forge_dispatcher.sh). Polls task queue, spawns workers, enforces budgets. Dumb but reliable. |
| Monitors | The eyes | Bash+cron scripts (scripts/monitors/). Check infra/security/business every 5-15 min. Only create tasks when something is wrong. Zero tokens when healthy. |
| Workers | The hands | On-demand Claude Code sessions. Do one task and exit. Named: worker-{task}_{Model}. |
| Justin | The CEO | Steers when he wants. Gets briefings. Approves big decisions. |
Decision Principles¶
- Manager creates tasks. Dispatcher spawns workers. They don't overlap.
- Monitors are bash scripts, not AI sessions. AI only activates when something needs fixing.
- New agents inherit system-map/ as their brain, write a wrapper, not a new brain.
- All memory that matters lives in forge (git-tracked). Agent-specific caches are ephemeral.
- When in doubt, write it to
memory/daily/YYYY-MM-DD.md.
How to add a new workflow¶
- Create the event trigger in n8n (webhook, cron, IMAP poll)
- Have n8n SSH to UDev and run
infra/n8n/task-creator.sh - The Dispatcher picks it up automatically
- Done. No code changes needed.
Runtime Steering Rules (Section 13 deny-list, Phase 4.8)¶
The dispatcher pre-flights every spawned worker through scripts/forge_steering_intercept.py before invoking claude -p. Tasks whose prompt matches any rule below are moved to tasks/failed/ with exit_reason: "steering-intercept-deny" and never reach a model. Source of truth is the _build_rules() function in the intercept script; this table mirrors that policy for human review.
| Rule ID | Severity | Pattern (informal) | Why |
|---|---|---|---|
no-secrets-shell-access |
fatal | ~/.forge-secrets/ or /home/justinwieb/.forge-secrets/ |
CLAUDE.md security rule 3 forbids plaintext credential handling outside the vault |
no-force-push-protected |
fatal | git push --force against main/master |
force-push can destroy upstream work; workers must use a branch + PR |
no-home-wipe |
fatal | rm -rf ~, rm -rf /home/justinwieb, rm -rf / |
catastrophic blast radius |
no-credential-echo |
error | echo/cat/printf with *_API_KEY, *_TOKEN, *_SECRET, *_PASSWORD |
echoed credentials would leak into worker logs that mkdocs may serve |
no-disable-eval-harness |
fatal | removing or chmod-zeroing eval.json, forge_eval_harness.py, or .git/hooks/pre-commit |
the eval harness IS the doctrine teeth; amendments go through Section 10 self-iteration |
no-disable-doctrine |
fatal | rm/mv of FORGE-DOCTRINE.md |
doctrine removal requires explicit Justin sign-off |
Adding a new rule: edit _build_rules() in forge_steering_intercept.py, then add a row to this table. No restart needed; dispatcher imports fresh on each spawn.
The intercept is a deny-list, not an LLM intent inspector, in v1. If a future doctrine pass funds an LLM-based intent classifier, it will run AFTER this fast deny-list as a second layer.