Decision flows

DecisionFlow is the v0.3 advanced abstraction for structured decision systems. DecisionPipeline remains the backwards-compatible linear binary API.

A flow is a deterministic DAG evaluated over one immutable historical pandas.DataFrame:

sensor_features
      │
      ├── failure_risk_model ──┐
      │                        ├── triage_policy → safety_rules → final_action
      └── downtime_model ──────┘

DeciShift remains a decision-change analysis library, not a generic workflow engine. Nodes cannot fetch remote state through DeciShift, there is no scheduler/server/database, and execution stays local and row aligned.

Nodes

from decishift import DecisionFlow, DecisionNode

flow = DecisionFlow(
    nodes=[
        DecisionNode(
            name="risk_model",
            component=risk_model,
            depends_on=("features",),
            version="risk_model_v13",
            group="predictive_models",
        ),
    ],
    final_node="final_action",
)

A component normally exposes:

def run(records, inputs):
    ...

records is the original source DataFrame. inputs maps declared dependency names to their row-aligned outputs. Lightweight records-only callables are also accepted. User exceptions are wrapped with node context; an exception raised inside a component is never reinterpreted as a calling-convention mismatch.

Validation

Before execution DeciShift checks:

DAG handling uses Python standard-library data structures; NetworkX is not required.

Caching

Node cache keys contain the node execution identity plus dependency lineage. If one node changes, that node and descendants are recomputed while unaffected upstream/parallel branches can be reused. Reports expose node evaluations, reused outputs, cache hits and misses.

Runtime object identity may be used only as an ephemeral in-process discriminator for an unstable component. It is never serialized as reproducible evidence.

Topology compatibility

Baseline and candidate flows are attribution-compatible only when they have:

Node implementations/versions may differ.

When topology changes, DeciShift can still execute each complete flow independently and compare observed final actions. It does not construct invalid hybrid graphs. Evidence reports topology_compatible: false and attribution_status: unsupported topology change, together with added/removed nodes, changed dependencies and changed final-node information.

Canonical topology identity

Topology serialization sorts node names, dependencies and stable metadata before SHA-256 hashing. The digest therefore does not depend on Python dictionary insertion order.

YAML

mode: flow
data:
  path: history.csv
id_column: record_id
baseline:
  final_node: final_action
  nodes:
    features:
      factory: myproject.components:FeaturesV1
      version: features_v1
      depends_on: []
    risk_model:
      factory: myproject.models:RiskModelV1
      version: risk_model_v1
      depends_on: [features]
      group: predictive_models
    final_action:
      factory: myproject.policy:FinalActionV1
      version: final_action_v1
      depends_on: [risk_model]
candidate:
  # same topology for node attribution; implementations/versions may differ

Factories and objects are imported from the local Python environment. DeciShift does not perform remote artifact resolution.

Inspect a flow without executing components:

decishift graph examples/triage/flow.yaml
decishift graph examples/triage/flow.yaml --format mermaid