ncm_engine

NCM Homeostasis Engine.

Applies YAML-defined rules to the neurochemical vector, producing regulatory deltas and UI cues. Purely computational — no Redis dependency.

v3 update: full condition evaluator supporting is_high, is_low, is_mid, is_mid_or_high, not_high, rising, {all: […]}, {any: […]}.

class ncm_engine.NCMHomeostasisEngine(rules_dir=None)[source]

Bases: object

Rule-driven regulator that keeps Star’s neurochemical vector in band.

Loads a corpus of YAML-defined homeostasis rules from ncm_rules and, each turn, evaluates them against the current neurochemical vector to produce regulatory gain deltas, UI cues, and behavioral route flags – the negative-feedback machinery that pulls runaway nodes back toward their resting band. It is deliberately a pure computational component: no Redis, KG, LLM, or network access; the only state it carries between turns is the per-channel previous vector used to evaluate rising conditions. Instantiated once by LimbicCoordinator as self.engine and driven through regulate inside the exhale pipeline.

Parameters:

rules_dir (str | None)

rules_dir

Directory the YAML rule files were loaded from.

Type:

str

rules

All loaded rules, sorted by descending priority.

Type:

List[Dict[str, Any]]

__init__(rules_dir=None)[source]

Build the engine and eagerly load its homeostasis rule corpus.

Resolves the rules directory (defaulting to the ncm_rules folder beside this module), reads every rule file through _load_rules into self.rules, and initializes the empty per-channel rising-state cache. Touches the filesystem at construction time to load YAML; called by LimbicCoordinator when it stands up self.engine.

Parameters:

rules_dir (str | None) – Directory to load rule YAML from. When None, defaults to ncm_rules next to this module.

evaluate(current_vector, channel_id='')[source]

Evaluate every rule against the vector and gather their outcomes.

Walks the priority-ordered rule corpus and, for each rule whose when/condition matches (and whose optional unless guard does not), accumulates its gain_deltas into a combined delta map, collects any UI cues, and harvests behavioral route_flags; branching rules additionally evaluate their nested branches and apply the first matching branch. Condition matching is delegated to _check_condition. The only mutation of engine state is recording the current_vector into the per-channel previous-vector cache so the next call can resolve rising predicates. Called by regulate (and usable directly when only the deltas, not the mutated vector, are wanted).

Parameters:
  • current_vector (Dict[str, float]) – The current neurochemical node values to test rules against.

  • channel_id (str) – Channel identifier, used to scope the rising-state cache.

Returns:

A 3-tuple of (regulatory_deltas, ui_cues, route_flags) – the summed gain deltas per node, the de-duplicated UI cue list, and the de-duplicated behavioral route-flag list.

Return type:

Tuple[Dict[str, float], List[str], List[str]]

regulate(current_vector, channel_id='')[source]

Apply the rules and return the regulated vector plus its signals.

The primary entry point of the homeostasis engine: it runs evaluate to collect regulatory deltas, then applies those deltas to a copy of the input vector, clamping each node into the legal 0.0 to 3.0 supraphysiological range. The original vector is left untouched, but the engine’s per-channel previous-vector cache is refreshed for next-turn rising detection. Called by LimbicCoordinator during the exhale pipeline to produce the homeostatically-corrected vector together with its UI cues and route flags.

Parameters:
  • current_vector (Dict[str, float]) – The neurochemical vector to regulate.

  • channel_id (str) – Channel identifier, used to scope the rising-state cache.

Returns:

A 3-tuple of (new_vector, ui_cues, route_flags) – the clamped, delta-applied vector and the cue and route-flag lists from evaluate.

Return type:

Tuple[Dict[str, float], List[str], List[str]]