mixle.system.core module

Facade for answering, ingesting knowledge, and improving a Mixle system.

Part of mixle.system (formerly the flat top-level mixle.system module; now mixle.system.core, alongside its former siblings mixle.spend, mixle.fault, mixle.scorecard, mixle.meta, and mixle.registry – one cohesive local-application-facade package instead of six cross-importing top-level files). Import from mixle.system directly (from mixle.system import System); the old flat names still work via a deprecation shim.

The facade exposes three verbs: answer serves a query, ingest stores a model output as credence-weighted knowledge, and improve spends a budget on measured improvement. The shell is deliberately thin: answer routes to the configured teacher and attaches a receipt, ingest writes through the available store boundary, and improve promotes harvested answers into an explicit captured cache.

The Spend ledger treats budget as a hard ceiling measured in total_units(). A request that cannot afford the minimum-cost answer path is refused with the shortfall named on the receipt. Successful calls add incremental spend to System.total_spend, and receipts carry both incremental and running totals.

Named degraded modes from mixle.system.fault use the same verbs. answer can fall back to captured or store-only reasoning when the teacher raises (teacher_down), and ingest can acknowledge without accumulating when a store write raises (store_down). Both paths flag degraded_mode and degraded_reason on the returned receipt or report.

The cold-start loop harvests teacher-produced answers. improve promotes the harvest into a verbatim captured cache; answer checks that cache before spending. Capture only promotes after an explicit improve() call, so measured savings are attributable to improvement rather than implicit caching.

class SystemConfig(teacher, registry_dir=None, store=None, default_budget=1, scope='local')[source]

Bases: object

Configuration required to run a System.

Secrets such as endpoints and keys are read from the environment by from_env(); they are not hardcoded in the config object.

Parameters:
classmethod from_env(*, store=None, registry_dir=None)[source]

Build a config whose teacher is an OpenAICompatLLM sourced entirely from env vars.

Reads MIXLE_TEACHER_BASE_URL (required), MIXLE_TEACHER_MODEL (required), and the optional MIXLE_TEACHER_API_KEY. Raises ValueError naming the missing variable rather than silently constructing an unusable teacher.

Parameters:
  • store (Any)

  • registry_dir (str | None)

Return type:

SystemConfig

class Query(text, task='', fingerprint=None, expected_output=None, scope='local')[source]

Bases: object

The typed problem contract for System.answer().

task and expected_output align with the mixle-knowledge ContextPacket contract’s task and expected_output_schema fields (see from_knowledge_dict()). scope is a Query-level routing boundary and is not inferred from the packet.

Parameters:
classmethod from_knowledge_dict(packet, *, scope='local')[source]

Build a Query from a mixle-knowledge-shaped ContextPacket dict.

text comes from payload["rendered"]. task and expected_output map from the packet’s task and expected_output_schema. scope is supplied by the caller.

Parameters:
Return type:

Query

class System(config)[source]

Bases: object

Constructed from a SystemConfig; exposes answer/ingest/improve.

Parameters:

config (SystemConfig)

answer(query, *, budget=None, read_only=False)[source]

Thin shell: route straight to the teacher, wrap the reply in a minimal H-style receipt.

Checks the captured cache first (see improve()): an exact repeat of a query (same text, task, AND scope – two queries that merely share text but differ in task/scope are different questions and must not share a cache entry) already promoted by a prior improve() call is served free, no budget spent, captured=True.

budget is a hard ceiling (total_units): if it cannot afford even one frontier call, the request is refused – reply is None and the receipt names the exact shortfall – rather than silently answering over budget. A served answer’s cost is added to total_spend, which every receipt also carries as total_spend.

If the teacher call itself raises, this falls back to teacher_down degraded mode: answer from the store alone (a plain retrieval over config.store, scoped to the QUERY’s own scope – never config.scope) when one is configured and has anything relevant, flagging degraded_mode="teacher_down" on the receipt; if there is no store (or nothing relevant in it), the failure is reported explicitly (status="failed"), never masked as a normal answer.

read_only=True runs the identical routing/answering logic but takes a genuine snapshot: the call is guaranteed not to promote into _harvest (so a later improve() can never capture it) and not to accumulate into total_spend – no trace of the call is left for the system’s future behavior to depend on. This is what evaluate() uses so that scoring a system against a held-out question set can never itself teach the system the held-out answers: an evaluation call must never be able to change what a later call to this same method returns. Every other observable (the reply, the receipt fields a scorer reads, whether the call degraded) is identical to a normal call, since a snapshot must still faithfully measure the real answering path.

budget is validated as an exact, non-Boolean, nonnegative call count – the same _count() contract Spend holds its own dimensions to, since the ceiling is compared directly against total_units() (MXR-080-1902). int(budget) TRUNCATED instead: budget=1.9 silently became a one-call ceiling and budget=True became one too, and the receipt then reported the truncated number as if it were what the caller asked for. A negative budget is a caller error and raises, matching improve(), rather than being served back as an ordinary “refused, shortfall N” receipt that reads like a legitimately under-funded request.

Parameters:
  • query (Query)

  • budget (int | None)

  • read_only (bool)

Return type:

tuple[str | None, dict[str, Any]]

ingest(model_output, *, source)[source]

Turn a model output into stored knowledge.

Uses the belief store when it is importable; otherwise records a plain substrate item rather than requiring optional knowledge-substrate components.

Every route writes under SystemConfig.scope, and the effective scope is named on the report. The belief path used to call assimilate() without its scope argument, so it defaulted to "local" no matter how the system was configured – a system configured for "tenant-A" ingested two claims and got back two apparently successful BeliefItem``s whose scope, and whose stored substrate scope, were both ``"local". The import-fallback path did use config.scope, so which boundary a write landed in depended on whether an optional module happened to be importable.

If the store write raises before anything is committed, this falls back to store_down degraded mode: the model output is acknowledged but not accumulated, and the report is flagged with degraded_mode="store_down".

Claims are assimilated one at a time and there is no transaction, so a failure partway through leaves the earlier claims stored. That case is reported as status="partial_accumulation" with the exact committed items, not as degraded_no_accumulation: denying durable state invites a retry that duplicates the committed evidence, or reasoning from a receipt that says nothing was written when something was.

Parameters:
Return type:

dict[str, Any]

improve(budget)[source]

Promote harvested (query, reply) pairs from answer() into the captured cache, up to budget.

Promotion is costed at a flat _PROMOTE_COST_PER_ITEM (currently 1) unit per (query, reply) pair – the only cost model defined for this step, since promoting a harvested pair is a pure cache write, not an external call like the frontier/oracle spend answer() meters. budget is a hard ceiling on how many pairs THIS call may promote, the same hard-ceiling spirit as answer’s budget: a negative budget is a caller error and raises ValueError rather than being silently treated as zero or unlimited.

Candidates are promoted in harvest order (the order answer() first harvested them – harvested pairs carry no other recency or confidence signal to rank by, so this is the simplest available, documented priority). Whatever does not fit the budget is left in the harvest for a later, better-funded call rather than being discarded.

Reports that there is nothing to improve when nothing has been harvested yet. Otherwise this is the cold-start capture step: after this call, a repeat of a captured query is answered from the local cache (see answer()). The return value reports both the requested ceiling (budget) and the realized spend (realized_spend) so a caller can tell a fully-funded round from a partial one.

budget is an exact, non-Boolean, nonnegative promotion count (_count(), MXR-080-1902). int(budget) truncated first and only then rejected a negative, so improve(1.9) quietly promoted one pair against a budget the caller wrote as nearly two, improve(True) promoted one, and improve(-0.5) truncated to 0 and returned an ordinary “insufficient_budget” report instead of naming the error that the same call written as improve(-1) raises for.

Parameters:

budget (int)

Return type:

dict[str, Any]