Standard operating procedure · SOP-13

AI Actions & Signal Providers

Version 1.0 · effective 13 July 2026 · owner: Jonny Allum

Trigger: adding or changing anything JonnyAI can see (signals) or do (actions). Owner: Jonny Allum. Policy anchor: POL-05 — read it first; this SOP implements it.

1. Signal providers (what JonnyAI sees)

  1. One provider per module in apps/shell/src/lib/ai/signals.ts — coverage is total and audit.mts fails the build if a registered module lacks one. New module ⇒ provider ships in the same PR (SOP-02 §8).
  2. Reuse the module's engine maths. The provider must agree with the board; a signal computed differently from the UI is a defect.
  3. Output stays compact: counts, renewal bands (expired/30/60/90/ ok), byStatus maps, one named worst item. *GBP fields are pounds, *Pct whole percentages. Never row dumps — this is the POL-05 §3 data-minimisation line, enforced in code review of the PR.
  4. Failures degrade to null, never throw into the ask path.
  5. Widening what a provider sends (new fields, more detail)? Write the short DPIA note (POL-02 §6) in the PR description.

2. Executable actions (what JonnyAI does)

  1. Actions live in apps/shell/src/lib/ai/action-registry.ts. Every action:
    • carries a user confirm step — no exceptions, ever (POL-05 §2);
    • binds to the active tenant and checks capabilities;
    • validates its inputs server-side like any public write path;
    • is metered by plan caps.
  2. Forbidden as AI actions: destructive bulk operations without a scoped preview, anything that sends money, anything that files externally (the HMRC red line — POL-05 §6), anything crossing tenants.
  3. New action ⇒ round-trip test covering: happy path, confirm-step actually gates execution, and tenant-binding rejects a foreign tenant id.

3. Prompts and backends

  • Prompt changes live in packages/ai/src/prompt.ts and keep the two invariants: rewrite-not-recompute, strict-JSON output defensively parsed. A confused model must never beat the deterministic engine.
  • Adding a backend: it must implement the same enrich/ask contract and the same graceful degradation (any transport/parse error → local fallback with a note, never a throw).
  • Provenance badges ("JonnyAI · model" vs "Composed (rules engine)") are preserved through any refactor — POL-05 §4.

4. Release

Sensitive-class change (POL-06 §2): cooling-off review + authenticated production smoke test of one enriched surface and one action confirm flow after deploy.

← All documents & policiesQuestions? hello@jonnyai.co.uk