mixle.task.knowledge_routing module

M3 – problem decomposition & tool/model routing over the IC-10 catalog (M3-core wiring).

route_task turns one compound question into ordered sub-tasks and explicit, typed prerequisite gaps – never hidden prose intermediates – matches each gap against the IC-10 catalog by declared domain/schema, and drives the existing orchestrate() loop to resolve what it can. Every tool result is normalized into an IC-13-shaped KnowledgeItem/KnowledgeDelta dict with model/tool attribution and a receipt; nothing free-form ever becomes a canonical delta. Core never imports mixle_knowledge – everything here is a plain, dependency-free dict envelope shaped to the frozen IC-13 contract (notes/exec/contracts.md), so M1c/M2a can validate and persist it.

This module reuses, rather than reinvents, three pieces of existing machinery:

  • DecompositionProposer – an outcome-trained proposer over ordered sub-task sequences; proposer.plan_model.sample(rng) gives the decomposition order.

  • orchestrate() – the step/re-plan/stop controller loop; this module supplies a trivial sequential plan model plus a World that resolves one gap per step.

  • ResearchProposal – the existing “here is how to find out” abstention output; research_proposal_to_gap() folds it into the same IC-13 gap shape rather than maintaining a second missing-knowledge lifecycle.

Pre-M5, the decomposition itself is heuristic/seeded (proposer is fit on a seed corpus, not learned online) – that is an explicit non-goal here, deferred to M5.

class KnowledgeOrchestrationResult(answer, trace, delta, remaining_gaps)[source]

Bases: object

An IC-13-shaped, dependency-free dict envelope: the answer, the IC-5 trace, an aggregate IC-13 KnowledgeDelta-shaped dict, and the gaps still open after this call. M1c/M2a validate and persist delta/remaining_gaps against the real mixle_knowledge contracts; core never imports that package itself.

Parameters:
research_proposal_to_gap(proposal, *, gap_id)[source]

Map an existing ResearchProposal (an abstention’s “here is how to find out”) into the frozen IC-13 gap shape, rather than maintaining a second missing-knowledge lifecycle alongside it. ResearchProposal carries no structured schema for the missing evidence, so required_schema is a best-effort description; acceptance_criteria is the proposal’s own ranked acquisition options (mirroring render()’s top-4 slice). nearest_knowledge/note have no home in the frozen KnowledgeGap fields and are intentionally dropped rather than smuggled in as ad hoc extra keys.

Parameters:
  • proposal (ResearchProposal)

  • gap_id (str)

Return type:

dict[str, Any]

route_task(question, catalog, *, proposer, budget, bundle=None)[source]

Decompose question into ordered sub-tasks and explicit prerequisite gaps, route each gap to the cheapest reliable/verifiable catalog entry (or an item already in bundle), drive orchestrate() to resolve what it can, and return an IC-13-shaped answer/trace/delta/remaining-gaps envelope. Core emits plain dicts and never imports mixle_knowledge; M1c/M2a validate and persist this envelope against the real contracts.

Parameters:
  • question (str)

  • catalog (list[CatalogEntry])

  • proposer (DecompositionProposer)

  • budget (int)

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

Return type:

KnowledgeOrchestrationResult