Decision Primitives
v1.0.0In-depth reference for SystemOne decision primitives: Noul (binary likelihoods), Choice (categorical criteria), and Score (bounded ranges and rubrics).
Decision Primitives
Decision Primitives are the fundamental building blocks of Obelaw SystemOne. Instead of unstructured prompting, primitives represent formal mathematical and probabilistic questions.
SystemOne ships with three core primitives:
Noul: Binary and Bernoulli likelihood estimation[0.0, 1.0].Choice: Categorical classification across defined options with probability distributions.Score: Bounded numerical ratings or ordered rubric scales.
All primitives implement Obelaw\SystemOne\Contracts\PrimitiveInterface and Illuminate\Contracts\Support\Arrayable.
flowchart TD
Root["SystemOne Decision Primitives<br/><code>PrimitiveInterface</code>"]
NoulNode["<b>Noul</b><br/>Binary & Bernoulli Likelihood<br/>Output: <code>float [0.0, 1.0]</code>"]
ChoiceNode["<b>Choice</b><br/>Categorical Classification<br/>Output: <code>string</code> (Key) + Softmax Dist"]
ScoreNode["<b>Score</b><br/>Bounded Ranges & Rubrics<br/>Output: <code>float</code> / <code>int</code>"]
Root --> NoulNode
Root --> ChoiceNode
Root --> ScoreNode
subgraph NoulUseCases["Use Cases"]
N1["Fraud detection<br/>Policy compliance<br/>Spam filtering"]
end
subgraph ChoiceUseCases["Use Cases"]
C1["Department routing<br/>Sentiment labeling<br/>Incident triage"]
end
subgraph ScoreUseCases["Use Cases"]
S1["Credit scoring<br/>ICP lead fit (1-10)<br/>Priority rubrics"]
end
NoulNode --> NoulUseCases
ChoiceNode --> ChoiceUseCases
ScoreNode --> ScoreUseCases
1. Noul (Binary Likelihood)
Noul answers binary yes/no questions by returning a calibrated Bernoulli probability between 0.0 (0% likelihood) and 1.0 (100% likelihood).
Syntax & Construction
use Obelaw\SystemOne\Primitives\Noul;
// Fluent factory
$primitive = Noul::make('Is this customer inquiry urgent?');
// Or fluently update instructions
$primitive->instructions('Does this transaction indicate fraud?');
Response Evaluation
When evaluated by a driver, Noul produces a float value representing confidence in the affirmative statement:
$response = SystemOne::state($orderData)
->ask('is_fraud', Noul::make('Is this payment transaction fraudulent?'))
->run();
// Raw probability value (float)
$probability = $response->value('is_fraud'); // e.g. 0.94
// Convenience threshold checks
if ($response->isPositive('is_fraud', threshold: 0.75)) {
// Triggers if probability > 0.75
$order->markAsSuspicious();
}
if ($response->isNegative('is_fraud', threshold: 0.20)) {
// Triggers if probability <= 0.20
$order->approveInstantly();
}
flowchart LR
State["Application State<br/>(Order Data)"] --> NoulEval["Noul Evaluation<br/><i>'Is payment fraudulent?'</i>"]
NoulEval --> Prob["Calibrated Likelihood<br/><code>value('is_fraud') = 0.94</code>"]
Prob --> T1{"isPositive(> 0.75)?"}
Prob --> T2{"isNegative(≤ 0.20)?"}
T1 -- "Yes (0.94 > 0.75)" --> Mark["markAsSuspicious()"]
T2 -- "No (0.94 > 0.20)" --> Skip["Continue Pipeline"]
Serialized Schema
Noul::toArray() serializes into:
{
"type": "noul",
"instructions": "Is this payment transaction fraudulent?"
}
Common Use Cases
- Fraud & Anomaly Detection: Is this login anomalous? Does this claim exhibit fraudulent indicators?
- Content Moderation: Does this user post violate safety policies?
- Customer Churn Risk: Is this customer expressing high intent to cancel?
- Spam Filtering: Is this form submission automated bot spam?
2. Choice (Categorical Classification)
Choice resolves decisions where the output must match one option from a defined set of criteria. It computes a softmax probability distribution across all choices.
Syntax & Construction
Choice supports both flat lists and associative key-value criteria:
Associative Criteria (Recommended)
Providing descriptions alongside keys gives the model explicit semantic boundaries for each category:
use Obelaw\SystemOne\Primitives\Choice;
$choice = Choice::make('Which department should handle this ticket?', [
'billing' => 'Invoices, refunds, chargebacks, and payment methods',
'support' => 'Technical bugs, platform outages, and troubleshooting',
'sales' => 'Plan upgrades, enterprise custom quotes, and demo requests',
'legal' => 'Terms of service, GDPR data requests, and compliance',
]);
List Criteria
If options are self-evident:
$choice = Choice::make('Select customer sentiment', [
'positive',
'neutral',
'negative',
]);
Fluent Criteria Builder
Add criteria dynamically at runtime:
$choice = Choice::make('Assign bug severity')
->criterion('sev1', 'Critical production outage affecting all users')
->criterion('sev2', 'Major feature broken with no workaround')
->criterion('sev3', 'Minor cosmetic issue or localized glitch');
Response Evaluation
The response provides the winning category, the model’s confidence, and the full probability breakdown:
$response = SystemOne::state($ticketText)
->ask('department', $choice)
->run();
// The winning category key
$selected = $response->value('department'); // "billing"
// Confidence of the selected pick (0.0 to 1.0)
$confidence = $response->confidence('department'); // 0.892
// Full probability distribution across all criteria
$probabilities = $response->probabilities('department');
/*
[
'billing' => 0.892,
'support' => 0.075,
'sales' => 0.023,
'legal' => 0.010,
]
*/
flowchart LR
State["Ticket Text State"] --> ChoiceEval["Choice Evaluation<br/><i>'Which department should handle this ticket?'</i>"]
ChoiceEval --> Dist["Softmax Distribution Across Criteria<br/>billing: 89.2%<br/>support: 7.5%<br/>sales: 2.3%<br/>legal: 1.0%"]
Dist --> Winner["Resolved Selection<br/><code>value(): 'billing'</code><br/><code>confidence(): 0.892</code>"]
Serialized Schema
Choice::toArray() serializes into:
{
"type": "choice",
"instructions": "Which department should handle this ticket?",
"criteria": {
"billing": "Invoices, refunds, chargebacks, and payment methods",
"support": "Technical bugs, platform outages, and troubleshooting",
"sales": "Plan upgrades, enterprise custom quotes, and demo requests"
}
}
3. Score (Bounded Ranges & Rubrics)
Score evaluates continuous numerical ratings or maps state against an ordered rubric scale.
Mode A: Bounded Numerical Range
Used when you need a rating within a specific numerical boundary (e.g., 1 to 10, or 0 to 100):
use Obelaw\SystemOne\Primitives\Score;
// Factory helper for range
$score = Score::range('Rate lead purchase intent from 1 to 10', 1, 10);
// Or via fluent setters
$score = Score::make('Calculate credit risk score')
->min(300)
->max(850);
Mode B: Ordered Rubric Scale
Used when evaluating qualitative quality levels that have an inherent order:
$rubric = Score::rubric('Rate ticket urgency', [
'Low',
'Medium',
'High',
'Critical',
]);
When evaluated as a rubric, the driver returns the continuous rating mapped against the rubric indices (e.g. 3.8 indicates very close to “Critical”).
Response Evaluation
$response = SystemOne::state($leadProfile)
->ask('fit_score', Score::range('ICP fit score 1-10', 1, 10))
->ask('urgency', Score::rubric('Buyer timeline', ['Browsing', 'Evaluating', 'Ready to Buy']))
->run();
$fit = $response->value('fit_score'); // 8.7 (float)
$urgency = $response->value('urgency'); // 2.9 (float)
$confidence = $response->confidence('fit_score'); // 0.91
flowchart TD
subgraph RangeMode["Mode A: Bounded Numerical Range"]
R1["Score::range('ICP fit score 1-10', 1, 10)"] --> R2["Continuous Numerical Output: 8.7 / 10<br/><code>confidence(): 0.91</code>"]
end
subgraph RubricMode["Mode B: Ordered Rubric Scale"]
B1["Score::rubric('Buyer timeline', ['Browsing', 'Evaluating', 'Ready to Buy'])"] --> B2["Interpolated Scale Position: 2.9 / 3.0<br/>(Tightly maps toward 'Ready to Buy')"]
end
Serialized Schema
Range Schema:
{
"type": "score",
"instructions": "ICP fit score 1-10",
"min": 1,
"max": 10
}
Rubric Schema:
{
"type": "score",
"instructions": "Buyer timeline",
"criteria": [
"Browsing",
"Evaluating",
"Ready to Buy"
]
}
Primitive Comparison Cheat Sheet
| Primitive | Return Type | Primary Methods | Best For |
|---|---|---|---|
Noul | float [0.0, 1.0] | make(), isPositive(), isNegative() | Binary classification, anomaly detection, policy compliance. |
Choice | string (Key) | make(), criterion(), probabilities() | Categorization, routing, intent dispatch, multi-class labels. |
Score | float / int | range(), rubric(), min(), max() | Quality ratings, credit scoring, lead qualification, urgency. |
Next Steps
- Learn how to chain primitives using the Fluent API & Builder.
- Connect SystemOne to Cloudflare Workers AI with the Cloudflare Clef Driver.