orchestrata_ultimate.knowledge_graph.context_pack.packer

Reference › orchestrata_ultimate › knowledge_graph › context_pack › packer

Budgeted packing and the editable pack format, the last step of the context pack pipeline (SPEC-106 FR-004). pack takes the ranked nodes from selector best first and includes them greedily under an explicit token budget that is never exceeded (REQ-106-030); tokens are counted with the shared TokenCounterProtocol implementations from the memory package (REQ-106-031). The result is a frozen ContextPack with the request frame, a snapshot_id, the budget and the amount spent, and a list of PackSection entries each carrying node id, label, selecting template, rank score, token cost and body (REQ-106-033).

A pack renders as a markdown file: YAML frontmatter (frame, snapshot id, budget and spent) followed by one section per node with full provenance. The snapshot id is a hash over the selected nodes' ids and rendered content only, with no wall clock, so the same frame against the same graph state gives a byte-identical body (REQ-106-034). render produces the text and parse recovers a ParsedPack of ParsedSection records from it. Packs are meant to be hand-trimmed by deleting whole sections and re-injected without regeneration, and validate_pack checks that a trimmed pack is still structurally complete (REQ-106-035). context_pack_cache caches rendered packs. The packer reads and writes no database.

At a glance

Source src/orchestrata_ultimate/knowledge_graph/context_pack/packer.py
Lines of code 317
Classes 4
Functions 9
Imports (internal) orchestrata_ultimate.core.base.traces, orchestrata_ultimate.core.protocols, orchestrata_ultimate.knowledge_graph.context_pack.frame, orchestrata_ultimate.knowledge_graph.context_pack.selector, orchestrata_ultimate.memory.token_counter
Imported by orchestrata_ultimate.knowledge_graph.context_pack, orchestrata_ultimate.knowledge_graph.context_pack.cache
Tests that import it tests/knowledge_graph/context_pack/test_cache.py, tests/knowledge_graph/context_pack/test_packer.py

Class diagram

Class diagram orchestrata_ultimate.knowledge_graph.context_pack.packer

Dependency diagram

Dependency diagram orchestrata_ultimate.knowledge_graph.context_pack.packer

API

Classes

PackSection (dataclass)

Decorators: dataclass(frozen=True) · Line 48

One rendered pack section with full provenance (REQ-106-033).

Attribute Type Default
node_id str
label str
template str
rank_score float
token_cost int
body str

ContextPack (dataclass)

Decorators: dataclass(frozen=True) · Line 60

FR-004's output — a budgeted, provenance-carrying, byte-stable pack.

Attribute Type Default
frame RequestFrame
snapshot_id str
budget int
spent int
sections tuple[PackSection, ...] ()
reason str | None None

ParsedSection (dataclass)

Decorators: traces(spec='106', reqs=['REQ-106-033', 'REQ-106-035']), dataclass(frozen=True) · Line 73

A section recovered from a rendered pack's text by :func:parse.

Attribute Type Default
node_id str
label str
template str
rank_score float
token_cost int
body str

ParsedPack (dataclass)

Decorators: traces(spec='106', reqs=['REQ-106-032', 'REQ-106-035']), dataclass(frozen=True) · Line 86

A rendered pack's text recovered back into frontmatter + sections.

Attribute Type Default
frontmatter dict[str, Any]
sections tuple[ParsedSection, ...] ()

Functions

Function Signature Summary
_properties_lines _properties_lines(properties: dict[str, Any]) -> list[str] Render a node's properties as sorted, deterministic bullet lines.
_render_section_content _render_section_content(node: RankedNode) -> str Render one node's substantive (heading + properties) markdown block.
_snapshot_id _snapshot_id(sections: list[PackSection]) -> str Deterministic hash over the selected nodes' ids + rendered content.
pack traces pack(subgraph: RankedSubgraph, frame: RequestFrame, *, counter: TokenCounterProtocol | None = None) -> ContextPack Greedily pack subgraph's ranked nodes under frame.budget (FR-004).
empty_pack traces empty_pack(frame: RequestFrame, reason: str) -> ContextPack Build an explicit empty pack carrying a degradation reason.
_frame_frontmatter _frame_frontmatter(frame: RequestFrame) -> dict[str, Any]
render traces render(pack: ContextPack) -> str Render a :class:ContextPack to its markdown-with-frontmatter file body.
parse traces parse(text: str) -> ParsedPack Recover a rendered pack's frontmatter + sections from its text.
validate_pack traces validate_pack(text: str) -> bool Re-validate a (possibly hand-trimmed) pack as still injectable.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/src/orchestrata_ultimate/knowledge_graph/context_pack/packer.py

"""Budgeted packing + the editable pack format (SPEC-106 FR-004).

``pack()`` greedily includes ranked nodes (best-first, as produced by
:func:`selector.select`) under an explicit token budget that is never
exceeded (REQ-106-030), counted via the shared
``memory.token_counter.TokenCounterProtocol`` implementations (REQ-106-031).

A pack is a markdown FILE: YAML frontmatter (request frame, graph snapshot
id, budget/spent) followed by one section per selected node, each carrying
full provenance — node id, selecting template, rank score, token cost
(REQ-106-032/033). The snapshot id is a hash over the *selected* nodes' ids
and rendered content only — no wall-clock anywhere — so the same frame
against the same graph state renders a byte-identical pack body
(REQ-106-034).

Packs are meant to be hand-trimmed (whole sections deleted) and re-injected
without regeneration; :func:`validate_pack` re-validates that a (possibly
trimmed) rendered pack is still structurally complete (REQ-106-035).
"""

from __future__ import annotations

import hashlib
import json
import re
from dataclasses import dataclass
from typing import Any

import yaml

from orchestrata_ultimate.core.base.traces import traces
from orchestrata_ultimate.core.protocols import TokenCounterProtocol
from orchestrata_ultimate.knowledge_graph.context_pack.frame import RequestFrame
from orchestrata_ultimate.knowledge_graph.context_pack.selector import (
    RankedNode,
    RankedSubgraph,
)
from orchestrata_ultimate.memory.token_counter import get_token_counter

_HEADING_RE = re.compile(r"^## (?P<label>\S+) (?P<node_id>.+)$")
_PROVENANCE_RE = re.compile(
    r"^<!-- provenance: node_id=(?P<node_id>\S+) template=(?P<template>\S+) "
    r"rank=(?P<rank>-?[\d.]+) tokens=(?P<tokens>\d+) -->$"
)


@dataclass(frozen=True)
class PackSection:
    """One rendered pack section with full provenance (REQ-106-033)."""

    node_id: str
    label: str
    template: str
    rank_score: float
    token_cost: int
    body: str  # rendered "## Label id\n<property bullets>" content


@dataclass(frozen=True)
class ContextPack:
    """FR-004's output — a budgeted, provenance-carrying, byte-stable pack."""

    frame: RequestFrame
    snapshot_id: str
    budget: int
    spent: int
    sections: tuple[PackSection, ...] = ()
    reason: str | None = None


@traces(spec="106", reqs=["REQ-106-033", "REQ-106-035"])
@dataclass(frozen=True)
class ParsedSection:
    """A section recovered from a rendered pack's text by :func:`parse`."""

    node_id: str
    label: str
    template: str
    rank_score: float
    token_cost: int
    body: str


@traces(spec="106", reqs=["REQ-106-032", "REQ-106-035"])
@dataclass(frozen=True)
class ParsedPack:
    """A rendered pack's text recovered back into frontmatter + sections."""

    frontmatter: dict[str, Any]
    sections: tuple[ParsedSection, ...] = ()


def _properties_lines(properties: dict[str, Any]) -> list[str]:
    """Render a node's properties as sorted, deterministic bullet lines."""
    lines = []
    for key in sorted(properties):
        value = properties[key]
        if value is None:
            continue
        lines.append(f"- **{key}**: `{value}`")
    return lines


def _render_section_content(node: RankedNode) -> str:
    """Render one node's substantive (heading + properties) markdown block."""
    heading = f"## {node.label} {node.node_id}"
    body = "\n".join(_properties_lines(node.properties)) or "(no properties)"
    return f"{heading}\n{body}"


def _snapshot_id(sections: list[PackSection]) -> str:
    """Deterministic hash over the selected nodes' ids + rendered content.

    No wall-clock, no random ids — the same set of sections in the same
    order always hashes to the same value (REQ-106-034).
    """
    payload = [
        {
            "id": s.node_id,
            "template": s.template,
            "rank": round(s.rank_score, 6),
            "body": s.body,
        }
        for s in sections
    ]
    blob = json.dumps(payload, sort_keys=True, ensure_ascii=True)
    return hashlib.sha256(blob.encode("utf-8")).hexdigest()[:16]


@traces(
    spec="106",
    reqs=["REQ-106-030", "REQ-106-031", "REQ-106-033", "REQ-106-034", "REQ-106-035"],
)
def pack(
    subgraph: RankedSubgraph,
    frame: RequestFrame,
    *,
    counter: TokenCounterProtocol | None = None,
) -> ContextPack:
    """Greedily pack ``subgraph``'s ranked nodes under ``frame.budget`` (FR-004).

    Nodes are tried in rank order (best first — ``subgraph.nodes`` is
    already sorted by :func:`selector.select`); a node is included iff its
    rendered content fits the REMAINING budget. Lower-ranked nodes that
    still fit after a higher-ranked one was skipped are still tried
    (classic greedy-by-value packing) — the budget is never exceeded
    (REQ-106-030).

    Args:
        subgraph: A :class:`RankedSubgraph` from :func:`selector.select`.
        frame: The :class:`RequestFrame` this subgraph was selected for —
            its ``budget`` governs packing.
        counter: Token counter to use; defaults to
            ``memory.token_counter.get_token_counter()`` (word-count
            fallback — REQ-106-031's TokenCounterProtocol contract, no
            provider needed for a generic pack).

    Returns:
        A :class:`ContextPack` whose ``spent`` never exceeds ``budget``.
    """
    tc = counter if counter is not None else get_token_counter()
    spent = 0
    sections: list[PackSection] = []
    for node in subgraph.nodes:
        content = _render_section_content(node)
        cost = tc.count(content)
        if spent + cost > frame.budget:
            continue
        spent += cost
        sections.append(
            PackSection(
                node_id=node.node_id,
                label=node.label,
                template=node.template,
                rank_score=node.rank_score,
                token_cost=cost,
                body=content,
            )
        )
    return ContextPack(
        frame=frame,
        snapshot_id=_snapshot_id(sections),
        budget=frame.budget,
        spent=spent,
        sections=tuple(sections),
    )


@traces(spec="106", reqs=["REQ-106-043"])
def empty_pack(frame: RequestFrame, reason: str) -> ContextPack:
    """Build an explicit empty pack carrying a degradation reason.

    Used when the KG is unavailable — never a silent partial: the rendered
    frontmatter always says why there are zero sections (REQ-106-043).
    """
    return ContextPack(
        frame=frame,
        snapshot_id="",
        budget=frame.budget,
        spent=0,
        sections=(),
        reason=reason,
    )


def _frame_frontmatter(frame: RequestFrame) -> dict[str, Any]:
    return {
        "task_type": frame.task_type.value,
        "budget": frame.budget,
        "requester": frame.requester,
        "entities": [
            {
                "token": e.token,
                "label": e.label,
                "node_id": e.node_id,
                "ambiguous": e.ambiguous,
                "candidates": [list(c) for c in e.candidates],
            }
            for e in frame.entities
        ],
    }


@traces(
    spec="106",
    reqs=["REQ-106-032", "REQ-106-033", "REQ-106-034", "REQ-106-035", "REQ-106-043"],
)
def render(pack: ContextPack) -> str:
    """Render a :class:`ContextPack` to its markdown-with-frontmatter file body.

    Byte-stable (REQ-106-034): every value comes from ``pack`` itself
    (already computed deterministically by :func:`select`/`pack`) — no
    wall-clock, no random ids, no locale-dependent formatting.
    """
    frontmatter: dict[str, Any] = {
        "frame": _frame_frontmatter(pack.frame),
        "snapshot_id": pack.snapshot_id,
        "budget": pack.budget,
        "spent": pack.spent,
        "sections": len(pack.sections),
    }
    if pack.reason is not None:
        frontmatter["reason"] = pack.reason
    yaml_text = yaml.safe_dump(frontmatter, sort_keys=True, default_flow_style=False)
    parts = [f"---\n{yaml_text.rstrip(chr(10))}\n---"]
    for section in pack.sections:
        provenance = (
            f"<!-- provenance: node_id={section.node_id} template={section.template} "
            f"rank={section.rank_score:.6f} tokens={section.token_cost} -->"
        )
        parts.append(f"{section.body}\n{provenance}")
    return "\n\n".join(parts) + "\n"


@traces(spec="106", reqs=["REQ-106-035", "REQ-106-033", "REQ-106-043"])
def parse(text: str) -> ParsedPack:
    """Recover a rendered pack's frontmatter + sections from its text.

    Tolerant of hand-trimming (whole sections deleted): every remaining
    section block is parsed independently.
    """
    blocks = text.strip("\n").split("\n\n")
    if not blocks:
        return ParsedPack(frontmatter={}, sections=())

    frontmatter: dict[str, Any] = {}
    fm_match = re.match(r"^---\n(?P<yaml>.*)\n---$", blocks[0], re.DOTALL)
    if fm_match:
        frontmatter = yaml.safe_load(fm_match.group("yaml")) or {}

    sections: list[ParsedSection] = []
    for block in blocks[1:]:
        block = block.strip("\n")
        if not block:
            continue
        block_lines = block.split("\n")
        heading_match = _HEADING_RE.match(block_lines[0])
        provenance_match = _PROVENANCE_RE.match(block_lines[-1])
        if not heading_match or not provenance_match:
            continue
        body_lines = block_lines[:-1]
        sections.append(
            ParsedSection(
                node_id=provenance_match.group("node_id"),
                label=heading_match.group("label"),
                template=provenance_match.group("template"),
                rank_score=float(provenance_match.group("rank")),
                token_cost=int(provenance_match.group("tokens")),
                body="\n".join(body_lines),
            )
        )
    return ParsedPack(frontmatter=frontmatter, sections=tuple(sections))


@traces(spec="106", reqs=["REQ-106-035", "REQ-106-043"])
def validate_pack(text: str) -> bool:
    """Re-validate a (possibly hand-trimmed) pack as still injectable.

    Deleting whole sections keeps this True — each remaining section is
    independently self-describing (full provenance + non-empty body) and
    the frontmatter is untouched. Structural corruption (a missing/mangled
    provenance line, an unparsable frontmatter, an empty body) fails
    validation (REQ-106-035).
    """
    if not text.strip():
        return False
    parsed = parse(text)
    required_keys = {"frame", "snapshot_id", "budget", "spent"}
    if not required_keys.issubset(parsed.frontmatter):
        return False
    blocks = text.strip("\n").split("\n\n")
    non_frontmatter_blocks = [b for b in blocks[1:] if b.strip()]
    if len(non_frontmatter_blocks) != len(parsed.sections):
        # Some non-empty block failed to parse into a section — corrupted,
        # not merely trimmed.
        return False
    return all(section.body.strip() for section in parsed.sections)