Version: 8.0
Module: factory.core/ObjDecisionSegmentation.py
Product: Arbiter
Schema: factory.core/ObjDecisionSegmentation.yaml
Tests: resource.test/pytests/factory.core/test_ObjDecisionSegmentation.py (77 tests)
Versioned segmentation engine for evaluating workflow context data
against column-based rules stored in a base data table. Part of
the Axion Decision family alongside ObjDecisionSwitch and
ObjDecisionMatrix.
ObjDecisionSegmentation(ObjData, ObjVersionMixin)
|
| Core engine - read + evaluate only
|
+-- ObjDecisionSegmentationEdit (extend.edit)
| Load, export, import, migrate
|
+-- ObjServiceSegmentation (factory.service)
| Legacy service - proxies compute_segment()
| to core.evaluate()
|
+-- ObjWorkflowDecisionSegment (factory.workflow)
DECISIONSEGMENT node type
1. read(segment_name)
+- Load from def_decision_segment + def_decision_segment_columns
+- _ensure_versioned() for schema migration
+- Cache in SEGMENT_CACHE
2. evaluate(context, input_guid)
+- Resolve context values via EXTRACT_CONTEXT_PREFIXES
| (_calc_, _form_, _api_, _sys_, _service_, sys_)
+- Strip surrounding quotes from context values
+- For each column operation:
| +- Resolve operator alias via ObjOperator.resolve_operator()
| +- Build SQL WHERE clause
| +- IN/NOT_IN: strip quotes from column data via REPLACE()
+- Execute SELECT against base table (ORDER BY rank LIMIT 1)
+- Persist results to meta table (REPLACE INTO)
+- Return first output value or default_outcome
Base table data may contain quoted CSV values like "Medium,def_Medium".
The IN operator wraps the column reference with REPLACE to strip
quotes before FIND_IN_SET:
FIND_IN_SET('Medium',
REPLACE(REPLACE(`showroom_risk_flag`,'"',''),"'",""))
Without this, FIND_IN_SET('Medium', '"Medium,def_Medium"') returns 0.
With stripping, it correctly returns 1.
Context values also have surrounding quotes stripped via _strip_quotes().
| Column | Type | Purpose |
|---|---|---|
SegmentName |
VARCHAR(255) | Primary identifier |
Package |
VARCHAR(255) | Package scope |
Module |
VARCHAR(255) | Always ObjDecisionSegmentation |
Version |
INT | Version number (default 1) |
BaseTable |
VARCHAR(255) | Data table to query (e.g. data_seg_limits) |
BaseRank |
VARCHAR(50) | ORDER BY column (default rank) |
BaseGuid |
VARCHAR(50) | PK column for meta joins |
BaseValues |
VARCHAR(500) | Output columns (comma-separated) |
InputGuid |
VARCHAR(50) | Input GUID column name |
MetaSegment |
VARCHAR(255) | Meta table name pattern ($basetable$_seg_meta) |
DefaultOutcome |
TEXT | Fallback when no row matches |
SimDataTable |
VARCHAR(255) | Simulation data table |
DataTable |
VARCHAR(255) | Alternative data table |
ConstantsTables |
VARCHAR(500) | Constants table references |
ThreeWords |
VARCHAR(255) | Human-readable version label |
Description |
TEXT | Free-form description |
Active |
CHAR(1) | Y/N |
Primary key: (SegmentName, Package, Version)
| Column | Type | Purpose |
|---|---|---|
SegmentName |
VARCHAR(255) | Parent segment |
Package |
VARCHAR(255) | Package scope |
Module |
VARCHAR(255) | Module reference |
Version |
INT | Version number |
Rank |
INT | Evaluation order |
ColumnName |
VARCHAR(255) | Column in base table to check |
ColumnMatch |
VARCHAR(255) | Context key to match (default: same as ColumnName) |
ColumnOperation |
VARCHAR(20) | Operator (IN, EQ, LE, etc.) |
Active |
CHAR(1) | Y/N |
Primary key: (SegmentName, Package, Version, Rank)
Standard versioning table created by ObjVersionMixin._ensure_versioned().
See ObjVersionMixin.md for schema.
Created per segment by _ensure_meta_table(). Structure:
| Column | Type |
|---|---|
{segment_name}_date |
DATETIME |
seg_guid |
VARCHAR(255) |
seg_id |
VARCHAR(255) |
seg_version |
VARCHAR(50) |
{input_guid} |
VARCHAR(255) PK |
{output_cols...} |
VARCHAR(255) each |
__init__(self, DB=0)Initialises with database connection. Loads queries from
ObjDecisionSegmentation.yaml. Sets default state:
segment_name="", version=1, operations=[], _loaded=False.
load_queries() -> dictLoads the full YAML file from ObjDecisionSegmentation.yaml.
Returns the parsed dict for use by ObjData.get_queries().
read(segment_name, version=0) -> boolLoads a segment definition from the database.
_ensure_versioned() for schema migrationSEGMENT_CACHE by {package}:{name}:{version}def_decision_segment for headerdef_decision_segment_columns for operations_loaded = TrueReturns True if found, False otherwise.
evaluate(context, input_guid="") -> strCore evaluation - builds and executes a SQL query against the base table.
CONVERT(col,CHAR) as colEXTRACT_CONTEXT_PREFIXESObjOperator.resolve_operator()_ALL_/_ELSE_ fallback_calc_{key} context entries for each output valueREPLACE INTO ... SELECTdefault_outcomelookup(context, guid="") -> dictRetrieves previously computed results from the meta table.
_strip_quotes(val) -> str (static)Strips surrounding single or double quotes from a string.
_ensure_meta_table(meta_table, output_cols)Creates the meta table if it doesn't exist. Adds the input_guid
column if missing.
_apply_cached(cached)Restores segment state from a cached dict. Sets _loaded = True.
All aliases resolve through ObjOperator.resolve_operator():
| Canonical | Aliases | SQL WHERE Clause |
|---|---|---|
IN |
><, @, IN |
FIND_IN_SET(val, REPLACE(col)) > 0 |
NOT_IN |
!><, NOT IN |
FIND_IN_SET(val, REPLACE(col)) = 0 |
EQUALS |
=, EQ, MATCH |
val = col |
NOT_EQUALS |
!=, <>, NEQ |
val != col |
CONTAINS |
~, LIKE |
val LIKE col |
NOT_CONTAINS |
!~ |
val NOT LIKE col |
LESS_THAN |
<, LT |
col < val |
LESS_OR_EQUAL |
<=, LE, LTE |
col <= val |
GREATER_THAN |
>, GT |
col > val |
GREATER_OR_EQUAL |
>=, GE, GTE |
col >= val |
IS_EMPTY |
?, IS NULL |
col IS NULL OR col = '' |
HAS_VALUE |
!?, IS NOT NULL |
col IS NOT NULL AND col != '' |
BETWEEN |
BETWEEN |
col BETWEEN low AND high |
OTHERWISE |
*, ELSE, DEFAULT |
1=1 (always matches) |
Every _ALL_ or _ELSE_ value in any column acts as a wildcard
(matches any context value).
SEGMENT_CACHE is a module-level dict keyed by
{package}:{segment_name}:{version}. Cleared on YAML import.
Stores: segment_name, version, base_table, base_rank, base_guid,
base_values, input_guid, meta_segment, default_outcome, operations.
Registered via @ObjNodeRegistry.register("DECISIONSEGMENT") in
factory.workflow/ObjWorkflowDecisionSegment.py. Side-effect import
in ObjWorkflow.py.
ObjWorkflowSegment calls ObjServiceSegmentation.compute_segment(),
which now proxies to ObjDecisionSegmentation.evaluate(). Both
node types can coexist.
DecisionSegmentConstants in ObjConstants.py:
| Constant | Value |
|---|---|
SERVICE_CODE |
DECISIONSEGMENT |
TABLE_SEGMENT |
def_decision_segment |
TABLE_COLUMNS |
def_decision_segment_columns |
TABLE_HISTORY |
def_decision_segment_history |
PATH_SEGMENTS |
local.documents/segments |
WILDCARD_ALL |
_ALL_ |
WILDCARD_ELSE |
_ELSE_ |
simulate(segment_name, source_table, guid_column, limit) — Batch-evaluate the segment against all rows in the source table. Writes results (outcome per row) to bloom_sim_{segment_name}.send_email(segment_name, recipients, version) — Send a branded HTML email with column operations table, version history, RACI matrix, and signoff status. Uses palette-styled headers and zebra striping. Falls back to RACI contacts if no recipients specified.The def_decision_segment table has RACI columns: RaciSimulation, RaciProduction, RaciOutcome, RaciDevelopment. Package supplementation fills empty slots from def_package_roles.
# Create tables
python factory.core/ObjDecisionSegmentation.py preflight
# List all segments
python factory.core/ObjDecisionSegmentation.py list
# Run segment simulation
python factory.core/ObjDecisionSegmentation.py run SEG_NAME \
--source-table data_input --limit 1000
# Send segment report email
python factory.core/ObjDecisionSegmentation.py send-email SEG_NAME \
--recipients "user@example.com"
For CRUD operations, use the Edit class:
python factory.core/extend.edit/ObjDecisionSegmentationEdit.py --help
The seg_limits segment evaluates credit scoring context to
assign a credit limit segment:
Base table: data_seg_limits
Operations: scorecard(IN), department(IN), showroom_risk_flag(IN),
targetedindicator(IN), msca(<=), cellmatch(IN),
scorecardno(IN)
Output: out_segment, out_cut_off
Context value Showroom_risk_flag = 'Medium' matches base table
row showroom_risk_flag = "Medium,def_Medium" via quote-stripped
FIND_IN_SET.
| File | Purpose |
|---|---|
ObjDecisionSegmentation.yaml |
Schema + 12 queries |
extend.edit/ObjDecisionSegmentationEdit.py |
CRUD, YAML export/import |
extend.edit/ObjDecisionSegmentationEdit.md |
Edit class documentation |
factory.workflow/ObjWorkflowDecisionSegment.py |
DECISIONSEGMENT workflow node |
factory.workflow/ObjWorkflowDecisionSegment.md |
Node documentation |
factory.service/package.core/ObjServiceSegmentation.py |
Legacy service (proxy) |
factory.service/package.core/ObjServiceSegmentation.md |
Legacy service documentation |
factory.core/ObjOperator.py |
Operator alias resolution |
factory.core/ObjVersionMixin.py |
Version history mixin |
factory.core/ObjConstants.py |
DecisionSegmentConstants |
resource.test/pytests/factory.core/test_ObjDecisionSegmentation.py |
77 tests |