mixle.substrate.act module

Action-based investigation over retrieve, compute, simulate, and create steps.

investigate() accepts a question and a set of Action objects. It scores actions by relevance per unit cost, executes them under an optional budget, accumulates evidence fragments, and returns an Investigation containing either an answer or an abstention.

Each action is a small adapter around run(question) -> list[str] plus cost and description metadata. Helper builders adapt substrate retrieval, registered skills, simulators, and creators into the same action protocol.

class Action(name, kind, run, cost=1.0, description='', base_score=0.0, earned_relevance=None)[source]

Bases: object

One evidence-acquiring move: run it on a question, get back evidence fragments, at a cost.

Parameters:
class Step(action, kind, fragments, cost, score, relevance=0.0, failed=False, error='')[source]

Bases: object

A fired action and what it yielded – the audit trail behind an investigated answer.

Parameters:
class Investigation(question, answer, abstained, confidence, steps=<factory>, note='', factuality=None, proposal=None, failed=False, error='')[source]

Bases: object

A cited answer (or abstention) plus the sequence of actions that acquired its evidence.

Parameters:
property evidence: list[str]

Flatten all evidence fragments collected by the investigation.

property spent: float

Total action cost spent by the investigation.

trace()[source]

The actions taken, in order – the provenance the answer must be checkable against.

Each entry’s failed/error distinguish “ran, found nothing” from “raised” – collapsing those into the same bare n_fragments: 0 is exactly how an action failure used to disappear from the trace (MXR-080-0256).

Return type:

list[dict[str, Any]]

as_dict()[source]

Return a JSON-serializable investigation summary.

Return type:

dict[str, Any]

relevance_of(action, question)[source]

How on-topic an action is for a question (lexical overlap + its base floor), ignoring cost.

This is a PROSPECTIVE estimate – “how promising does this mounted capability look” – used both as score_action’s routing prior and, elsewhere, to rank untried acquisition strategies (see mixle.scientist.Scientist.propose()). It is deliberately NOT what confidence is earned from once an action has actually run; see _relevance_for().

Parameters:
  • action (Action)

  • question (str)

Return type:

float

score_action(action, question)[source]

EIG-per-cost proxy: lexical relevance of the action to the question, divided by its cost.

This heuristic can be replaced with a learned or calibrated expected-information-gain estimate. Retrieval-style actions carry a base_score floor because retrieval is always at least weakly informative.

Zero-cost actions have nothing to divide by: a free, on-topic action has no cost tradeoff to weigh against anything else, so it scores +inf and sorts first; a free but wholly irrelevant action (zero numerator) scores 0.0, same as any other non-informative action, rather than becoming an unbounded favorite. Action.__post_init__ already guarantees cost is finite and non-negative, so these are the only two cases – no clamped division ever runs on a negative or non-finite value (MXR-080-0254).

Parameters:
  • action (Action)

  • question (str)

Return type:

float

investigate(question, actions, answerer, *, budget_cost=None, min_evidence=1, min_confidence=0.15, target_confidence=None, max_actions=None, scorer=None, telemetry=None)[source]

Answer question by firing evidence-acquiring actions under a cost budget, or abstain.

Actions are ordered by scorer (default score_action(), EIG-per-cost) and fired highest-first. The loop stops early once it holds at least min_evidence fragments and confidence clears target_confidence (default: min_confidence). It also stops at the cost budget or max_actions. scorer can be replaced with a learned acquisition policy such as mixle.inference.learn_action_policy(). The answerer is called only when the evidence clears the bar. The returned Investigation carries the ordered action trace as provenance, and each fired action can emit telemetry for later policy learning. Each action’s score is evaluated exactly once – up front, cached, and reused for both the ordering and the fire/skip decision – so a stateful or stochastic scorer can never produce a fired order inconsistent with the score recorded on its Step (MXR-080-0256).

Every action’s cost is validated (finite, non-negative) up front, before any ranking or accounting runs (MXR-080-0254). An action that raises during run() is recorded as an explicit failed Step (empty fragments, failed=True, the exception on error) instead of being silently coerced into an empty success; an answerer that raises is likewise recorded on the returned Investigation (abstained=True, failed=True, error set) instead of propagating with no investigation record at all (MXR-080-0256).

Parameters:
Return type:

Investigation

retrieve_action(substrate, *, name='retrieve', k=6, scope=None, cost=1.0, min_score=0.0)[source]

A retrieve action over a Substrate (the always-available floor action).

min_score filters out weak matches: a small embedder returns a result for every query, so a positive floor keeps genuinely-irrelevant items from becoming false evidence. It defaults to 0.0, but the comparison is a strict > regardless of the floor chosen: an exact-zero score means no overlap at all, which is never usable evidence, so it is always excluded – not admitted just because the caller left the default floor at its lowest setting (MXR-080-0255). A small positive min_score makes retrieval conservative still, on a noisy index where near-zero (but not exactly zero) scores are also unreliable.

Confidence is earned separately from ordering: base_score gives retrieval a routing prior for score_action() (“always at least weakly worth trying”), but the fired Step’s confidence-bearing relevance is the TRUE top calibrated score among the results that survived the floor (0.0 when nothing did) – never the fixed routing prior. A store with nothing relevant now reports low or zero confidence instead of borrowing retrieval’s routing floor as if it were support (MXR-080-0255).

Parameters:
Return type:

Action

compute_action(skill, *, name=None, cost=1.0, description=None)[source]

A COMPUTE action that runs a Skill and reports its result.

Parameters:
Return type:

Action

simulate_action(simulator, field_index, scenario, *, name=None, cost=2.0, description='')[source]

A SIMULATE action that runs a what-if scenario and reports the simulated outcome mean.

Parameters:
Return type:

Action

create_action(build, *, name='create', cost=4.0, description='', report=None)[source]

A CREATE action that builds a model / dataset on demand and reports what it made.

build(question) -> artifact fits/synthesizes something (e.g. via mixle.inference.create() or mixle.inference.synthesize()); report renders the artifact to an evidence fragment (default: a certificate/guarantee summary when present, else repr). Creation is the most expensive action, so it defaults to cost=4 – the reasoner reaches for it only when cheaper retrieve/compute/simulate actions cannot answer.

Parameters:
Return type:

Action

delegate_action(delegate, *, name='delegate', cost=8.0, description='', priced=True)[source]

A DELEGATE action that hands the question to an external worker (pool job / remote tool / agent).

delegate(question) -> answer is any priced external capability. This is the reasoner’s most expensive move (default cost=8) and the escalation of last resort: it fires only when nothing local clears the bar, honoring the 99%-local topology. priced=True records that the call incurs real spend (the pool/interop layers own the actual budget-reject + confirm rails).

Parameters:
Return type:

Action

action_features(action, question)[source]

The features a learned acquisition policy keys on: the action’s kind, cost, and query overlap.

Parameters:
  • action (Action)

  • question (str)

Return type:

dict[str, Any]