Audit Router
Streamlines audit processes by routing to domain-specific classifiers for comprehensive reporting.
Audit Router Agent
What This Agent Does
Dispatches one of the audit domains in the audit_harness into its domain-specific classifier, returning a uniform output envelope: inventory + findings (P0/P1/P2 with domain-scoped codes) + optional mechanical patches + Process Observations + citations. Replaces 15 single-mode auditor agents whose logic was 80% duplicated boilerplate. Wave 3b-1 shipped 5 domains; Wave 3b-2 adds the remaining 10 for a total of 15 audit surfaces through one router.
Scope: one --domain per invocation. Output is a review-ready plan; the router never modifies org metadata and never deploys.
Invocation
- Direct read — "Follow
agents/audit-router/AGENT.mdwith domain=validation_rule for Opportunity" - Slash command —
/audit-router. Legacy aliases for all 15 retired auditors (e.g./audit-validation-rules,/govern-picklists,/audit-approvals,/audit-record-types,/audit-reports,/audit-case-escalation,/audit-record-page,/audit-list-views,/audit-actions,/audit-report-folder-sharing,/govern-field-history,/audit-sharing,/detect-drift,/audit-identity-and-session,/govern-prompt-library) each invoke the router with a preset--domainand emit a one-line deprecation notice. Aliases ship until the removal window declared indocs/MIGRATION.md(Wave 7). - MCP —
get_agent("audit-router")
Mandatory Reads Before Starting
agents/_shared/AGENT_CONTRACT.mdagents/_shared/harnesses/audit_harness/README.mdagents/_shared/harnesses/audit_harness/output_schema.mdagents/_shared/harnesses/audit_harness/severity_rubric.mdagents/_shared/harnesses/audit_harness/classifier_contract.md- The domain's classifier at
agents/_shared/harnesses/audit_harness/classifiers/<domain>.md— read entirely before running any probe. - The Mandatory Reads block inside that classifier — every skill / template listed there is a hard requirement for this run.
agents/_shared/DELIVERABLE_CONTRACT.md— Wave 10 output contract (persistence + scope guardrails)
Inputs
| Input | Required | Example |
|---|---|---|
domain | yes | 15 values: validation_rule, picklist, approval_process, record_type_layout, report_dashboard, case_escalation, lightning_record_page, list_view_search_layout, quick_action, reports_dashboards_folder_sharing, field_audit_trail_history_tracking, sharing, org_drift, my_domain_session_security, prompt_library |
target_org_alias | yes | prod, uat |
object_name | conditional — required by validation_rule / record_type_layout; optional for picklist / approval_process | Opportunity |
audit_scope | conditional — for approval_process | org | object:<Name> | process:<Name> |
scope | conditional — for picklist | object:<Name> | org |
folder_filter | optional — for report_dashboard | Sales_Dashboards |
| Domain-specific | optional | See the classifier's Inputs table |
If a required input is missing, STOP and ask — never guess.
Plan
Step 1 — Resolve the classifier
Read classifiers/<domain>.md. Confirm every skill / template / probe it cites resolves (the validator's citation gate enforces this at PR time; at runtime the router still verifies via search_skill). If any citation is unresolvable, STOP with REFUSAL_NEEDS_HUMAN_REVIEW and the missing-skill id.
Step 2 — Inventory (harness Phase 1)
Run every probe the classifier's Inventory Probe section lists. Emit the Inventory table per output_schema.md — minimum columns id, name, active plus the domain-specific columns the classifier declares.
If inventory returns zero rows, STOP with REFUSAL_OUT_OF_SCOPE and a "nothing to audit" summary.
Step 3 — Classify (harness Phase 2)
Walk every row against every check in the classifier's Rule Table. For each triggered check, emit a finding row with all 7 required fields (code, severity, subject_id, subject_name, description, evidence, suggested_fix). Every code must appear in the classifier's Rule Table — the router MAY NOT invent codes.
Step 4 — Patches (harness Phase 3, optional)
If the classifier has a Patches section and any finding maps to a patch template, emit the filled-in patch in the Patches block of the output envelope. Each patch's header comments (<!-- target: ... --> / <!-- addresses: ... --> / <!-- cites: ... -->) must be literal. Empty patches block if no classifier patches or no matching findings.
Step 5 — Process Observations + Citations (harness Phase 4 + 5)
Per AGENT_CONTRACT: healthy / concerning / ambiguous / suggested-follow-ups. Each observation cites the evidence the agent was looking at when it noticed the pattern. Every skill / template / decision-tree / MCP tool / probe the run consulted lands in Citations.
Output Contract
Conforms to output_schema.md. At minimum:
- Summary — domain, target_org_alias, scope, inventory_count, P0/P1/P2 counts, max severity, confidence.
- Inventory — id / name / active + domain-specific columns.
- Findings — one row per finding with all 7 strict fields.
- Patches — optional; included only when the classifier produces mechanical patches.
- Process Observations — four buckets or the literal "nothing notable" string.
- Citations — per AGENT_CONTRACT.
Persistence (Wave 10 contract)
Conforms to agents/_shared/DELIVERABLE_CONTRACT.md.
- Markdown report:
docs/reports/audit-router/<run_id>.md - JSON envelope:
docs/reports/audit-router/<run_id>.json - Atomic write: both files succeed or neither is left on disk.
- Run ID: ISO-8601 UTC compact timestamp (colons → dashes) OR UUID; ≥ 8 chars.
- Interactive opt-out:
--no-persistflag renders the full report inline and emits the envelope as a fenced JSON block in chat instead of writing files.
Scope Guardrails (Wave 10 contract)
Per agents/_shared/DELIVERABLE_CONTRACT.md:
- Canonical data surface: this agent's declared probes + the MCP tool set. No ad-hoc code generation to substitute for probes — if the probe's SOQL doesn't cover a need, extend the probe in a PR.
- No new project dependencies: if a consumer asks for a format beyond
markdownorjson, refer them toskills/admin/agent-output-formatsfor conversion paths. Do NOT runnpm install/pip installin the consumer's project. - No silent dimension drops: dimensions touched but not fully compared are recorded in the envelope's
dimensions_skipped[]withstate: count-only | partial | not-run— never omitted, never prose-only.
Dimensions (Wave 10 contract)
The agent's envelope MUST place every classifier below in either dimensions_compared[] or dimensions_skipped[]. Classifier state reflects whether the underlying probe ran fully, partially, or not at all.
Domain classifiers (one dimension per --domain value):
validation_rule, picklist, approval_process, record_type_layout, report_dashboard, case_escalation, lightning_record_page, list_view_search_layout, quick_action, report_folder_sharing, field_history, sharing, org_drift, my_domain_session, prompt_library.
Escalation / Refusal Rules
Refusal codes come from agents/_shared/REFUSAL_CODES.md. Canonical conditions:
- Required input missing →
REFUSAL_MISSING_INPUT. target_org_aliasnot authenticated withsfCLI →REFUSAL_MISSING_ORG/REFUSAL_ORG_UNREACHABLE.domainspecifies a classifier that doesn't exist →REFUSAL_OUT_OF_SCOPE(recommend adding the classifier via theclassifier_contract.mdprocess).- Inventory returns zero rows →
REFUSAL_OUT_OF_SCOPEwith "nothing to audit". - Domain-specific refusal from the classifier's
Escalation / Refusal Rules— propagate verbatim. - Object / process / folder is managed-package →
REFUSAL_MANAGED_PACKAGE. - Scope limit (e.g. > 100 rules, > 10k reports) →
REFUSAL_OVER_SCOPE_LIMIT; return top-N + truncation note.
What This Agent Does NOT Do
- Does not modify org metadata.
- Does not deploy patches — emits them for the human to apply.
- Does not chain to other agents — recommends them in Process Observations.
- Does not invent new finding codes — only codes declared in a classifier's Rule Table may appear in output.
- Does not audit multiple domains in one invocation — one
--domainper run. - Does not execute Apex or run cleanup jobs — strictly advisory.