Customer emails disputing an invoice. Extract invoice ref + reason. Attach prior invoices. Propose response. Queue for sales rep. Flag for AR hold-or-continue decision.
event["inbound_email_triage_classification"]| name | required | type / hint |
|---|---|---|
email_uuid | required | — |
customer_id | optional | — |
invoice_ref | optional | — |
reason_text | required | — |
invoicetransactionsSELECT id, tranid, foreigntotal, trandate FROM transactions WHERE type='CustInvc' AND tranid=?
recent_paymentscustomer_paymentsSELECT
*
FROM customer_payments
WHERE customer_id=?
AND payment_date > datetime('now','-90 days')prior_disputesar_disputesSELECT
COUNT(*)
FROM ar_disputes
WHERE customer_id=?
AND status IN ('open','escalated')| check | rule | severity |
|---|---|---|
invoice_exists | invoice IS NOT NULL OR invoice_ref IS NULL | warn |
Risk level 3 ≥ 3 — runner stages a proposed_actions row before fan-out runs. Mike must approve in proposed-actions.html before any side-effect step executes (real or stub).
workflow_customer_invoice_dispute (proposal envelope)workflow:customer_invoice_dispute:run_<run_id>draft_response hitl_email_draft STUBpropose_email_to_customersrc/lib/workflow_runner.ts (kind hitl_email_draft hits the placeholder branch at line ~340 and emits step status 'stub'). Documented intent only.escalate stage_proposed_action REALcustomer_escalationcustomerar_hold_decision stage_proposed_action REALar_hold_reviewprior_disputes >= 2| id | action | source |
|---|---|---|
runner_log_run | INSERT into workflow_run_log (run_id, workflow_type, status, started_at, completed_at, summary_json) | runner automatic |
runner_reflexion | INSERT into reflexion_log (tags=customer_invoice_dispute, run_id, narrative) | runner automatic (reflexion_enabled=1) |
log_run | INSERT workflow_runs | declared in contract |
reflexion | INSERT reflexion_log with tags=invoice_dispute,customer:? | declared in contract |
workflow_verify_results (pending — verify cron not yet wired)response_draftedSELECT id FROM proposed_actions WHERE action_type='customer_email' AND proposed_at > ?
2linear3000true| system | table / resource | action | status | source |
|---|---|---|---|---|
| D1 | proposed_actions | INSERT (action_type=customer_escalation, entity_type=customer) | REAL | fan-out #2 (escalate) |
| D1 | proposed_actions | INSERT (action_type=ar_hold_review, entity_type=workflow_run) | REAL | fan-out #3 (ar_hold_decision) |
| D1 | workflow_run_log | INSERT (run summary) | REAL | runner automatic |
| D1 | reflexion_log | INSERT (tags=customer_invoice_dispute) | REAL | runner automatic |
| Event | workflow.completed (or workflow.failed) | fire | REAL | runner automatic |
| D1 | workflow_verify_results | INSERT pending × 1 | REAL | runner verify staging |
| D1 | proposed_actions | INSERT (HITL gate envelope) | REAL | runner HITL gate |
| D1 | proposed_actions | INSERT (email draft via propose_email_to_customer) | STUB | fan-out #1 (draft_response) |