The Ops Atlas xOps School

Data & AI Vendor/platform-specific label Sources verified

DecisionOps

DecisionOps is a vendor-coined label for running automated decisions like managed software: decision logic built from rules, model scores and optimisation is versioned, tested offline and online, logged for audit and improved against measured outcomes.

Key takeaways

  • DecisionOps is a vendor-promoted label (Nextmv, now part of FICO, and a few others), not a standard; the practice behind it, decision management with DMN and champion/challenger testing, is much older.
  • Make the decision, not the model, the unit of work: one owner, one version, one test suite and one log record for every decision made.
  • Test in a ladder: table checks, replay on stored inputs, shadow runs, then a randomised champion/challenger or switchback test. Replay cannot tell you how newly approved cases will behave.
  • Log every decision with its inputs, version, rule path, assignment probability and, later, its outcome; without version and probability you can neither audit nor compare fairly.
  • Human review counts only when the reviewer has the time, information and authority to change the outcome; automation bias affects experts too.
  • Do not automate a decision you cannot explain, contest or roll back; several jurisdictions restrict solely automated decisions with significant effects.

DecisionOps is the work of running automated decisions the way good teams run software. A decision here is a repeated operational choice made by a system: approve, refer or decline a refund; which driver gets which delivery; which offer a customer sees; whether a payment is blocked. Its logic usually mixes business rules, model scores and sometimes optimisation. DecisionOps gives that logic an owner, a version, tests, a controlled release, a log of every decision made, and a loop that compares decisions with their outcomes so the logic improves.

The idea in one line: the model predicts; the decision acts; DecisionOps operates the act. A fraud model that is 2% better is worth nothing if the threshold that turns its score into “block” is edited by hand in production and nobody can say which version blocked a customer last Tuesday.

Where to start. Beginners: the glossary and Lab 1. Engineers: the reference architecture and the testing ladder. Leaders: the decision framework and the judgement call. Last verified 2026-10-23.

Aspect Summary
Goal Automated decisions that are correct by construction, testable before release, explainable and contestable afterwards, and better over time
People Decision owners (business), rules analysts, decision scientists, optimisation engineers, platform engineers, reviewers, risk and compliance
In scope Decision inventory; decision logic (rules, DMN, thresholds, strategies, optimisation); combining rules with model scores; human referral; testing (replay, shadow, champion/challenger, switchback); release and rollback; decision logs and audit; outcome measurement
Out of scope Training models → MLOps; approving models and rule sets as models → ModelOps; metric definitions → AnalyticsOps; human leadership decisions → BizOps; risk appetite → RiskOps; AML and fraud policy → FinCrimeOps
Prerequisites Basic statistics; helps: MLOps or AnalyticsOps
Key outputs A decision inventory, versioned decision logic with tests, a release record per change, a decision log, a monthly decision scorecard
Term status Vendor-specific label (note above); the practice is established under other names

Organisations automate thousands of small decisions a day and rarely treat them as a product. The publisher’s description of Taylor and Raden’s 2007 book on enterprise decision management says many business decisions “tend to be hidden in systems that make poor decisions, or don’t make them at all”.[11] Hidden decisions fail in recognisable ways:

  • Logic nobody can see whole. A threshold lives in a config file, an exclusion in a stored procedure, a “temporary” override in a spreadsheet. Nobody can say what the policy is, only what the code does.
  • Changes nobody can test. A rules analyst edits a cut-off; it goes live at once; the effect shows up weeks later in losses or complaints. Stripe’s documentation warns that a rule “can automatically allow a large number of elevated or high-risk payments or block a large number of legitimate payments, if it isn’t set up properly”.[14]
  • Decisions nobody can explain. A customer complains; nobody can reconstruct which version, inputs and rule produced the outcome. In US credit, reasons for adverse action must be specific; “failed to achieve a qualifying score” is not enough.[15]
  • Outcomes nobody joins back. Decisions sit in one system, outcomes arrive months later in another.
  • Dead logic that wakes up. In 2012 Knight Capital’s new trading code reused a flag that once switched on retired “Power Peg” code; one of eight servers missed the deployment, and the loss ultimately exceeded $460 million.[16] ReleaseOps tells the case in full.
Operating reality Without DecisionOps With DecisionOps
What the policy is Spread across code, config and people One versioned decision definition per decision
A change Edited live Reviewed, replayed, shadowed, released to a share of traffic
A complaint Hours of archaeology One decision record: inputs, version, rule path, reviewer
Learning Opinions in a meeting Champion/challenger results joined to outcomes

What DecisionOps is not: boundaries and naming

Link to section “What DecisionOps is not: boundaries and naming”
  • Not MLOps for rules. MLOps produces reliable scores; DecisionOps decides what to do with them, together with policy rules, costs and capacity.
  • Not ModelOps. Gartner’s ModelOps definition covers “decision models” including rules and optimisation.[17] This Atlas’s editorial distinction (not an industry rule): ModelOps governs models and rule sets (inventory, tier, approval); DecisionOps runs the decision logic built from them (authoring, testing, release, logging, measurement).
  • Not “decision intelligence” by another name. Gartner’s decision intelligence covers how decisions are made and “how outcomes are evaluated, managed and improved via feedback”, human or automated;[13] DecisionOps is the slice run by software. Nor is it a product: a decision list, a rules engine or plain code, a log table and discipline are enough.

The pieces are older than the word. A Fair Isaac patent filed in 2000 describes champion/challenger testing: every account gets a two-digit “random digit”, a challenger strategy runs on a slice such as 10% of a portfolio, and a winner is rolled out “as a new champion”.[18] Taylor and Raden argued for enterprise decision management in 2007.[11] OMG published DMN 1.0 in September 2015 and 1.6 in September 2026.[12] Gartner’s Critical Capabilities report for Decision Intelligence Platforms is dated 27 January 2026, as FICO reports.[19] The label DecisionOps came from optimisation: Nextmv’s 1.0 launch (2023) asked “So what if we treated decisions as code?”[2]

Term Meaning on this page
Decision DMN: “the act of determining an output value (the chosen option), from a number of input values, using logic”.[20] Here: a repeated, automated or automation-assisted choice
Decision requirements graph (DRG) DMN’s network of decisions, input data and knowledge that each decision requires[20]
Decision table and hit policy Rules in rows; the hit policy says what happens when several match (Unique, First, Priority, Collect…)[20]
Decision service A callable unit that evaluates a set of decisions; DMN requires it to be stateless with no side effects[20]
Strategy A complete version of decision logic for one decision
Champion / challenger The current strategy and a candidate tested against it on a random share of cases[18]
Replay (backtest) Running stored past inputs through a new version offline and comparing outputs
Shadow Running the candidate on live inputs without acting on its output[21]
Switchback test Randomising versions over time windows and regions, not individual units, when units interact[22]
Referral / override Handing a case to a person; a person changing the automated outcome
Decision log One immutable record per decision: inputs, version, path, output, assignment, reviewer, later outcome
Outcome window Time until the outcome is known (minutes for a click, months for a loan default)
Selective labels Outcomes observed only for cases the old logic let through[23]
Propensity The probability with which a randomised assignment chose this version or action[24]

Mental model: a decision is a function with a contract, a version and a memory. The contract fixes inputs and allowed outputs (including “refer to a person”); the version says which logic ran; the memory is the decision log, later joined to the outcome. DecisionOps keeps all three true while the logic changes weekly.

Neighbour Shared ground The neighbour owns DecisionOps owns
MLOps Scores used in decisions Training, serving and monitoring reliable scores Thresholds, strategies and rules that turn scores into actions
ModelOps Rules and models in production Inventory, tiering, approval of models and rule sets Authoring, testing, releasing and logging the decision logic
AnalyticsOps Metrics Governed metric definitions Decision-level metrics that use them
BizOps “Decisions” Human leadership decisions and their decision log Automated decision logic and its audit
RiskOps Risk appetite Appetite and acceptance Encoding limits (exposure caps, referral bands) in logic
FinCrimeOps Fraud and AML rules Domain policy and investigations The engine, testing and release of those rules
LLMOps LLMs and agents in decisions Evaluations, guardrails, traces The decision contract and log around an LLM step
ReleaseOps Progressive rollout Release strategy for software Release of decision versions, which may change without a code deploy

Also: DataOps supplies the input data; PrivacyOps the lawful basis for using it; ComplianceOps collects audit evidence; KnowledgeOps maintains the policy documents rules come from.

Figure 1. Where DecisionOps sits: it turns inputs into actions within limits set by others
intentapproval, limitsoutcomes, overridesInputs: MLOps scores,DataOps data, AnalyticsOpsmetric definitionsBizOps: policy intent fromleadersDecisionOps: logic, tests,release, decision log,outcomesActions in business systemsModelOps and RiskOps:approvals and limits
Diagram source (Mermaid)
flowchart TB
  IN["Inputs: MLOps scores, DataOps data, AnalyticsOps metric definitions"]
  BZ["BizOps: policy intent from leaders"]
  DO["DecisionOps: logic, tests, release, decision log, outcomes"]
  ACT["Actions in business systems"]
  GOV["ModelOps and RiskOps: approvals and limits"]
  IN --> DO
  BZ -.->|"intent"| DO
  DO --> ACT
  DO <-.->|"approval, limits"| GOV
  ACT -->|"outcomes, overrides"| DO
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  class DO core
  class IN,BZ,GOV neutral
  class ACT decision

Text equivalent: Inputs flow into DecisionOps: model scores from MLOps, input data from DataOps and metric definitions from AnalyticsOps; BizOps supplies policy intent from leaders. DecisionOps owns the decision logic, its tests and release, the decision log and outcome measurement, and produces actions in business systems. ModelOps and RiskOps exchange approvals and limits with it. Outcomes and human overrides flow back from the business systems to DecisionOps.

No official manifesto exists; this charter is this Atlas’s proposal.

Mission. Every automated decision has an owner, a definition anyone can read, a tested version, a record of each time it ran, and evidence that it does what its owner intends.

  1. One decision, one owner, one definition. The owner is a business role accountable for outcomes, not the engineer who wrote the code.
  2. Logic is versioned with its tests. Tables, thresholds and strategies live in version control with test cases, whatever runs them.
  3. No silent outcomes. A DMN table with no matching rule returns null unless a default is set.[20] Every decision ends in an allowed output, and “refer to a person” counts as an output.
  4. Every decision leaves a record of inputs, version, path, output, assignment probability, reviewer and, later, outcome.
  5. Change climbs a ladder whose height matches the risk: a threshold inside an approved band needs less than a new data source.
  6. Human review must be real. Reviewers need time, information and authority; otherwise it is, in the Article 29 Working Party’s words, “just a token gesture”.[25]
  7. Learn from randomised comparisons, not stories. Outcomes observed only for cases the old logic accepted cannot prove a new one.[23]
  8. Explainable and contestable by design. Reason codes are written with the rule, not reverse-engineered after a complaint.

Non-goals. Approving models (ModelOps) and setting risk appetite (RiskOps).

Block What it is Typical form
Decision inventory List of automated decisions with owner, volume, effect on people, outcome window Table or catalogue
Decision card The contract: purpose, inputs, outputs, reason codes, fallback, limits, metrics YAML or wiki page (template)
Decision logic Tables, rules, scorecards, thresholds, optimisation models DMN, rules-engine files, code, solver models
Decision service Stateless runtime that evaluates a pinned version API, library, stream processor
Assignment Chooses champion or challenger per unit or time window; records the probability Hash on a unit id with a per-experiment salt
Decision log Append-only record per decision Event stream into a warehouse table
Review queue Cases referred to people; overrides with reasons Case-management tool
Outcome join Links each decision to its outcome when known Scheduled job keyed by decision id

R = responsible, A = accountable, C = consulted, I = informed.

Activity Decision owner Decision engineer / rules analyst Decision scientist Platform engineer ModelOps / risk / compliance
Define the decision, outputs and success metric A R C I C
Change logic (rules, thresholds, strategy) A R C I C (A if the change is material)
Design and read experiments A C R C I
Run the decision service and log I C I A, R I
Approve models and material rule sets C C C I A, R (ModelOps)
Handle a contested decision A R (reconstruct from log) C C C
Retire a decision or rule A R C R I

Small organisations combine roles, but an owner should not approve their own material changes.

Stage What happens Exit evidence
Discover Find hidden decisions; add to inventory Owner named; volume and effect on people recorded
Design Write the decision card; draw the DRG if decisions depend on each other Card reviewed; fallback and reason codes defined
Build Author logic and test cases Table checks pass (no overlaps under Unique, no gaps); unit tests pass
Validate offline Replay stored inputs; check acceptance criteria Decision-change matrix reviewed and signed
Release Shadow, then a randomised share, then full No sample ratio mismatch; guardrails held; rollback target named
Operate Monitor mix, referrals, overrides, latency, log completeness Monthly scorecard
Learn Join outcomes; compare champion and challenger Decision to promote, iterate or stop, recorded
Retire Remove the decision or a rule, including dead code paths No callers; logic deleted, not just disabled

Governance turns on change classes (this Atlas’s proposal; align them with your ModelOps change classes):

Class Example Minimum path Approver
P: parameter inside an approved band Referral threshold moves from 0.12 to 0.13 within a band of 0.10–0.15 Peer review, table checks, replay Decision owner
L: logic change New rule, reordered table, new input field, new reason code P + shadow + randomised share with guardrails Owner; compliance if eligibility, price or a protected group may be affected
M: material change New model or solver formulation, new data source, newly automated decision L + ModelOps approval + impact assessment Model risk or equivalent authority
E: emergency Fraud attack; a broken input Switch to a pre-approved fallback strategy; full review within days On-call owner, then retrospective approval

Cadence. Weekly: alerts, referrals, override reasons. Monthly: the scorecard. Quarterly: strategy and inventory review. Redo the impact assessment when scope changes, as Canada’s directive requires.[26]

A decision service evaluates a pinned version of the decision logic. Assignment chooses the version, the log records everything, and outcomes return later.

Figure 2. Reference architecture of an automated decision with experiments, review and an outcome loop
Decision service: one pinned versionvalideligibleinvalid: referno optimiserallocation neededrefer bandrule refuses: referreviewer's decisionwrite, then actjoin by decision idroutes to one versionreleaseCalling system: checkout,claims, dispatchAssignment: champion orchallenger, with probabilityAssemble and validate inputsPolicy rules: eligibility, hardlimitsModel score callStrategy table: bands, reasoncodesOptimiser (optional)Review queue: people withauthorityDecision log: append-onlyAction and notice to thecustomerOutcome join, days to monthslaterVersion registry and tests inGit
Diagram source (Mermaid)
flowchart TB
  CALL["Calling system: checkout, claims, dispatch"]
  ASG["Assignment: champion or challenger, with probability"]
  subgraph SVC["Decision service: one pinned version"]
    direction TB
    IN["Assemble and validate inputs"]
    POL["Policy rules: eligibility, hard limits"]
    SC["Model score call"]
    STR["Strategy table: bands, reason codes"]
    OPT["Optimiser (optional)"]
  end
  REV["Review queue: people with authority"]
  LOG[("Decision log: append-only")]
  ACT["Action and notice to the customer"]
  OUT["Outcome join, days to months later"]
  REG["Version registry and tests in Git"]
  CALL --> ASG -->|"routes to one version"| SVC
  IN -->|"valid"| POL
  POL -->|"eligible"| SC --> STR
  IN -->|"invalid: refer"| REV
  STR -->|"no optimiser"| LOG
  STR -->|"allocation needed"| OPT
  STR -->|"refer band"| REV
  POL -->|"rule refuses: refer"| REV
  OPT --> LOG
  REV -->|"reviewer's decision"| LOG
  LOG -->|"write, then act"| ACT
  ACT --> OUT
  OUT -.->|"join by decision id"| LOG
  REG -.->|"release"| SVC
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class IN,POL,SC,STR,OPT core
  class CALL,ACT,OUT,REG neutral
  class ASG,REV decision
  class LOG risk

Text equivalent: A calling system (checkout, claims or dispatch) sends a request; assignment chooses the champion or a challenger version and records the probability. Inside the decision service (one pinned version), invalid inputs and requests a policy rule refuses are referred to a review queue of people with authority. Eligible requests get a model score; a strategy table applies bands and reason codes, refers its referral band, sends cases needing an allocation to the optional optimiser, and passes the rest on. Every automated result and every reviewer’s decision is first written to the append-only decision log, and only then becomes an action and a notice to the customer (“write, then act”). Outcomes are joined back by decision id days or months later. Versions and tests live in Git and are released into the service.

Design choices and trade-offs.

  • Rules before scores, so a score can never approve what policy forbids, and the reason is a rule, not a probability.
  • Stateless service. DMN decision services are stateless with no side effects;[20] counters such as refunds_90d are inputs computed elsewhere, so a replay reproduces the decision.
  • Pin the version per request, and make every replica run it (Knight’s failure above).
  • No record, no action. If logging fails, refer or fail closed. Open Policy Agent, by contrast, drops decision-log events beyond a configured rate limit;[27] know what your stack does.
  • Rules engine or code? DMN gives readable tables and a standard, but engines differ: on the DMN TCK (results page updated August 2026), engines with submitted results range from 3,391 of 3,391 tests passed to 2,741, and the suite reflects DMN 1.4, so it says nothing about 1.5 or 1.6 features.[28] Test portability yourself.

End-to-end workflow: one decision, happy and exception paths

Link to section “End-to-end workflow: one decision, happy and exception paths”

Happy path (an illustrative refund request):

  1. Checkout calls refund_auto_approval with order value, customer tenure and refunds in the last 90 days.
  2. Assignment hashes the customer id with the experiment salt: bucket 45, champion 1.3.0, probability 0.9.
  3. Inputs validate; policy rules pass; the strategy table matches rule R2: APPROVE, reason code LOW_VALUE_LONG_TENURE.
  4. The service writes the decision record, then returns APPROVE with its reason code; the refund is issued.
  5. Thirty days later the outcome job marks the refund not_disputed and joins it to the record.

Exception paths:

  • Input missing or out of range (tenure null): the service returns REFER with reason INPUT_INCOMPLETE and alerts if the rate rises; it never guesses.
  • No rule matched: the default rule returns REFER and increments a default_hit counter that should stay at zero.
  • Score service timeout: the pre-approved fallback strategy (policy rules only, wider referral band) runs, and the record says so.
  • Referral: a reviewer sees inputs, reason codes and the recommendation, decides, and records an override reason if they disagree.
  • Contest: support retrieves the record by decision id, gives the reason codes, and a person with authority reconsiders; what the law requires differs by jurisdiction (regulation table).

Search for decisions, not systems. For each, record owner, daily volume, outputs, effect on people, outcome window, where the logic lives and whether people review. Rank by volume × cost of a wrong decision × effect on people; start with the top three. Canada’s definition is a useful net: “Any technology that either assists or replaces the judgment of human decision makers”, including “rules-based systems”.[26]

Playbook 2: write logic that can be checked

Link to section “Playbook 2: write logic that can be checked”
  • Declare the hit policy. DMN’s default, Unique, forbids overlapping rules; First-hit tables “are not considered good practice because they do not offer a clear overview of the decision logic”.[20] If order matters, say so and test it.
  • Close every gap. Either make the table complete or add an explicit default that returns REFER, never null.[20]
  • Attach reason codes to rules, so every output carries a specific reason, as US Regulation B requires for adverse credit action.[15]
  • Type and bound inputs. Ranges, units and null handling belong in the decision card; validation failures become REFER.
  • Keep thresholds as data with an approved band, so class-P changes do not need code changes.
  • Delete retired logic. A disabled rule or reused flag is a loaded path (Knight Capital).

Each rung answers a question the previous one cannot. Nextmv separates offline tests (“run on stored data, which does not involve the production system”) from online shadow and switchback tests;[21] Stripe Radar offers a backtest, shadow at 0% traffic, then a rising share.[14]

Figure 3. The testing ladder for a decision change, with the question each rung answers
passpasspasspassguardrails heldfailfailguardrail breached or SRM1. Table checks and unittests: is the logic wellformed?2. Replay on stored inputs:which decisions change, andhow many?3. Acceptance criteria: arechange rates and knownoutcomes inside limits?4. Shadow on live inputs:does it run correctly atproduction volume?5. Randomised share orswitchback: what happens tooutcomes?6. Full rollout with a namedrollback version7. Post-release review afterthe outcome windowStop or redesign
Diagram source (Mermaid)
flowchart TB
  T1["1. Table checks and unit tests: is the logic well formed?"]
  T2["2. Replay on stored inputs: which decisions change, and how many?"]
  T3["3. Acceptance criteria: are change rates and known outcomes inside limits?"]
  T4["4. Shadow on live inputs: does it run correctly at production volume?"]
  T5["5. Randomised share or switchback: what happens to outcomes?"]
  T6["6. Full rollout with a named rollback version"]
  T7["7. Post-release review after the outcome window"]
  STOP["Stop or redesign"]
  T1 -->|"pass"| T2 -->|"pass"| T3 -->|"pass"| T4
  T4 -->|"pass"| T5 -->|"guardrails held"| T6 --> T7
  T1 -.->|"fail"| STOP
  T3 -.->|"fail"| STOP
  T5 -.->|"guardrail breached or SRM"| STOP
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class T1,T2,T3,T4,T6,T7 core
  class T5 decision
  class STOP risk

Text equivalent: Seven rungs, top to bottom. 1, table checks and unit tests ask whether the logic is well formed. 2, replay on stored inputs shows which decisions change and how many. 3, acceptance criteria check that change rates and known outcomes are inside limits. 4, a shadow run on live inputs shows the version runs correctly at production volume. 5, a randomised share or switchback test measures what happens to outcomes. 6, full rollout names a rollback version. 7, a post-release review follows the outcome window. Failing rung 1 or 3, or breaching a guardrail or finding a sample ratio mismatch at rung 5, leads to “stop or redesign”.

Rungs 1–4 cannot tell you how newly approved cases behave, because the past contains outcomes only for cases the old logic accepted (selective labels). Only rung 5 measures that. For a class-P change you may stop at rung 3 if the decision-change rate is tiny; for class M, climb every rung.

Choosing rung 5. Randomise per unit (customer, account) when units do not interact: classic champion/challenger with a stable hash.[18] When they share capacity, randomise time windows and regions. DoorDash found A/B testing “is not optimal for testing our assignment algorithm”, because giving one delivery the only available Dasher affects the other; its switchback tests randomise “on geographic region and time ‘units’ rather than users”, and analysis respects those units.[22][29]

Before reading any result, check the split. A sample ratio mismatch, “the situation when the observed sample ratio in the experiment is different from the expected”, is a symptom of data-quality problems; Fabijan et al. warn that ignoring it “may result in a bad product modification appearing to be good”.[30] ProductOps teaches experiment hygiene in depth; for decisions the extra work is a stable assignment and a logged propensity per decision, which Lab 3 builds before a short split check.

Playbook 4: design human review that is real

Link to section “Playbook 4: design human review that is real”
  • Refer a band, not everything: borderline scores, missing inputs, high-impact cases; audit a random sample of the rest.
  • Give reviewers time, context and authority, and capture override reasons. WP29: oversight “should be carried out by someone who has the authority and competence to change the decision”.[25]
  • Expect automation bias. A review found it “occurs in both naive and expert participants, cannot be prevented by training or instructions”.[31] Show the recommendation only after a first look in a sample of cases; track override rates per reviewer, where near zero is a warning.
  • Canada’s rule for high-impact systems is blunt: at levels III and IV, “The final decision must be made by a human.”[26]

Playbook 5: release and roll back decision versions

Link to section “Playbook 5: release and roll back decision versions”
  1. Build an immutable artefact (tables, thresholds, model versions) with its tests and replay report.
  2. Release by repointing an instance (Nextmv: “a representation of a version and optional configuration”)[32] or route; rollback is the same pointer change, recorded.
  3. Check every replica reports the new version before raising traffic.
  4. In emergencies, switch to a pre-approved fallback strategy; never edit rules live.
  5. Mind tools whose UI edits apply at once: Stripe keeps rule history “for the past 180 days” (October 2026);[14] export it if you need longer.
  • Define the outcome and its window in the card (default within 12 months, dispute within 30 days); confirm early proxies when the real outcome arrives. Join by decision id.
  • Beware selective labels. In Lakkaraju et al.'s bail example, failure to appear is observed “only if the human judge decides to release the defendant”.[23] Loans, refunds and fraud are the same: you see outcomes only where you said yes.
  • Buy information deliberately. A small randomised share, with each action’s probability logged, lets you estimate what other logic would have done; Bottou et al. stress such data “must be collected with an experiment involving active randomization”.[33] Vowpal Wabbit’s bandit format stores exactly this: action:cost:probability.[24]
Item Type What it gives you Caveats
DMN (OMG) Formal standard; 1.6 adopted September 2026[12] Decision requirements graphs, decision tables with hit policies, the FEEL expression language, decision services; three conformance levels (level 3 requires full FEEL)[20] Engines differ in conformance (TCK); DMN says nothing about testing, release or logging
Champion/challenger Industry practice Random share of units on a candidate strategy; promote on evidence[18] Slow when outcomes take months; needs a stable assignment and logging
Switchback experiments Experiment design Valid comparisons when units interact through shared capacity[22] Fewer independent units, so less statistical power
Counterfactual evaluation Research method Estimates for logic you did not run, from randomised logs[33] Needs logged probabilities and overlap between old and new choices

Regulation that shapes automated decisions (October 2026; jurisdiction-specific; not legal advice):

Jurisdiction Rule What it means for DecisionOps
EU (GDPR) Art. 22: a right not to be subject to a decision “based solely on automated processing” with legal or similarly significant effects, subject to exceptions; for the contract and consent exceptions, safeguards include human intervention and the right to contest[34] Know which decisions are “solely automated”; token human review does not change that[25]
EU (CJEU) SCHUFA (C-634/21, 7 Dec 2023): a credit score is an automated decision “in so far as” lenders give it “a determining role” in granting credit[35] A score supplier can be inside Art. 22 when the decision maker relies on it
EU (consumer credit) Directive (EU) 2023/2225, applying from 20 November 2026: where a creditworthiness assessment “involves the use of automated processing of personal data”, the consumer may request human intervention: an explanation, their point of view, a review (Art. 18(8)); rejections must mention this right (Art. 18(9))[36][37] Not limited to solely automated decisions: credit decisions need a staffed review route; national law sets the detail
EU (AI Act) Annex III lists creditworthiness evaluation and credit scoring as high-risk, except fraud detection[38] Obligations and dates belong to ModelOps; check current dates
US (ECOA) Regulation B, 12 CFR 1002.9(b)(2): specific principal reasons for adverse action[15] Reason codes per rule; the CFPB’s 2022 circular on complex algorithms[39] was withdrawn in May 2025, but the regulation still applies[40]
Canada (federal) Directive on Automated Decision-Making: impact assessment, notice, explanation, peer review, human involvement by impact level, keeping all released versions[26] A ready-made control list, even outside government
UK The Data (Use and Access) Act 2025, s. 80, replaced UK GDPR Art. 22 with Arts 22A–22D, commenced on 5 February 2026:[41][42] “solely automated” means “no meaningful human involvement”; strict limits remain for special-category data and for processing based on recognised legitimate interests; significant solely automated decisions need information, representations, human intervention and contest. ICO draft guidance consultation closed 29 May 2026[43] Check the ICO’s final guidance; build the four safeguards into the review route

Categories first; product facts are dated October 2026 and change often.

Category Job Representative options (verified) Watch-outs
DMN and rules engines Evaluate decision tables and rules Engines reporting DMN TCK results, such as Apache KIE Drools, Camunda, IBM, Trisotech and jDMN[28] Conformance differs; vendor extensions reduce portability
Decision platforms Author, test, deploy and monitor decisions FICO Platform (DMN or decision flows, champion/challenger, simulation);[6] Nextmv (decision models, offline and online tests)[21] Lock-in of logic and logs; export both
Embedded rules in a domain product Rules on top of the vendor’s score Stripe Radar rules with backtest, traffic allocation and shadow at 0%; custom rules depend on the Radar plan, allow rules on request (October 2026)[14] Limited history and logic outside your version control
Optimisation solvers Choose allocations under constraints HiGHS;[44] Google OR-Tools[45] Time limits and optimality gaps make outputs vary; log them
Policy engines with decision logs Authorisation-style decisions Open Policy Agent, whose decision logs carry decision id, input, result and bundle revision, with masking[27] Built for access control; logs can drop events under rate limits
Experiment assignment and analysis Randomise, log probability, analyse In-house hashing plus a statistics library, or a platform such as open-source GrowthBook[46] or Statsig, which also runs switchback tests[47] Unit of randomisation must match the decision’s interference
Decision log store Keep records joinable for years Event stream into a warehouse table Personal data: retention, access, masking

Select on: readable logic, replay in a test harness, a record per decision, version pinning and rollback, and export of logic and logs.

  • LLMs drafting rules. Stripe’s Radar Assistant drafts a rule from a natural-language request, then “Test rule” runs it against history (October 2026; Stripe may use the chat entries for training).[14] Treat generated logic as a class-L change.
  • LLMs or agents inside a decision. Same contract: allowed outputs, reason codes, a REFER exit, full logging, limits enforced by rules after the model. Evaluations belong to LLMOps.
  • Automating the operation (mix alerts, fallback on timeout) is cheap and useful; promoting challengers with no person reading the result is not, for decisions with significant effects.

Illustrative scenario: a retailer automates refund approvals: about 4,000 requests a day, outputs APPROVE or REFER (people decide every refusal), outcome = dispute or abuse within 30 days. The minimum artefacts:

1. The decision card (the contract). Example status: YAML syntax-checked by the validator; not executed.

decision: refund_auto_approval
owner: head-of-customer-care          # a business role, not a person's name
purpose: Approve low-risk refunds instantly; refer the rest to agents
outputs: [APPROVE, REFER]             # no automated refusals in this design
inputs:
  order_value: {type: number, unit: EUR, min: 0}
  tenure_months: {type: integer, min: 0}
  refunds_90d: {type: integer, min: 0}
on_invalid_input: REFER               # reason INPUT_INCOMPLETE
on_no_rule_match: REFER               # reason DEFAULT_RULE; alert if > 0
reason_codes: [LOW_VALUE, LOW_VALUE_LONG_TENURE, NEW_CUSTOMER,
               RECENT_REFUNDS, HIGH_VALUE, INPUT_INCOMPLETE, DEFAULT_RULE]
approved_bands:
  approve_max_order_value: {min: 400, max: 600}  # live value 500; class P inside
service_levels: {p99_latency_ms: 150, log_completeness: 1.0}
outcome: {event: refund_disputed_or_abusive, window_days: 30}
experiments: {unit: customer_id, max_challenger_share: 0.10}
human_review: {queue: refunds-l2, target_handling_minutes: 6}
effects_on_people: financial, reversible; customer may contest via support

2. One decision record. Example status: JSON syntax-checked; not executed. Fields mirror the OPA decision-log idea (decision id, input, result, version)[27] plus what experiments and audits need. recommendation is what the logic suggests (for a referral, what the reviewer is shown); final_output is what was done, set by the reviewer when there is one.

{
  "decision_id": "d-2026-10-23-000481",
  "decision": "refund_auto_approval",
  "version": "1.3.0",
  "arm": "champion",
  "propensity": 0.9,
  "timestamp": "2026-10-23T09:14:07Z",
  "inputs": {"order_value": 120, "tenure_months": 30, "refunds_90d": 1},
  "path": ["policy:eligible", "table:R2"],
  "recommendation": "APPROVE",
  "output": "APPROVE",
  "reason_codes": ["LOW_VALUE_LONG_TENURE"],
  "fallback_used": false,
  "reviewer": null,
  "final_output": "APPROVE",
  "outcome": null
}

3. A release manifest. Example status: YAML syntax-checked; not executed.

release: refund_auto_approval 1.4.0
change_class: L
summary: >-
  Raise long-tenure approve limit from 500 to 600 EUR (inside the approved band,
  class P on its own); new rule R6 makes the release class L
evidence:
  table_checks: pass            # no overlaps, no gaps, 14/14 tests
  replay: {inputs: 90 days, decision_change_rate: 0.031, report: replay-1.4.0.html}
  shadow: {days: 7, errors: 0, p99_latency_ms: 41}
rollout:
  challenger_share: 0.10
  min_days: 21
  guardrail: dispute_rate <= champion + 0.5pp
srm_gate: p >= 0.001 before reading outcomes
rollback_to: 1.3.0
approvals: {owner: head-of-customer-care, compliance: not required (no refusals)}

4. Outcome join and scorecard query. It assumes the log is loaded into a decisions table whose columns are the record’s top-level fields, and an outcomes table (decision_id, disputed). The override rate divides by reviewed cases only, as the KPI table defines it. Example status: executed on 2026-10-23 in SQLite 3.31 on 100 synthetic rows (20 reviewed, 2 overridden, 5 disputed): override_rate 0.1, referral_rate 0.2, dispute_rate 0.05 as computed by hand; not run on real data.

SELECT d.version, d.arm,
       COUNT(*) AS decisions,
       AVG(CASE WHEN d.output = 'REFER' THEN 1.0 ELSE 0 END) AS referral_rate,
       SUM(CASE WHEN d.reviewer IS NOT NULL
                 AND d.final_output <> d.recommendation THEN 1.0 ELSE 0 END)
         / NULLIF(SUM(CASE WHEN d.reviewer IS NOT NULL THEN 1 ELSE 0 END), 0)
         AS override_rate,
       AVG(CASE WHEN o.disputed = 1 THEN 1.0 ELSE 0 END) AS dispute_rate
FROM decisions d
LEFT JOIN outcomes o ON o.decision_id = d.decision_id
WHERE d.decision = 'refund_auto_approval'
  AND d.timestamp < DATE('now', '-30 days')    -- outcome window has closed
GROUP BY d.version, d.arm;

Three labs, standard library Python 3.8 or later, no network, no cost. All three were executed on 2026-10-23 (Python 3.8.10); the outputs shown are copied from those runs. Teardown for every lab: delete the working folder.

Lab 1 (beginner): find overlaps and gaps in a decision table

Link to section “Lab 1 (beginner): find overlaps and gaps in a decision table”

Objective. See why hit policies matter by checking a Unique table automatically. Prerequisites. Python 3.8+; an empty folder. Cost and risk. None. Save the table as refund_table.json. It contains two planted defects that mirror real policy drafting: R1 and R4 disagree about customers with exactly two recent refunds, and R5 was typed as “over 1,000” while the other rules stop at 500. Example status: executed.

{
  "decision": "refund_auto_approval",
  "version": "1.3.0-draft",
  "hit_policy": "UNIQUE",
  "inputs": ["order_value", "tenure_months", "refunds_90d"],
  "output": "action",
  "rules": [
    {"id": "R1", "order_value": [0, 50], "tenure_months": null,
     "refunds_90d": [0, 3], "action": "APPROVE"},
    {"id": "R2", "order_value": [50, 500], "tenure_months": [12, null],
     "refunds_90d": [0, 2], "action": "APPROVE"},
    {"id": "R3", "order_value": [50, 500], "tenure_months": [0, 12],
     "refunds_90d": [0, 2], "action": "REFER"},
    {"id": "R4", "order_value": [0, 500], "tenure_months": null,
     "refunds_90d": [2, null], "action": "REFER"},
    {"id": "R5", "order_value": [1000, null], "tenure_months": null,
     "refunds_90d": null, "action": "REFER"}
  ],
  "tests": [
    {"in": {"order_value": 20, "tenure_months": 1, "refunds_90d": 0},
     "expect": "APPROVE"},
    {"in": {"order_value": 120, "tenure_months": 30, "refunds_90d": 1},
     "expect": "APPROVE"},
    {"in": {"order_value": 120, "tenure_months": 3, "refunds_90d": 0},
     "expect": "REFER"},
    {"in": {"order_value": 900, "tenure_months": 60, "refunds_90d": 0},
     "expect": "REFER"}
  ]
}

Save the checker as check_table.py (intervals are [low, high); null means unbounded or “any”):

"""Check a DMN-style decision table (hit policy UNIQUE).

Reports overlapping rules, gaps (no rule matches) and failing test cases.

Usage: python3 check_table.py refund_table.json
Intervals are [low, high): low inclusive, high exclusive; null means unbounded or "any".
"""
import itertools
import json
import sys


def matches(cond, value):
    if cond is None:
        return True
    low, high = cond
    return (low is None or value >= low) and (high is None or value < high)


def probe_values(rules, name):
    """Each bound plus the values 0.5 below and above it."""
    bounds = {0}
    for rule in rules:
        cond = rule[name]
        if cond is not None:
            bounds.update(b for b in cond if b is not None)
    values = set()
    for b in bounds:
        values.update({b - 0.5, b, b + 0.5})
    return sorted(v for v in values if v >= 0)


def evaluate(table, case):
    return [r for r in table["rules"]
            if all(matches(r[name], case[name]) for name in table["inputs"])]


def main(path):
    table = json.load(open(path))
    names = table["inputs"]
    grids = [probe_values(table["rules"], n) for n in names]
    overlaps, gaps, seen = [], [], set()
    for combo in itertools.product(*grids):
        case = dict(zip(names, combo))
        hits = evaluate(table, case)
        if len(hits) > 1:
            key = tuple(r["id"] for r in hits)
            if key not in seen:
                seen.add(key)
                overlaps.append((key, case))
        elif not hits and len(gaps) < 3:
            gaps.append(case)
    print(f"{table['decision']} v{table['version']} hit policy {table['hit_policy']}")
    print(f"probe points: {len(list(itertools.product(*grids)))}")
    for key, case in overlaps:
        print(f"OVERLAP {'+'.join(key)} at {case}")
    for case in gaps:
        print(f"GAP (no rule, result null) at {case}")
    failed = 0
    for t in table["tests"]:
        hits = evaluate(table, t["in"])
        got = hits[0]["action"] if len(hits) == 1 else f"{len(hits)} hits"
        if got != t["expect"]:
            failed += 1
            print(f"TEST FAIL {t['in']}")
            print(f"  expected {t['expect']} got {got}")
    print(f"tests: {len(table['tests']) - failed}/{len(table['tests'])} passed")
    ok = not overlaps and not gaps and not failed
    print("RESULT", "PASS" if ok else "FAIL")
    return 0 if ok else 1


if __name__ == "__main__":
    sys.exit(main(sys.argv[1]))

Run python3 check_table.py refund_table.json. Expected output (exit code 1):

refund_auto_approval v1.3.0-draft hit policy UNIQUE
probe points: 385
OVERLAP R1+R4 at {'order_value': 0, 'tenure_months': 0, 'refunds_90d': 2}
GAP (no rule, result null) at {'order_value': 500, 'tenure_months': 0, 'refunds_90d': 0}
GAP (no rule, result null) at {'order_value': 500, 'tenure_months': 0, 'refunds_90d': 0.5}
GAP (no rule, result null) at {'order_value': 500, 'tenure_months': 0, 'refunds_90d': 1.5}
TEST FAIL {'order_value': 900, 'tenure_months': 60, 'refunds_90d': 0}
  expected REFER got 0 hits
tests: 3/4 passed
RESULT FAIL

Validation. Change R1’s refunds_90d to [0, 2] and R5’s order_value to [500, null]: RESULT PASS, exit code 0 (verified). Troubleshooting. KeyError: a rule lacks a declared input; for non-integer inputs add finer probes than ± 0.5. Lesson. Three of four example tests passed, yet the table was wrong twice: systematic checks find what examples miss.

Lab 2 (intermediate): replay a challenger and see what history cannot tell you

Link to section “Lab 2 (intermediate): replay a challenger and see what history cannot tell you”

Objective. Compare a champion and a challenger credit-style strategy on stored inputs and read the decision-change matrix. Prerequisites. Lab 1 folder. Cost and risk. None; data are synthetic, generated with a fixed seed. Save as replay.py. Example status: executed.

"""Replay stored inputs through the champion and a challenger; compare decisions.

Usage: python3 replay.py
Synthetic data (fixed seed). Outcomes exist only where the champion approved
(selective labels).
"""
import collections
import random

ACTIONS = ("APPROVE", "REFER", "DECLINE")


def champion(app):  # strategy v4.2.0
    if app["pd"] > 0.20 or (app["amount"] > 5000 and not app["verified"]):
        return "DECLINE"
    if app["pd"] > 0.12:
        return "REFER"
    return "APPROVE"


def challenger(app):  # strategy v4.3.0-rc1: wider approve band, higher amount limit
    if app["pd"] > 0.22 or (app["amount"] > 8000 and not app["verified"]):
        return "DECLINE"
    if app["pd"] > 0.14:
        return "REFER"
    return "APPROVE"


def make_input_set(n=2000, seed=7):
    rng = random.Random(seed)
    apps = []
    for i in range(n):
        pd = min(0.6, rng.betavariate(2, 14))
        app = {"id": f"A{i:05d}", "pd": round(pd, 3),
               "amount": rng.choice([500, 1500, 3000, 6000, 9000]),
               "verified": rng.random() < 0.7}
        # Outcome is observed only if the champion approved the application in production.
        if champion(app) == "APPROVE":
            app["defaulted"] = rng.random() < app["pd"]
        apps.append(app)
    return apps


def main():
    apps = make_input_set()
    matrix = collections.Counter((champion(a), challenger(a)) for a in apps)
    print("champion -> challenger    count")
    for c in ACTIONS:
        for d in ACTIONS:
            if matrix[(c, d)]:
                flag = "" if c == d else "  <- changed"
                print(f"{c:>8} -> {d:<10} {matrix[(c, d)]:>6}{flag}")
    changed = sum(v for (c, d), v in matrix.items() if c != d)
    print(f"decision-change rate: {changed / len(apps):.1%} of {len(apps)}")
    swap_in = [a for a in apps if champion(a) != "APPROVE" and challenger(a) == "APPROVE"]
    swap_out = [a for a in apps
                if champion(a) == "APPROVE" and challenger(a) != "APPROVE"]
    labelled = [a for a in swap_in if "defaulted" in a]
    print(f"swap-ins (newly approved): {len(swap_in)}, "
          f"with observed outcome: {len(labelled)}")
    print(f"swap-outs (no longer approved): {len(swap_out)}")
    kept = [a for a in apps if champion(a) == "APPROVE" and challenger(a) == "APPROVE"]
    rate = sum(a["defaulted"] for a in kept) / len(kept)
    print(f"default rate where both approve (observed): {rate:.1%} of {len(kept)}")
    print("swap-in default rate: UNKNOWN from history -> needs a controlled test")


if __name__ == "__main__":
    main()

Expected output of python3 replay.py:

champion -> challenger    count
 APPROVE -> APPROVE      1006
   REFER -> APPROVE       133  <- changed
   REFER -> REFER         341
 DECLINE -> APPROVE        72  <- changed
 DECLINE -> REFER          89  <- changed
 DECLINE -> DECLINE       359
decision-change rate: 14.7% of 2000
swap-ins (newly approved): 205, with observed outcome: 0
swap-outs (no longer approved): 0
default rate where both approve (observed): 5.3% of 1006
swap-in default rate: UNKNOWN from history -> needs a controlled test

Validation. Explain the 72 DECLINE → APPROVE cases (unverified requests for 6,000, now under the 8,000 limit). Lesson. The 205 swap-ins are the challenger’s whole point, and history holds no outcome for any of them: replay sizes the change, only a randomised test prices it. Troubleshooting. Other numbers mean a different random implementation; the structure is what matters.

Lab 3 (advanced): assignment, propensity and a sample ratio check

Link to section “Lab 3 (advanced): assignment, propensity and a sample ratio check”

Objective. Assign units deterministically and log, for every decision, the version and the probability that chose it: the raw material for fair comparisons and counterfactual estimates. A short split check at the end stops a broken experiment from being read (sizing and SRM practice in depth: ProductOps). Prerequisites. Python 3.8+. Cost and risk. None; writes decisions.jsonl (about 8 MB) in the current folder. Save as experiment.py. Example status: executed.

"""Champion/challenger assignment, a decision log with propensities, an SRM check.

Usage: python3 experiment.py [--drop-rate 0.08]
Writes decisions.jsonl in the current directory. Standard library only.
"""
import argparse
import hashlib
import json
import math
import random

SALT = "refund-exp-2026-10"     # new salt per experiment, never reused
CHALLENGER_BUCKETS = range(0, 10)  # buckets 0-9 = 10 % challenger
VERSIONS = {"champion": "1.3.0", "challenger": "1.4.0-rc1"}


def bucket(unit_id):
    digest = hashlib.sha256(f"{SALT}:{unit_id}".encode()).hexdigest()
    return int(digest[:8], 16) % 100


def assign(unit_id):
    b = bucket(unit_id)
    arm = "challenger" if b in CHALLENGER_BUCKETS else "champion"
    propensity = len(CHALLENGER_BUCKETS) / 100 if arm == "challenger" else 0.9
    return arm, b, propensity


def srm_p_value(observed, expected_share):
    """Chi-square goodness of fit, 1 degree of freedom."""
    total = sum(observed)
    expected = [total * s for s in expected_share]
    chi2 = sum((o - e) ** 2 / e for o, e in zip(observed, expected))
    return chi2, math.erfc(math.sqrt(chi2 / 2))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--drop-rate", type=float, default=0.0,
                        help="simulate a logging bug that loses challenger events")
    args = parser.parse_args()
    rng = random.Random(11)
    counts = {"champion": 0, "challenger": 0}
    with open("decisions.jsonl", "w") as log:
        for i in range(50000):
            unit = f"cust-{i:06d}"
            arm, b, p = assign(unit)
            if arm == "challenger" and rng.random() < args.drop_rate:
                continue  # the bug: event never written
            event = {"decision_id": f"d-{i:06d}", "decision": "refund_auto_approval",
                     "version": VERSIONS[arm], "arm": arm, "bucket": b,
                     "propensity": p, "unit": unit}
            log.write(json.dumps(event) + "\n")
            counts[arm] += 1
    chi2, p_value = srm_p_value([counts["champion"], counts["challenger"]], [0.9, 0.1])
    print(f"logged champion={counts['champion']} challenger={counts['challenger']}")
    print(f"expected share 90/10, chi2={chi2:.1f}, p={p_value:.2g}")
    if p_value < 0.001:
        print("SRM DETECTED: do not read outcome metrics; find the cause first")
    else:
        print("no SRM: outcome comparison may proceed")


if __name__ == "__main__":
    main()

Expected output. python3 experiment.py prints logged champion=45063 challenger=4937, chi2=0.9, p=0.35 and “no SRM”. python3 experiment.py --drop-rate 0.08 (a bug that loses 8% of challenger records) prints logged champion=45063 challenger=4524, chi2=42.3, p=7.7e-11 and “SRM DETECTED”. Validation. Run the first command twice: the same customers land in the same arms, because assignment depends only on the salt and the id. Troubleshooting. If the split drifts with no drop rate, check that the salt and bucket ranges match the experiment plan. Extension. Give 5% of champion-arm REFER cases an APPROVE at random, log propensity for that action, and you have the raw material for counterfactual estimates.[33]

Scenario Context and method Trade-offs Success measure Pitfall
Delivery dispatch (real: DoorDash, 2019)[22] An assignment algorithm decides which Dasher takes which delivery; changes are tested by switchback over region-time units Fewer independent units, so less power; analysis aggregated to units Delivery duration at unit level Per-delivery A/B tests contaminate control with treatment
Card fraud rules on a vendor score (product mechanics: Stripe Radar; scenario illustrative)[14] Block, review or allow rules combine the vendor’s risk level with business attributes; new rules are back-tested on six months, shadowed at 0%, then ramped (custom rules are plan-dependent) Review rules cost analyst time; allow rules override everything Fraud losses and false-positive rate per rule; review-queue size A broad review rule floods the queue; an allow rule lets fraud through
Credit-line strategy (illustrative; rules sourced) Champion/challenger on 10% of accounts by random digit;[18] reason codes per rule for adverse action[15] Outcomes take months; challenger losses are a cost of learning Loss rate, revenue, complaint rate per arm Reading early delinquency as final; SCHUFA-style reliance on a third-party score[35]
Public benefit debts (real: Robodebt, Australia) Income data were matched “through an automated system” and, without a response, the employer-reported amount for the period “would be divided up evenly” across its fortnights to raise debts[48] Speed and scale against legality and fairness Our inference: share of debts upheld against actual fortnightly income Logic without lawful basis; the Royal Commission called it “a crude and cruel mechanism, neither fair nor legal”[48]

The Royal Commission’s recommendations 17.1 and 17.2 read like DecisionOps controls: a clear path to review, plain-language explanations, “business rules and algorithms should be made available, to enable independent expert scrutiny”, and a body to monitor and audit automated decision-making.[48]

Measure each decision, per version and arm. Outcome metrics come from the business (AnalyticsOps owns their definitions); the rest are operational.

KPI Formula Why it matters Trap
Output mix decisions with output x ÷ all decisions, per version First sign of a broken release or input A stable mix can hide offsetting errors
Referral rate referred ÷ all decisions Drives review cost and customer wait Lowering it is not automatically good
Override rate reviewed cases whose final outcome ≠ recommendation ÷ reviewed cases Shows disagreement, or rubber-stamping when near zero Read per reviewer and reason, not only in total
Default-rule hits decisions resolved by the default rule ÷ all decisions Table gaps or new input values Should be zero; any non-zero value is a defect
Log completeness decisions logged with version and inputs ÷ actions taken in business systems Audit and experiments depend on it Count from the action side, not the log
Reproducibility sampled logged decisions that replay to the same output ÷ sample Proves you can explain past decisions Non-deterministic optimisers need seed and limits logged
Outcome per arm for example loss or dispute rate, with a confidence interval The point of the whole exercise Only after the outcome window; only if no SRM
Contest rate and uphold rate contested ÷ decisions; overturned ÷ contested Fairness and quality signal from the people affected Low contest rates may mean people do not know they can

Mix, referrals, default hits and log completeness are daily leading signals; outcomes lag by their window. Set targets from the owner’s risk appetite, not another company’s numbers.

  • Integrity of logic. Who can change rules is a security question: reviewed releases only, a protected registry, alerts on changes outside the pipeline. Canada’s directive asks departments to “secure data and model integrity to prevent tampering and unauthorized modifications”.[26] Treat allow rules as privileged: in Stripe Radar they “override all your other rules”.[14]
  • Decision logs hold personal data. Omit or mask what is not needed to explain or reproduce (OPA can erase or modify fields before upload),[27] restrict access and set retention with PrivacyOps.
  • Fairness and versions. Canada requires testing for “unintended biases” before production, scheduled outcome monitoring, and “Obtaining and safeguarding all released versions of software components”.[26]
  • Regulatory mapping sits with ModelOps, evidence with ComplianceOps.

The main costs are people and learning. Review labour is referrals × handling time (960 hours above). Learning cost is the extra loss while a weaker challenger runs; cap it with share, guardrails and a stop rule. Solver compute: HiGHS stops a mixed-integer solve at a relative gap of 0.0001 by default, with no time limit unless set;[44] set limits and log the gap reached. Energy matters only for large solves (GreenOps).

  • Monthly: the owner reads the scorecard; a sample of logged decisions is replayed with their logged versions (re-performance; below 100% is a defect).
  • Quarterly: reconcile the inventory; review override reasons (recurring reasons are requirements).
  • Independent review for high-impact decisions; Canada scales peer review by impact level.[26]
Symptom Likely cause Diagnose Fix and prevent
Mix shifts with no code deploy Rule or threshold edited in a tool UI Tool’s rule history; diff against the registry Revert; make the registry the only path to production
Outputs differ for identical inputs Mixed versions across replicas, as at Knight Capital[16] Group the log by version and host Version check before raising traffic
Default-rule hits appear Table gap or new input value Inputs of the default-hit records Close the gap; validate inputs at the edge
Challenger “wins” by a lot SRM, survivorship, or outcome window not closed SRM test; label coverage per arm Fix the split; wait for the window
Review queue explodes A broad review rule (Stripe’s example: all prepaid cards)[14] Queue inflow by reason code Narrow the rule; add capacity limits
Approvals drift over weeks Upstream model recalibrated, thresholds unchanged Score distribution by model version Treat model releases as decision changes; re-replay
Override rate near zero Rubber-stamping (automation bias)[31] Time per case; blind-review sample Redesign review; reduce volume
A past decision cannot be explained Log lacks version or inputs; optimiser not deterministic Re-performance sample Complete records; log seed, time limit and gap

Worked runbook: approvals fall sharply after a quiet release

Link to section “Worked runbook: approvals fall sharply after a quiet release”

Illustrative incident. At 09:30 on a Tuesday the refund approval rate drops from 71% to 52%; referrals triple; nobody announced a change.

Figure 4. Runbook for a sudden shift in decision mix
yesnoyesnobroken feedgenuineAlert: approvals52%, normal 71%One version or hostonly?Pin all replicas tolast-known-goodAny change in 48hours?Redeploy or rollback the releasedversionInputs shifted?Broken feed:policy-only fallbackGenuine shift: ownerdecidesRe-decide affectedcases; record theincident
Diagram source (Mermaid)
%%{init: {"flowchart": {"wrappingWidth": 140, "nodeSpacing": 25, "rankSpacing": 40}}}%%
flowchart TB
  A["Alert: approvals 52%, normal 71%"]
  B{"One version or host only?"}
  C["Pin all replicas to last-known-good"]
  D{"Any change in 48 hours?"}
  E["Redeploy or roll back the released version"]
  F{"Inputs shifted?"}
  G["Broken feed: policy-only fallback"]
  H["Genuine shift: owner decides"]
  I["Re-decide affected cases; record the incident"]
  A --> B
  B -->|"yes"| C
  B -->|"no"| D
  D -->|"yes"| E
  D -->|"no"| F
  F -->|"broken feed"| G
  F -->|"genuine"| H
  C --> I
  E --> I
  G --> I
  H --> I
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  class A risk
  class B,D,F decision
  class C,E,G,H,I core

Text equivalent: An alert reports approvals at 52% against a normal 71%. If the drop is confined to one version or host, pin all replicas to the last-known-good version. Otherwise, if a rule, threshold or model changed in the last 48 hours, redeploy or roll back the released version. Otherwise check the inputs: a broken feed leads to the pre-approved policy-only fallback; a genuine shift goes to the owner. Every branch ends by re-deciding affected cases and recording the incident.

  1. Confirm from the decision log: approval rate by version, host and hour.
  2. Isolate: all hosts report 1.4.0, released last week, but the rule tool’s history shows a threshold edited at 09:12 by a user with direct access, so production no longer matches 1.4.0.
  3. Contain: redeploy 1.4.0 from the registry, overwriting the edit; approvals return to 70%.
  4. Recover: about 1,900 requests were referred instead of approved; nobody was refused (refusals are human here). Clear the queue oldest first.
  5. Prevent: remove direct edit rights; alert on changes made outside the pipeline; record the incident with decision ids.
  • “The model is the decision.” A better AUC changes nothing until thresholds change, and may break them.
  • “Replay proved the challenger.” Replay cannot observe outcomes for newly approved cases.[23]
  • “A person clicks approve, so it is not automated.” Fabricated involvement does not escape GDPR Article 22.[25]
  • Logging only the output, optimising a proxy (approval rate, review cost) and disabling instead of deleting retired logic.

Use DecisionOps when a decision is repeated at volume, its logic changes more than a few times a year, a wrong decision costs money or harms people, outcomes can be observed, or regulators and customers ask “why?”.

Do not, or not yet:

  • One-off or strategic decisions: BizOps decision records.
  • Low volume: a written policy and human judgement are cheaper.
  • No observable outcome: you can test correctness but not learn; use decision support.
  • No lawful basis or no way to contest, or no specific reasons: automate the preparation, not the decision.
  • Unstable policy: agree the policy first.

Hidden responsibilities: a review team, an outcome pipeline, log retention, change governance and on-call.

Figure 5. Should this decision be automated, and how should changes to it be tested?
noyesyesnoyesnoyesnoRepeated, with stable policyand measurable outcomes?Keep human judgement; usedecision supportSignificant effects on people?Design real human reviewand contest; check the lawDo units interact throughshared capacity?Switchback test over time andregionMay you randomise who getswhich version?Champion/challenger perunit, propensity loggedReplay, shadow, stagedrollout; state the blind spot
Diagram source (Mermaid)
flowchart TB
  Q1{"Repeated, with stable policy and measurable outcomes?"}
  N1["Keep human judgement; use decision support"]
  Q2{"Significant effects on people?"}
  H["Design real human review and contest; check the law"]
  Q3{"Do units interact through shared capacity?"}
  SB["Switchback test over time and region"]
  Q4{"May you randomise who gets which version?"}
  AB["Champion/challenger per unit, propensity logged"]
  SH["Replay, shadow, staged rollout; state the blind spot"]
  Q1 -->|"no"| N1
  Q1 -->|"yes"| Q2
  Q2 -->|"yes"| H --> Q3
  Q2 -->|"no"| Q3
  Q3 -->|"yes"| SB
  Q3 -->|"no"| Q4
  Q4 -->|"yes"| AB
  Q4 -->|"no"| SH
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class Q1,Q2,Q3,Q4 decision
  class SB,AB,SH,H core
  class N1 risk

Text equivalent: If the decision is not repeated, with stable policy and measurable outcomes, keep human judgement with decision support. If it has significant effects on people, first design real human review and a way to contest, and check the law. If units interact through shared capacity, test changes with switchbacks over time and region. Otherwise, if you may randomise who gets which version, run champion/challenger per unit with the propensity logged; if not, use replay, shadow and staged rollout and state the blind spot.

Weighted check for the level of automation (score each 1–5; weights are this Atlas’s suggestion):

Criterion Weight Full automation favoured when…
Volume and speed needed 3 Thousands a day, answer needed in seconds
Reversibility of a wrong decision 3 Easy and cheap to reverse
Effect on people 3 Low, or the outcome is always favourable (approve-only)
Quality of inputs 2 Validated, complete, current
Observability of outcomes 2 Short window, unbiased labels
Explainability of logic 2 Rules or a scorecard with reason codes

Scores above about 60 of 75 suggest full automation with sampling; 40–60, automation with a referral band; below 40, decision support only. Treat the cut-offs as a starting point for discussion, not a rule.

This is this Atlas’s model, not an industry standard.

Level Observable behaviour Exit criteria
0 Hidden Decisions live in code and spreadsheets; nobody lists them Inventory exists with owners
1 Inventoried Top decisions have cards; logic located Logic in version control with tests for the top three
2 Versioned and tested Releases through a pipeline; table checks; replay Every decision logs version, inputs and path; rollback rehearsed
3 Experimenting Champion/challenger or switchback with SRM gates; real review design Outcomes joined per arm; monthly scorecards
4 Outcome-managed Strategies improve on evidence; re-performance at 100%; contest data used Sustained for a year; independent review of high-impact decisions
Window Actions Milestone
Days 1–30 Build the inventory; pick three decisions; write their cards; locate their logic; add a decision id and version to every record Inventory and three cards approved by owners
Days 31–60 Move logic into version control; table checks and replay in CI; define fallbacks; design review bands; start the outcome join First class-P change released through the pipeline with a replay report
Days 61–90 First randomised test with an SRM gate; scorecards live; change classes agreed with ModelOps and compliance One champion/challenger result read and acted on; first monthly review held

Before releasing a decision change

  • Change class set; approver named
  • Table checks pass: no overlaps under Unique, no gaps or an explicit REFER default
  • Every rule has a reason code; test cases cover each rule and each boundary
  • Replay report reviewed: decision-change matrix, swap-ins and swap-outs explained
  • Shadow run clean at production volume; latency within service level
  • Experiment plan: unit, share, guardrails, stop rule, SRM gate, outcome window
  • Rollback version named and deployable; fallback strategy tested

Operating readiness

  • Decision card current; owner and on-call named
  • Every decision logged with version, inputs, path, output, propensity
  • Mix, default-hit, latency and log-completeness alerts live
  • Review queue staffed for the expected referral volume; override reasons captured

Quarterly governance audit

  • Inventory reconciled with code and tools
  • Re-performance sample at 100%
  • Override and contest reasons reviewed; changes raised
  • Retired rules deleted; no direct edit rights outside the pipeline
  • Legal and impact assessments still match the decision’s scope

Decision change request (copy into your tracker):

Decision:             refund_auto_approval
Change class:         P | L | M | E
Requested by / owner: <role> / <role>
What changes:         <rules, thresholds, inputs, models referenced>
Why:                  <problem, evidence, expected effect on outcome metric>
Replay result:        <decision-change rate; swap-ins; swap-outs; report link>
Effect on people:     <who gets a different outcome; can they contest?>
Test plan:            <shadow days; share; guardrails; stop rule; outcome window>
Rollback:             <version>; fallback strategy <name>
Approvals:            owner <date>; compliance <date or n/a>; ModelOps <n/a>

Reviewer guidance card (one page per referral reason):

Referral reason:  RECENT_REFUNDS
What the system saw: refunds_90d >= 2, order value, tenure, reason codes
What you can check that it could not: order notes, carrier proof, contact history
You may: approve, request evidence, decline (give the specific reason)
Record:   final outcome + override reason from list + free text if "other"
Time:     target 6 minutes; escalate rather than guess

The decision card and the release manifest above complete the set.

Kinds of decision logic

Logic Strength Weakness Test with
Rules and decision tables Readable, reason codes for free, fast to change Brittle at scale; overlaps and gaps Table checks, replay
Model score plus threshold Uses many signals; ranks well Reasons need extra work; drift moves the cut-off’s meaning Replay, champion/challenger
Optimisation Best allocation under constraints Results vary with time limits and gaps; units interact Scenario tests, switchback
LLM step inside the logic Handles unstructured input Non-deterministic; needs guardrails LLMOps evaluations, then the same ladder

Is DecisionOps a job title or a certification? We found neither (October 2026); the label comes from vendors.[2][6]

Do we need DMN or a rules engine? No. DMN helps when business owners must read and change tables and you want a standard;[20] plain code with the same tests, versions and logs is DecisionOps too.

Our decisions only recommend; a person decides. Does this apply? Yes: the recommendation still shapes outcomes, and automation bias means people often follow it.[31] In the EU, a third party’s score can count as the decision when it plays a determining role.[35]

How big should a challenger share be? Large enough to detect the effect you care about within the window, small enough that a bad challenger’s losses are affordable; the Fair Isaac patent’s 10% is an example, not a rule.[18]

Can we skip randomised tests if replay looks good? Only if the change cannot approve anything the old logic declined. Otherwise replay is blind exactly where it matters (Lab 2).

How long should we keep decision logs? As long as decisions can be contested or audited, no longer than privacy law allows.

  • Counterfactual evaluation and bandits: with logged propensities, estimate logic you did not run;[33] common in advertising research, rarer elsewhere.
  • Simulation (FICO markets “business outcome simulations”)[6] screens changes; validate with live tests.
  • Standards drift: DMN 1.7 is in beta;[12] check the TCK before relying on new features.[28]
Stage Do this
Prerequisites Basic probability; spreadsheets or Python; one decision you know well
1 day Read the DMN introduction and hit policies;[20] run Lab 1
1 week Labs 2 and 3; write a decision card and a change request for a real decision
30 days Replay a real change on stored inputs; design a review band; draft a champion/challenger plan with an SRM gate
Specialise Experimentation (switchbacks, counterfactuals), optimisation (solvers), or regulatory decisioning (credit, public sector)
Portfolio idea Publish a replay report and experiment plan for an open dataset, with every assumption stated
Topic Remember
Term Vendor label; practice = decision management, DMN, champion/challenger
Unit The decision: owner, card, version, tests, log
Logic hygiene Declared hit policy; no gaps; reason codes; delete retired rules
Testing Table checks → replay → acceptance → shadow → randomised or switchback → rollout → review
Evidence traps Selective labels, SRM, unclosed outcome windows
People Real review: time, information, authority; watch override rates
Metrics Mix, referrals, overrides, default hits, log completeness, reproducibility, outcomes per arm
Next action Inventory your top three decisions and add version ids to their logs this month

A judgement call: review every denial, or review the right ones?

Link to section “A judgement call: review every denial, or review the right ones?”

Situation (illustrative). A lender automates small personal-loan decisions: 3,000 automated denials a day. Compliance proposes that a person reviews every denial (A). The operations lead proposes reviewing a borderline band plus a 5% random sample, with a fast reconsideration route for anyone who asks (B). Assumptions: 12 reviewers, 7 productive hours a day each; EU consumer credit; denials have significant effects; the lender must decide which Article 22 exception applies, and from 20 November 2026 the Consumer Credit Directive lets every applicant assessed with automated processing request human intervention and a review, and rejections must say so.[36] Transposition and scope are counsel’s job (not legal advice).

Reasoning. (1) Capacity: A gives each denial 12 × 420 minutes ÷ 3,000 ≈ 1.7 minutes. Under that pressure, with the recommendation visible, automation bias predicts agreement;[31] WP29 requires involvement that is “meaningful, rather than just a token gesture”.[25] A buys the appearance of human decisions and may mislead the legal analysis. (2) B’s risk: clear denials are automated, so the lender needs a lawful exception and safeguards, including human intervention and contest.[34] (3) Quality: assume the borderline band holds about 150 denials a day and about 30 applicants a day ask for reconsideration; with the 150 sampled cases that is 330 cases, so B’s 5,040 reviewer-minutes give each about 15 minutes, where judgement changes outcomes, and the random sample measures how often automated denials would be overturned. Under the directive, both options need the request-and-review route; A simply has no capacity left to run it. (4) What would change the answer: if counsel finds no exception, every denial needs a genuinely human decision: more reviewers or fewer automated denials, not faster clicking.

Decision: B, with the override and reconsideration rates published monthly to the owner and compliance. Uncertainty: the borderline band’s width is a guess until the first month’s sample shows where reviewers disagree, and reconsideration requests may rise once rejection notices mention the right to human assessment; size the team from the first months’ data.

After this page you can explain the term’s status and boundaries; write a checkable decision table; choose a testing rung; design human review; read a replay and an experiment; and run a decision incident.

1. A colleague says “we already do MLOps, so our decisions are covered”. What is missing?

MLOps makes the score reliable. Nothing yet owns the thresholds, rules, referral bands, versions, decision log or outcome comparison that turn the score into actions; those are DecisionOps.

2. A Unique-policy table has a gap for orders of exactly 500. What does a DMN engine return, and what should you do?

Null, unless a default output is set.[20] Close the gap, or add an explicit REFER default, and alert on default hits.

3. Replay shows the challenger approves 205 more applicants and the default rate “where both approve” is 5.3%. Can you promote it?

No. The 205 swap-ins have no observed outcomes (selective labels),[23] so their default rate is unknown. Run a randomised share with guardrails and wait for the outcome window.

4. Your dispatch team wants an A/B test of a new assignment algorithm, randomised by order. Objection?

Orders compete for the same drivers, so treatment affects control. Randomise region-time windows (switchback) and analyse at that unit.[22]

5. Planned 10% challenger; logged 11,640 of 120,000. Read the outcomes?

Not yet: χ² ≈ 12, p ≈ 0.0005, a sample ratio mismatch.[30] Find the cause (here, a retry path that skipped logging) first.

6. Reviewers override 0.4% of recommendations. Good news?

Not necessarily. It can mean the recommendations are excellent, or that reviewers rubber-stamp. Check time per case and run a blind sample where reviewers decide before seeing the recommendation.[31]

DecisionOps is a young vendor word for an old, under-practised discipline. Its value is not a platform; it is a shift of attention from the model to the act: what the system decided, under which version, for which reason, with what result. Teams that treat each automated decision as a product, with a contract, tests, a ladder of evidence and a memory, change policy quickly and can answer the customer, the auditor and themselves. Teams that do not will keep discovering their policies in incident reviews, or, as Robodebt showed, in a royal commission.[48] Facts are dated October 2026; re-check before relying on them.

Vendor and documentation pages carry no publication date unless stated. Ledger with claim-by-claim notes: research/decisionops-ledger.md.

Further reading

Changelog. 2026-10-23: first version (research, ledger, draft, diagrams, three executed labs).

Changelog. 2026-10-23 (r1 revision, after the independent fact check): fixed the scorecard SQL (override rate over reviewed cases; record gains recommendation and final_output; re-run on synthetic rows); added the EU Consumer Credit Directive 2023/2225 and the UK Arts 22A–22D commencement; made the worked example consistent; redrew the reference architecture (write, then act; referral exits; optional optimiser); dated term-status evidence (Nextmv and FICO posts, EURO Practitioners’ Forum); corrected the TCK range, Taylor–Raden attribution, Knight and Robodebt wording; Stripe plan limits; ProductOps link; derived the judgement call’s capacity numbers.

Changelog. 2026-10-23, post-score polish: FICO definition traced to Nextmv (2024); Gartner date narrowed; figure 2 re-routed; experimentation platforms and a Robodebt measure; trims.


  1. Nextmv home page — nextmv.io / FICO, as of October 2026. Checked 2026-10-23. ↩︎

  2. Nextmv 1.0: Accelerate decision model development with a DecisionOps platform — Carolyn Mooney, Nextmv, 2023-11-16. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  3. Nextmv is now part of FICO — Carolyn Mooney and Ryan O’Neil, Nextmv, 2026-05-19. Checked 2026-10-23. ↩︎

  4. Fair Isaac Corporation completes acquisition of nextmv.io Inc — Faegre Drinker, June 2026. Checked 2026-10-23. ↩︎

  5. What Is DecisionOps? And Why Is It a Critical Piece in Your AI Strategy? — FICO blog, 2026-09-03. Checked 2026-10-23. ↩︎

  6. FICO Platform: Intelligent Decisions — FICO, as of October 2026. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  7. What is DecisionOps and why does it matter? — Haley Eshagh, Nextmv, 2024-07-31. Checked 2026-10-23. ↩︎

  8. Business Rules and Decision Management — FlexRule, as of October 2026. Checked 2026-10-23. ↩︎

  9. Decision Ops: What It Is, How It Works… — r4 Technologies, 2026-01-12 (archived copy; the live page blocks automated access). Checked 2026-10-23. ↩︎

  10. 13 June 2025 – Empowering reliable automated decision making in ECCO with DecisionOps — EURO Practitioners’ Forum, webinar by Matthias Als (ECCO), 2025-06-13. Checked 2026-10-23. ↩︎

  11. Smart Enough Systems: How to Deliver Competitive Advantage by Automating Hidden Decisions — James Taylor and Neil Raden, Prentice Hall/Pearson, 2007 (publisher page and its unsigned description). Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  12. Decision Model and Notation (DMN), versions — Object Management Group, as of October 2026. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  13. Decision Intelligence (Gartner IT Glossary) — Gartner, archived 2025-09-18. Checked 2026-10-23. ↩︎ ↩︎

  14. Fraud prevention rules — Stripe Docs, as of October 2026. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  15. 12 CFR 1002.9: Notifications (Regulation B) — eCFR, text as of 2026-10-01. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  16. In the Matter of Knight Capital Americas LLC, Release No. 34-70694 — US Securities and Exchange Commission, 2013-10-16. Checked 2026-10-23. ↩︎ ↩︎

  17. ModelOps (Gartner IT Glossary) — Gartner, archived 2025-05-17. Checked 2026-10-23. ↩︎

  18. US7383215B1: Data center for account management — Fair Isaac Corp., filed 2000-10-26, granted 2008-06-03. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  19. FICO Recognized in the 2026 Gartner Critical Capabilities Report for Decision Intelligence Platforms — FICO, 2026-01-30. Checked 2026-10-23. ↩︎

  20. Decision Model and Notation, version 1.6 (formal/25-12-02) — Object Management Group, September 2026; clauses 2.1, 5.2, 5.3.3, 8.2.11 and decision-table semantics. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  21. Experiments and testing overview — Nextmv Docs. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  22. Experiment Rigor for Switchback Experiment Analysis — Carla Sneider and Yixin Tang, DoorDash, 2019-02-20 (archived copy). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  23. The Selective Labels Problem: Evaluating Algorithmic Predictions in the Presence of Unobservables — Lakkaraju, Kleinberg, Leskovec, Ludwig and Mullainathan, KDD 2017. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  24. Contextual Bandits and Vowpal Wabbit — Vowpal Wabbit docs. Checked 2026-10-23. ↩︎ ↩︎

  25. Guidelines on Automated individual decision-making and Profiling (WP251rev.01) — Article 29 Data Protection Working Party, revised 2018-02-06. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  26. Directive on Automated Decision-Making — Treasury Board of Canada Secretariat, modified 2025-06-24. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  27. Decision Logs — Open Policy Agent docs. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  28. DMN Technology Compatibility Kit results — DMN TCK project, last updated 2026-08-01; reflects DMN 1.4. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  29. What is switchback testing for decision models? — Nicole Misek and Tiffany Bogich, Nextmv, 2023-10-26. Checked 2026-10-23. ↩︎

  30. Diagnosing Sample Ratio Mismatch in Online Controlled Experiments — Fabijan et al., KDD 2019 (Microsoft Research page). Checked 2026-10-23. ↩︎ ↩︎

  31. Complacency and bias in human use of automation: an attentional integration — Raja Parasuraman and Dietrich Manzey, Human Factors 52(3), 2010. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  32. Application instances — Nextmv Docs. Checked 2026-10-23. ↩︎

  33. Counterfactual Reasoning and Learning Systems: The Example of Computational Advertising — Bottou et al., Journal of Machine Learning Research 14, 2013. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  34. Art. 22 GDPR: Automated individual decision-making, including profiling — Regulation (EU) 2016/679, text as reproduced by gdpr-info.eu. Checked 2026-10-23. ↩︎ ↩︎

  35. Press release 186/23: Judgments in C-634/21 SCHUFA Holding (Scoring) and joined cases — Court of Justice of the EU, 2023-12-07. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  36. Directive (EU) 2023/2225 on credit agreements for consumers — Official Journal of the EU, 2023-10-30; Art. 18(8)–(9), Art. 48 (EUR-Lex text read via the Internet Archive, snapshot 2026-10-10). Checked 2026-10-23. ↩︎ ↩︎

  37. Consumer protection in financial services — European Commission, as of October 2026. Checked 2026-10-23. ↩︎

  38. EU AI Act, Annex III: High-risk AI systems — Regulation (EU) 2024/1689 as reproduced by artificialintelligenceact.eu (not the Official Journal). Checked 2026-10-23. ↩︎

  39. Consumer Financial Protection Circular 2022-03 (complex algorithms and adverse action notices) — CFPB, 2022-05-26. Checked 2026-10-23. ↩︎

  40. Interpretive Rules, Policy Statements, and Advisory Opinions; Withdrawal — CFPB, Federal Register, 2025-05-12. Checked 2026-10-23. ↩︎

  41. Data (Use and Access) Act 2025, section 80: Automated decision-making — legislation.gov.uk (read via the Internet Archive, snapshot 2026-10-02). Checked 2026-10-23. ↩︎

  42. The Data (Use and Access) Act 2025 (Commencement No. 6 and Transitional and Saving Provisions) Regulations 2026, SI 2026/82 — made 2026-01-29, legislation.gov.uk (read via the Internet Archive). Checked 2026-10-23. ↩︎

  43. ICO consultation on the draft guidance about automated decision-making, including profiling — Information Commissioner’s Office, March–May 2026. Checked 2026-10-23. ↩︎

  44. HiGHS option definitions — HiGHS docs (development version). Checked 2026-10-23. ↩︎ ↩︎

  45. OR-Tools — Google for Developers. Checked 2026-10-23. ↩︎

  46. GrowthBook documentation — GrowthBook, as of October 2026. Checked 2026-10-23. ↩︎

  47. Switchback tests — Statsig Docs, as of October 2026. Checked 2026-10-23. ↩︎

  48. Report of the Royal Commission into the Robodebt Scheme — Commonwealth of Australia, 2023-07-07 (corrected edition 2023-07-11; read via the Internet Archive). Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

Related Ops

ModelOps

ModelOps is the governance and lifecycle management of every model an organisation relies on (machine learning, rules, optimisation, LLM applications and agents): each one inventoried, risk-tiered, validated, approved for a use, monitored and retired.

MLOps

MLOps is the engineering practice of getting trained machine-learning models into production and keeping them correct there: versioned data, code and models, automated training and release pipelines, monitoring for skew and drift, and controlled retraining.

AnalyticsOps

AnalyticsOps has no standard definition. On this page it means operating the layer where people consume data: versioned metric definitions, a semantic layer that serves them, and BI content that is certified, monitored and retired, so each important metric has one trusted definition.

BizOps

BizOps (business operations) has no standard definition. On this page it is the company's operating system: the planning cadence, goal and KPI hierarchy and business reviews that turn strategy into resourced work and move resources when results diverge.

RiskOps

RiskOps, as this Atlas uses it, is the day-to-day operation of risk decisions: appetite and tolerances, a live risk register, quantification where it pays, and acceptance, treatment or transfer by the owner with the authority, with an expiry. The label has no standard meaning.

FinCrimeOps

FinCrimeOps (financial crime operations) is the team and workflow that turn anti-money-laundering, sanctions and fraud obligations into daily decisions: check customers, screen names, work alerts, investigate, report suspicion to the authorities on time, and prove every decision later.

LLMOps

LLMOps is the practice of running applications built on large language models in production: versioning prompts, models and retrieval together, gating every change on evaluations, tracing each request, and keeping prompt injection, latency and token use in check.

ReleaseOps

ReleaseOps is an informal label for turning deployed code into a deliberate, reversible change for users: versioning, cadence, progressive exposure, feature flags, rollback and release records. The exact name is also a ServiceNow product.

Practise and get certified

From xOps School

Practise DecisionOps and get certified

The DecisionOps track on xOps School (part of the Coffee Pass) has study notes, a 25-question practice quiz with explanations, and a verifiable certificate when you score 70% or more. Sign in with Google to start.

For teams

Instructor-led training

Live batches for your team, with completion certificates and reports for L&D/HR.

Source: master.md (the editorial source of this page) · built 2026-10-23 · diagrams rendered with @mermaid-js/mermaid-cli 11.17.0 (mermaid 11.17.2)