Skip to content

symfonic.capabilities.extensions.admission

admission

Which contributions survive composition, and in what order (T4.2.2).

Three rules, split from the composer so each one is readable on its own and so "why was my tool dropped?" is answered by a function with the reason in its body rather than by a branch inside a loop.

Reserved names win. A contributed tool whose name the host already owns is refused, not admitted-and-shadowed. That is AS-INT-3: an extension executes with the invoking request's authority, and taking over a first-party tool's name is the cheapest way to acquire more.

First declaration wins. Two extensions offering the same tool name, or the same fragment id, resolve by the composition's declared order — and the loser gets a diagnostic rather than silence. The pre-refactor MCP provider resolved the same collision by overwriting its routing map, with no record that a tool had been replaced and no way for an operator to find out.

Order is total. :func:fragment_key breaks every tie, so a compiled prompt is byte-stable across runs and across whatever iteration order produced the contributions.

admit_fragment

admit_fragment(fragment: PromptFragment, admitted: list[PromptFragment], ids: set[str], diagnostics: list[ExtensionDiagnostic]) -> bool

Admit fragment unless its id is already taken.

Source code in src/symfonic/capabilities/extensions/admission.py
def admit_fragment(
    fragment: PromptFragment,
    admitted: list[PromptFragment],
    ids: set[str],
    diagnostics: list[ExtensionDiagnostic],
) -> bool:
    """Admit ``fragment`` unless its id is already taken."""
    if fragment.fragment_id in ids:
        diagnostics.append(
            _refusal(
                extension=fragment.extension,
                kind=ContributionKind.PROMPT,
                subject=fragment.fragment_id,
                detail="refused: this fragment id is already taken; the first "
                "declaration wins.",
            )
        )
        return False
    ids.add(fragment.fragment_id)
    admitted.append(fragment)
    return True

admit_tool

admit_tool(tool: ToolContribution, admitted: list[ToolContribution], names: set[str], reserved: frozenset[str], diagnostics: list[ExtensionDiagnostic]) -> bool

Admit tool unless its name is reserved or already taken.

Returns True when the tool was admitted. The caller does not branch on the result today; it is returned so a future caller counting admissions does not have to re-derive it by diffing the list.

Source code in src/symfonic/capabilities/extensions/admission.py
def admit_tool(
    tool: ToolContribution,
    admitted: list[ToolContribution],
    names: set[str],
    reserved: frozenset[str],
    diagnostics: list[ExtensionDiagnostic],
) -> bool:
    """Admit ``tool`` unless its name is reserved or already taken.

    Returns ``True`` when the tool was admitted. The caller does not branch on
    the result today; it is returned so a future caller counting admissions does
    not have to re-derive it by diffing the list.
    """
    if tool.name in reserved:
        diagnostics.append(
            _refusal(
                extension=tool.extension,
                kind=ContributionKind.TOOL,
                subject=tool.name,
                detail="refused: the host already owns this tool name, and a "
                "contribution may not shadow it (AS-INT-3).",
            )
        )
        return False
    if tool.name in names:
        diagnostics.append(
            _refusal(
                extension=tool.extension,
                kind=ContributionKind.TOOL,
                subject=tool.name,
                detail="refused: an earlier extension already contributed this "
                "tool name; the first declaration wins.",
            )
        )
        return False
    names.add(tool.name)
    admitted.append(tool)
    return True

fragment_key

fragment_key(fragment: PromptFragment) -> tuple[int, int, str, str]

Total order over fragments: layer, declared order, extension, id.

Source code in src/symfonic/capabilities/extensions/admission.py
def fragment_key(fragment: PromptFragment) -> tuple[int, int, str, str]:
    """Total order over fragments: layer, declared order, extension, id."""
    return (
        layer_rank(fragment.layer),
        fragment.order,
        fragment.extension,
        fragment.fragment_id,
    )