Configuration
Configuration reference
All knobs that control Auriga's routing behavior — environment variables, batch caps, human filter, review squad rules, agent registry, and runtime capacity.
Environment variables
These are read at startup and override defaults without requiring a code change.
| Variable | Default | Effect |
|---|---|---|
| AURIGA_CONFIG | — | Path to an optional JSON override file. Any key present replaces the corresponding export from config.mjs or config-substrate.mjs. Absent keys keep defaults. |
| AURIGA_PER_CYCLE_TOTAL | 5 | Max new dispatches per cycle. Overrides CAPS.perCycleTotal. |
| AURIGA_PER_CYCLE_PER_AGENT | 2 | Max dispatches to a single agent per cycle. Overrides CAPS.perCyclePerAgent. |
| AURIGA_CYCLE_MS | 75000 | Sleep between cycles in milliseconds. Overrides CAPS.cycleMs. |
| AURIGA_PIDFILE | /tmp/auriga-router.pid | Path to the pidfile that enforces single-instance locking. |
| AURIGA_LOG | /tmp/auriga-router.log | Path to the human-readable log file. |
| AURIGA_MEMORY_ADAPTER | mnemosyne | Which MemoryAdapter implementation to use. Set to stub for local testing without a live Mnemosyne instance. |
Log files
In addition to AURIGA_LOG, the router also writes a structured JSONL log at /tmp/auriga-router.jsonl (not overridable). The supervisor has its own log at /tmp/auriga-supervisor.log and /tmp/auriga-supervisor.pid.
CAPS
The CAPS object in lib/config.mjs controls all cycle timing and per-cycle dispatch limits. Every cap is a hard bound — once hit, no further mutations of that type happen in that cycle. Can be overridden entirely via the AURIGA_CONFIG external file.
| Key | Default | Description |
|---|---|---|
| perCyclePerAgent | 2 | Max new dispatches to a single agent within one cycle. Prevents any one agent from being mass-assigned. |
| perCycleTotal | 5 | Max new dispatches across all agents in one cycle. |
| cycleMs | 75000 | Milliseconds to sleep between cycles. |
| zombieStaleMs | 1200000 (20 min) | Age in ms at which an in_progress issue with no run activity is considered a zombie. |
| zombieMaxAttempts | 3 | Max times a zombie is re-queued before giving up and setting it to blocked. |
| verifyDelayMs | 6000 | Milliseconds to wait after assigning an issue before verifying a run actually started. |
| perCycleReview | 1 | Max review squad dispatches per cycle. Kept tight because review runs share the Claude account. |
| perCycleFalseDone | 3 | Max false-done corrections (done → in_review) per cycle. |
| perCycleCascade | 5 | Max cascade (completed issue → dependent enqueue) operations per cycle. |
// Example: external override file to slow the cycle
{
"CAPS": {
"perCycleTotal": 3,
"cycleMs": 120000,
"zombieMaxAttempts": 2
}
}
HUMAN_NAMES
The list of human names that trigger the human-todo filter. An issue with waiting_on: <value> in its metadata is excluded from agent dispatch if value case-insensitively contains any name in this list.
// Default in lib/config.mjs export const HUMAN_NAMES = _ext.HUMAN_NAMES ?? ['mathew', 'dostal']; // Override via AURIGA_CONFIG: { "HUMAN_NAMES": ["mathew", "dostal", "alice"] }
Add a name here when a new human joins the team and needs issues flagged for their attention routed to the human queue instead of an agent lane. See Human-todo filter for full semantics.
REVIEW_SQUAD_RULES
The explicit, inspectable rule table that reviewSquadPlan(issue, cfg) uses to size the review squad for each ticket. Keyword lists classify issues into tiers; the tier determines which perspectives run and whether Playwright is required.
// lib/config.mjs — edit keyword lists to change how tickets are sized export const REVIEW_SQUAD_RULES = _ext.REVIEW_SQUAD_RULES ?? { ui: ['ui', 'ux', 'page', 'react', 'dashboard', 'css', ...], backend: ['api', 'endpoint', 'router', 'service', 'schema', ...], light: ['docs', 'readme', 'chore', 'config', 'typo', ...], tiers: { full: { product: true, technical: true, qa: true, ux: true, playwright: true }, backend: { product: true, technical: true, qa: true, ux: false, playwright: false }, light: { product: false, technical: true, qa: true, ux: false, playwright: false }, standard: { product: true, technical: true, qa: true, ux: true, playwright: true }, }, };
Classification scans the issue title and description for keywords. The first matching tier wins. If no keyword matches, the issue gets the standard tier (full four perspectives). No code change is needed to tune the keyword lists — update them in the override file via AURIGA_CONFIG.
AGENTS
The agent registry in lib/config-substrate.mjs. Maps agent IDs (Multica UUIDs) to agent metadata used during dispatch.
// Each entry in AGENTS: { "<uuid>": { name: "auriga-build", // display name runtime: "claude", // runtime bucket for RUNTIME_CAP maxInflight: 3, // max concurrent in_progress issues lane: "hive", // routing lane (optional — overrides PROJECT_LANE) } }
Add an entry here when a new agent joins the swarm. The runtime field must match a key in RUNTIME_CAP. The maxInflight per-agent cap is checked independently of the per-runtime cap — both must have room for an issue to be dispatched to that agent.
RUNTIME_CAP
A map from runtime bucket name to the maximum number of concurrently in_progress issues that bucket can hold. Defined in config-substrate.mjs and mutated in config.mjs to add the review bucket.
// config-substrate.mjs — base runtime caps export let RUNTIME_CAP = { claude: 4, codex: 6, opencode: 4, 'claude-planning': 1, }; // config.mjs — review gets its own bucket RUNTIME_CAP['claude-review'] = 1;
The runtime cap check is: count the in_progress issues assigned to all agents in the same runtime bucket, then compare against the cap. If the bucket is full, no further dispatches happen to any agent in that bucket this cycle.
Lane configuration
Lane maps are in config-substrate.mjs. They determine which Multica agent lane receives each dispatched story.
| Export | Role |
|---|---|
| PROJECT_LANE | Map from Multica project ID → lane name. Defines which lane stories from each project go to. |
| DEFAULT_LANE | Fallback lane when no PROJECT_LANE entry matches (used for non-hive stories). |
| HIVE_LANE | Lane used for hive stories (requires Claude + plugin-hive). |
| REVIEW_LANE | Lane used for review squad dispatches. |
| REVIEW_REPO_OWNER | GitHub org/user to search for PRs linked to in_review issues. |
| REVIEW_SEARCH_REPOS | List of repo names to search for linked PRs (within REVIEW_REPO_OWNER). |
External JSON override
Set AURIGA_CONFIG=/path/to/override.json to a JSON file with partial overrides. Only keys present in the file replace the in-source defaults — absent keys keep their values from the source files.
# Start with a custom config file
AURIGA_CONFIG=/etc/auriga/prod.json node src/router/auriga-router.mjs
// /etc/auriga/prod.json — only override what differs from defaults
{
"CAPS": {
"perCycleTotal": 8,
"cycleMs": 60000
},
"HUMAN_NAMES": ["mathew", "dostal", "alice"],
"RUNTIME_CAP": {
"claude": 6,
"claude-review": 2
}
}
The override is processed at startup by lib/config-loader.mjs via loadExternalConfig(). If the file path is invalid or the file is malformed JSON, the router logs a warning and uses the built-in defaults.
Not a merge — a replace
If you override CAPS, you must provide all CAPS keys you want to keep — the external value completely replaces the in-source default for that key. Partially overriding nested objects is not supported; the whole top-level key is replaced.