Skip to content

Add LicensePolicy dispatch override (never auto-execute licence findings) #253

Description

@hyperpolymath

Gap

FleetDispatcher.dispatch_routed_action/1 (lib/fleet_dispatcher.ex:27–90) routes findings by confidence-score tier:

  • ≥ 0.95 → robot-repo-automaton (auto-execute)
  • 0.85–0.94 → rhodibot (auto-PR)
  • < 0.85 → sustainabot (advisory)

The license-policy detector being added in hypatia#416 emits findings tagged category="LicensePolicy". Per estate policy feedback_no_automated_licence_edits, license remediation must be manual / file-by-file / owner-only — but a high-confidence license finding (e.g. workspace Cargo.toml license vs deny.toml allow-list, confidence 0.99) would route to robot-repo-automaton and auto-execute under current logic. That's wrong.

Required wiring

Add a category-override path that runs BEFORE the confidence-tier routing:

def dispatch_routed_action(%{category: "LicensePolicy"} = finding) do
  # Override: licence findings ALWAYS route to advisory tier,
  # never robot-repo-automaton, regardless of confidence.
  dispatch_to(:sustainabot, finding |> Map.put(:dispatch_hint, :advisory))
end

def dispatch_routed_action(finding) do
  # ... existing confidence-tier routing
end

Equivalently, honour the do_not_automate: true flag that the detector sets on every emission:

def dispatch_routed_action(%{do_not_automate: true} = finding) do
  dispatch_to(:sustainabot, finding)
end

The flag approach is more general — covers future categories that share the policy.

Companion guardrail (already in estate memory)

feedback_pr_sweep_title_keyword_exclusion: for any sweep loop, pre-filter PR titles for license|SPDX|PMPL|MPL|AGPL|GPL|Apache|copyright|attribution|relicens|secret|vulnerab|CVE-. Route to manual review even if CI is clean. Origin: neurophone#81 mis-merge incident.

This wiring is the second layer — the detector tags do_not_automate: true, the dispatcher refuses auto-execute, the sweep pre-filter is a fallback. Defence in depth.

Test cases

  1. LicensePolicy + confidence 0.99 → :sustainabot (not robot-repo-automaton)
  2. LicensePolicy + confidence 0.5 → :sustainabot (same routing regardless of confidence)
  3. do_not_automate: true on any category → :sustainabot (general invariant)
  4. Non-license finding at 0.99 → robot-repo-automaton (existing behaviour preserved)

Constraint

This is defensive wiring. The detector at hypatia#416 already sets do_not_automate: true + dispatch_hint: :advisory on every license finding it emits. This issue is the bot-side enforcement so that no other detector emitting category="LicensePolicy" (or relying on the keyword filter) can accidentally bypass.

Related

  • hypatia#416 — the detector that emits these findings
  • verisimdb#82 / verisimdb#101 — the bite that started the campaign
  • Estate memory: feedback_no_automated_licence_edits, feedback_pr_sweep_title_keyword_exclusion, feedback_estate_license_policy_umbrella

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    automationBots, schedulers, dispatch, self-healing, fan-outenhancementNew capability or improvement to existing behaviourlicensingLicences, SPDX headers, REUSE compliance, attribution

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions