mixle.substrate.context module

Budgeted, provenanced context packets assembled from the substrate.

A ContextPacket is a task-specific view of selected substrate items: the task, items in relevance order, rendered text, budget, and provenance for the included evidence. A ContextBudget describes how much context a target can accept and in what shape.

Assembly combines substrate retrieval with greedy budgeted selection. The most relevant items are packed until the budget is reached, and an optional telemetry event records the budget, usage, and number of selected items.

substrate_item_to_knowledge_dict(item, *, schema_uri=None)[source]

Bridge one SubstrateItem to an IC-13 KnowledgeItem-shaped dict (M0b).

Core never imports mixle_knowledge: this returns a plain, JSON-native dict with exactly the frozen field names, so a caller (or test) can validate it with mixle_knowledge.contracts.KnowledgeItem.model_validate without core depending on that package.

item.payload is the canonical structured payload UNLESS it carries a "ref"/"path" pointer (the substrate’s own artifact convention – see ingest_artifacts), in which case that pointer becomes artifact_ref and any remaining payload keys (e.g. spatial metadata) stay in payload. schema_uri defaults from item.kind (and, for a record item whose payload already looks like a typed table, from its shape) but an explicit override always wins. The item hash is always computed fresh over the canonical envelope; it never hashes item.text alone.

Parameters:
  • item (SubstrateItem)

  • schema_uri (str | None)

Return type:

dict[str, Any]

class ContextBudget(max_chars=2000, max_items=20, shape='passages')[source]

Bases: object

What a target can take – the DeviceSpec of context. shape hints the rendering style.

Parameters:
  • max_chars (int)

  • max_items (int)

  • shape (str)

class ContextPacket(task, items=<factory>, scores=<factory>, budget=<factory>, n_candidates=0, texts=<factory>, compressed=False)[source]

Bases: object

A budgeted, provenanced view of the substrate assembled for one target + task.

texts holds the text actually used per item – the full item surface, or (when the packet was compressed) an extractive summary that keeps only the query-relevant sentences. preservation receipts how much of each item’s query-relevant content survived, so compression is measured, not trusted.

Parameters:
render(*, header=True)[source]

The assembled context string the target consumes (respecting the budget shape).

Parameters:

header (bool)

Return type:

str

property used_chars: int

The TRUE size of this packet’s default (header-included) rendering – always derived from the actual render() output, never an independently-settable estimate that can silently drift from what a receiver actually gets (MXR-080-0239, MXR-080-0240).

preservation()[source]

Per item, the fraction of the task’s query terms retained in the used text (1.0 = all kept).

The receipt for compression: a value near 1.0 means the summary kept what the query cares about; a low value flags an item whose relevant content was squeezed out.

Return type:

list[float]

property compression_ratio: float

Used chars / full chars over the selected items (1.0 = uncompressed).

provenance()[source]

Where every included piece came from – ids, kinds, sources, relevance scores.

Return type:

list[dict[str, Any]]

as_dict()[source]

Return a JSON-serializable context-packet summary.

Return type:

dict[str, Any]

to_knowledge_dict(*, id, project_id, target_kind, target_id=None, expected_output_schema=None, factuality=None)[source]

Return a plain dict shaped like mixle_knowledge.contracts.ContextPacket.

The exported fields cover id, project_id, task, target_kind, target_id, token and byte budgets, evidence item identifiers, constraints, citations, expected_output_schema, and payload. Constructing a validated pydantic object is the receiving package’s responsibility; core mixle intentionally keeps this as a dependency-free dictionary so platform contract packages can depend on core rather than the reverse.

When factuality is a FactualityReceipt, it is included in payload["factuality"] so receivers can inspect grounding metadata before trusting the packet.

Parameters:
  • id (str)

  • project_id (str)

  • target_kind (str)

  • target_id (str | None)

  • expected_output_schema (dict[str, Any] | None)

  • factuality (Any)

Return type:

dict[str, Any]

to_knowledge_bundle_dict(*, id, project_id, target_kind, target_id=None, expected_output_schema=None, gaps=None, required_capability_ids=None, handoff_policy=None, continuation=None)[source]

Return a plain dict shaped like mixle_knowledge.contracts.KnowledgeBundle (IC-13, M0b).

Unlike to_knowledge_dict() (kept, unchanged, as a deprecated compatibility view – M1c must never use it as canonical state), this bridge carries each selected item’s OWN canonical structured payload/artifact_ref/relations (substrate_item_to_knowledge_dict()) instead of flattening everything into one rendered text string: a graph stays a graph, a typed table stays a typed table, an image keeps its artifact ref. self.render() and the compression receipt are only a disposable legacy view, kept under renderings["legacy_text"]; they may be recomputed or dropped at will without touching any item’s canonical payload or hash.

As with substrate_item_to_knowledge_dict(), core never imports mixle_knowledge – the caller validates the result (e.g. with KnowledgeBundle.model_validate).

Parameters:
Return type:

dict[str, Any]

assemble_context(substrate, task, *, budget=None, kind=None, scope=None, compress=False, telemetry=None)[source]

Assemble the best-affordable ContextPacket for task from substrate.

Retrieves relevant items (Substrate.search()), then packs them in descending relevance until the character budget or item cap is reached. The packet’s default rendering – header, separators, provenance tags, and all – is GUARANTEED to fit budget.max_chars: every candidate is checked against its actual rendered length before being kept, not an estimate that can silently diverge from what ContextPacket.render() later returns (MXR-080-0239). When even the single most relevant item does not fit whole, its text is shrunk instead of dropped – extractively with compress=True, by hard truncation otherwise – so a small-but-feasible budget still yields something, exactly as before, except the result now genuinely fits rather than silently overflowing.

budget.max_chars must be enough to hold at least the empty rendering for task (the header alone); if it cannot, this raises immediately rather than doing retrieval work for a budget no selection could ever satisfy.

With compress=True, items too large to fit whole are extractively summarized to their query-relevant sentences instead of dropped; packet.preservation() reports what was kept. Emits a context event when telemetry is supplied.

Parameters:
  • substrate (Substrate)

  • task (str)

  • budget (ContextBudget | None)

  • kind (str | None)

  • scope (str | None)

  • compress (bool)

  • telemetry (Any)

Return type:

ContextPacket

compress_text(text, task, max_chars)[source]

Extractive, torch-free summary of text keeping the sentences most relevant to task, within max_chars (the standalone compressor used by assemble_context() with compress=True). max_chars must be a positive int – raises otherwise; the returned string’s length is always <= max_chars (MXR-080-0239).

Parameters:
Return type:

str

class ReceiverProfile(name, max_chars=2000, max_items=20, shape='passages', compress=False)[source]

Bases: object

A named receiver’s capacity – what assemble_for_receivers() budgets and shapes for it.

A frontier LM and a local student are not the same target: the LM affords a large, prose-shaped context; the student needs a small, feature-shaped one. ReceiverProfile names that difference so it is set once per receiver, not re-derived ad hoc at every call site.

Parameters:
to_budget()[source]

Convert this receiver profile to a context budget.

Return type:

ContextBudget

assemble_for_receivers(substrate, task, receivers, *, kind=None, scope=None, telemetry=None)[source]

Assemble ONE task-conditioned ContextPacket per named receiver – the concrete receiver-conditioned compression path.

Two receivers reading the same substrate for the same task get genuinely different renderings: budget, shape, and, via compress, which sentences survive. The result is not the same blob truncated to fit each consumer.

packets = assemble_for_receivers(substrate, task, [
    ReceiverProfile("frontier_llm", max_chars=2000, shape="passages"),
    ReceiverProfile("local_student", max_chars=200, shape="features", compress=True),
])
packets["frontier_llm"].render(), packets["local_student"].render()

receivers must have unique, non-empty names – the result is keyed by name, so a duplicate would otherwise silently discard an earlier receiver’s packet AFTER its retrieval, compression, and telemetry work has already run (MXR-080-0241). Validated upfront, before any of that work starts.

Parameters:
  • substrate (Substrate)

  • task (str)

  • receivers (Sequence[ReceiverProfile])

  • kind (str | None)

  • scope (str | None)

  • telemetry (Any)

Return type:

dict[str, ContextPacket]