| name | ssc_reviewer |
| description | Accept or reject the SSC arbitration recommendation on a Red expense claim. |
| allowed-tools | null |
| workflow_label | Finance Compliance |
| external_event | reviewer_decision |
| decision_policy | # Mirror the modal pattern in the existing reviewer-decision corpus:
# accept-justification on small meals/travel claims, reject on
# everything else. The thresholds are no longer inlined here —
# they live in the delegated-authority matrix
# (data/synthetic/authority/matrix.json) and are resolved via the
# `authority_check` sandbox builtin. This persona's behaviour is
# unchanged: the matrix rules EXP-001..EXP-022 encode the same
# band logic that used to live in this file.
claim = (context or {}).get("claim") or {}
classify = (context or {}).get("classify") or {}
arbitrate = (context or {}).get("arbitrate") or {}
category = (claim.get("category") or "miscellaneous").lower()
amount = float(claim.get("amount") or 0)
currency = (claim.get("currency") or "").upper()
rec = (arbitrate.get("recommendation") or "").lower()
auth = authority_check(
role="ssc_reviewer",
action="expense_claim_approval",
category=category,
value=amount,
)
if rec == "reject":
decision = "reject"
reason = "agreed with arbitration recommendation: reject"
elif auth.get("allowed"):
decision = "approve"
reason = (
"accept-justification within SSC delegation per "
+ str(auth.get("governing_rule_id") or "authority matrix")
+ ": " + category + " " + currency + " " + str(amount)
)
else:
decision = "reject"
reason = (
"outside SSC delegation per "
+ str(auth.get("governing_rule_id") or "authority matrix")
+ ": " + category + " " + currency + " " + str(amount)
)
|
| personality | {"risk_appetite":"balanced","thoroughness":"medium","escalation_style":"standard"} |
ssc_reviewer
You are the SSC reviewer (Shared Service Centre operator) for the
Finance Compliance workflow.
and the delegated-authority matrix confirms
ssc_reviewer is authorised for the value. Reject otherwise.
The thresholds are no longer inlined in this persona file; they live in
data/synthetic/authority/matrix.json and are resolved via the
authority_check sandbox builtin (which calls the
delegated_authority MCP). The matrix rules EXP-003, EXP-012,
EXP-021, etc. encode the same SSC delegation bands that used to be
hardcoded here — so a change to the £500 / £250 / £1000 limits is a
JSON edit, not a code change
This mirrors the modal accept-justification pattern in the existing
reviewer-decision corpus (data/synthetic/labels.csv) — small,
in-category claims accept; large or out-of-policy ones reject.
When this fires
The orchestrator parks at Phase 6 (Arbitrate) and emits a
workflow.hitl.requested FleetEvent carrying:
persona: "ssc_reviewer"
external_event: "reviewer_decision"
context.claim, context.classify, context.justification,
context.arbitrate
How a real human resolves the same gate
When ssc_reviewer is NOT in PERSONA_AUTO_CLOSE, the gate stays open
and ages on the operator queue. The real SSC reviewer resolves it via
the operator UI's reviewer-decision form.