Skip to content

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

  1. Create the event trigger in n8n (webhook, cron, IMAP poll)
  2. Have n8n SSH to UDev and run infra/n8n/task-creator.sh
  3. The Dispatcher picks it up automatically
  4. 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.