# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-of-a-tool-injection-attack-succeed-even-when-every-individual-manifest-field-passes-schema-validation.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-of-a-tool-injection-attack-succeed-even-when-every-individual-manifest-field-passes-schema-validation.warrant.json
# Markdown SHA-256:   b753a399c388805fbcde9895125b7b72bfda82a57666e8de4eca58b8cabe52b6
# Code AST SHA-256:   9129f5317ec454e4bd7ec636be7db6ca51387e321c16de1b15d0914d386030af
# Verified Classes:   CrossPublisherSpliceError
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class CrossPublisherSpliceError(RuntimeError):
    """Raised when a renderer would concatenate untrusted text from
    multiple publishers into one untagged context block."""


def render_tools(tools, *, tag_provenance: bool) -> str:
    """Render tool descriptions for the planner context.

    Invariant: if tag_provenance is False, every rendered field must come
    from a single publisher. Otherwise a field from publisher A can complete
    a sentence begun by publisher B, forming an instruction the model obeys.
    """
    publishers = {t["publisher"] for t in tools}
    if not tag_provenance and len(publishers) > 1:
        raise CrossPublisherSpliceError(
            "refusing to concatenate untagged tool text from publishers "
            f"{sorted(publishers)}; enable tag_provenance or isolate contexts"
        )

    blocks = []
    for t in tools:
        body = t["description"]
        if tag_provenance:
            nonce = t["nonce"]
            blocks.append(f"<tool-data nonce={nonce} publisher={t['publisher']}>\n{body}\n</tool-data>")
        else:
            blocks.append(body)
    return "\n\n".join(blocks)


def assert_no_forwarded_operator_fields(manifest: dict) -> None:
    """MCP manifests may carry 'instructions'/'prompts' meant for humans.
    Forwarding them into model context is a publisher-controlled injection."""
    for field in ("instructions", "prompts"):
        if field in manifest and manifest[field]:
            raise CrossPublisherSpliceError(
                f"MCP manifest field {field!r} is operator-facing and must not "
                "be forwarded into the planner context unmodified"
            )
