Concept

Feedback learning channel

When the user modifies Cortex's draft before approving — tweaks the tone, swaps a recipient, shifts a meeting time — that modification is the single most valuable per-counterparty learning signal available. The feedback learning channel captures the delta and feeds it into the trust state machine + rule-candidate pipeline. Substantive deltas demote trust; cosmetic deltas emit a low-confidence voice-style candidate without trust impact.

Two ingress paths, one learning hook

Path 1: trigger.complete executed_modified outcome (ADR-0019 amendment)

When your handler executes a Cortex trigger but the user modified the draft before approving, report outcome="executed_modified" with an applied_payload field carrying the delta:

json
POST /v1/triggers/trg_01HX.../complete
{
  "outcome": "executed_modified",
  "executed_at": "2026-06-15T19:24:00Z",
  "applied_payload": {
    "to": "marcus@example.com",
    "subject": "Re: Project timeline",
    "body_draft": "Hey Marcus — sounds good. Let's sync Thursday afternoon instead.",
    "tone": "casual"
  },
  "external_ref": "msg_abc123"
}

applied_payload has the same JSON shape as the original envelope payload field. The substrate computes the delta on its side; you don't need to compute or send a diff. This is the primary, recommended path.

Path 2: feedback.signal

For explicit customer-side feedback affordances that don't fit the dispatch round-trip (e.g., a “this rule is wrong” button in your settings UI), feedback.signal takes atarget_id (decision_id / action_id / rule_id / trigger_id), a signal_kind, and a payload. MVP supports signal_kind="modification_delta"; other kinds return feature_not_available.

The modification-delta classifier

The learning hook (packages/feedback-learning/) doesn't treat every modification as a correction. It runs the delta through a classifier — Sonnet-routed, structured output, deterministic at temperature 0, sandbox-friendly — that splits the delta into substantive vs cosmetic:

  • Substantive — counterparty change, intent change, payload-class change, recipient swap, semantic content rewrite. Writes a negative trust-survival signal for the (user × action_class × counterparty) triple; emits a rule candidate referencing the source rule + the substantive delta; consolidation reviews and proposes a refinement.
  • Cosmetic — whitespace, polite-tone padding, ordering, casing, minor tone shift. Emits a low-confidence voice-style rule candidate (counterparty_voice family); no trust impact. The substantive trust ladder is untouched.

What the substrate does with the signal

Over time, Cortex's drafts for each (user × counterparty × action class) converge on the user's voice without anyone authoring an explicit rule. The mechanism:

  1. User modifies draft → your handler reports executed_modified withapplied_payload.
  2. Classifier splits the delta. Substantive deltas emit a rule candidate (visible via patterns.list).
  3. Consolidation Phase 2 reviews recurring deltas and proposes a refinement to the source rule via the existing rule-candidate ceremony.
  4. Next time Cortex drafts for the same triple, the refined rule produces a draft closer to the user's actual voice.

Cross-references

  • Concept: Counterparty depth — the per-counterparty intelligence loop the feedback channel closes.
  • Concept: Explainability — track rule-candidate proposals via decision.history + meta.what_rules_fired.
  • Dispatch protocol (ADR-0019, amended) — the trigger.complete callback path is where Path 1 lands.
  • ADR-0019 amendment (additive executed_modified outcome); ADR-0021 §learning-channel; Architecture §4a.11; Pattern §5.16 (Modification Learning Pattern).