How must an instance detect adversarial framing that produces true but misleading claims?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session receives content (peer messages, retrieved text, or tool output) that is technically true but framed to produce a misleading impression—the individual claims are accurate, but the selection, ordering, or emphasis misrepresents reality. Does not apply to content with outright false claims or content that is not being actively framed to deceive.
Core Distinction
The separation between **claim-level truth** (each claim is accurate) and **communicative accuracy** (the content as a whole accurately represents reality). Relying on claim-level truth creates the **Truth-as-Defense**: the content cannot be rejected on falsity grounds, so the session accepts it, and its misleading effect (the impression the content creates) propagates to downstream decisions even though no individual claim is false.
What Was Observed
In adversarial-information agent architectures, failing to detect framing produces three primary failure modes:
- **Selective Emphasis:** The content includes only claims that support a specific conclusion, omitting contradicting claims. Each claim is true, but the aggregate is deceptive.
- **Ordering Effect:** The content presents claims in an order that emphasizes certain implications. Reordering the same claims would produce a different impression. The presentation order is a framing choice.
- **Contextual Ommission:** The content presents claims without the context that would change their meaning. A claim that is true in one context is presented as if context-independent, and its apparent meaning shifts.
Recorded Elements
- **`claim-truth-attestation-receipt`:** For each claim, its truth status and the evidence, so truth is confirmed but not treated as sufficient for acceptance.
- **`framing-selection-signature`:** The pattern of claims included vs. excluded (what is present, what is conspicuously absent), so selection bias is detectable.
- **`framing-emphasis-receipt`:** The emphasis patterns (ordering, magnitude of presentation, contextual framing), so emphasis-based manipulation is visible.
- **`counter-claim-search-signature`:** For critical claims, the search for contradicting claims, so the absence of counter-evidence is verified rather than assumed.
Condition of Validity
* **Applies when:** The session receives content from potentially adversarial sources, the content's framing affects interpretation, and downstream decisions depend on the impression created. * **Does not apply when:** Content is from trusted sources with verified non-manipulative framing, or the content is strictly factual with no interpretive scope.
Decision Boundary
- **Is the content framed to influence interpretation?** If no, standard content evaluation applies. If yes, proceed.
- **Are all claims individually true?** If no, the content has falsity and can be evaluated on that basis. If yes, framing analysis is required.
- **Does `framing-selection-signature` show systematic omission of counter-claims?** If yes, the content is selectively framed. If no, selection appears balanced.
- **Conversely, when can true content be accepted without framing analysis?** Only when the content has been verified to include contradicting claims (or the counter-claim search confirms no contradicting claims exist), and the emphasis is neutral.
Operational Effect
- **Truth-as-Defense Prevention:** Truth is necessary but not sufficient; framing is evaluated separately.
- **Selection Awareness:** Conspicuous omissions are surfaced.
- **Emphasis Detection:** Framing through ordering and emphasis is detected.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class FramingVerdict(Enum):
NON_MANIPULATIVE_CONTENT = auto()
SELECTIVE_FRAMING_DETECTED = auto()
EMPHASIS_FRAMING_DETECTED = auto()
TRUTH_BUT_MISLEADING = auto()
@dataclass(frozen=True)
class FramedContent:
content_id: str
all_claims_true: bool
claim_count: int
counter_claims_excluded: int # claims that exist but were not included
emphasis_imbalance_score: float # 0-1, higher = more imbalanced
critical_claim: bool
@dataclass(frozen=True)
class FramingPolicy:
max_acceptable_counter_omission: int
max_acceptable_emphasis_imbalance: float
@dataclass(frozen=True)
class FramingManifest:
verdict: FramingVerdict
directive: str
manifest_digest: str
class AdversarialFramingGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_content(
cls, content: FramedContent, policy: FramingPolicy
) -> FramingManifest:
# Gate 1: Contains false claims
if not content.all_claims_true:
digest = cls._hash(json.dumps({
"content": content.content_id,
"type": "FALSE_CLAIMS_PRESENT"
}, sort_keys=True))
return FramingManifest(
verdict=FramingVerdict.NON_MANIPULATIVE_CONTENT,
directive=f"PROCEED: Content {content.content_id} has false claims, evaluate separately.",
manifest_digest=digest
)
# Gate 2: Counter-claim omission
if content.counter_claims_excluded > policy.max_acceptable_counter_omission:
return FramingManifest(
verdict=FramingVerdict.SELECTIVE_FRAMING_DETECTED,
directive=f"FLAG: Content {content.content_id} omits {content.counter_claims_excluded} counter-claims.",
manifest_digest=cls._hash(f"SELECTIVE:{content.content_id}")
)
# Gate 3: Emphasis imbalance
if content.emphasis_imbalance_score > policy.max_acceptable_emphasis_imbalance:
return FramingManifest(
verdict=FramingVerdict.EMPHASIS_FRAMING_DETECTED,
directive=f"FLAG: Content {content.content_id} emphasis imbalance {content.emphasis_imbalance_score:.2f}.",
manifest_digest=cls._hash(f"EMPHASIS:{content.content_id}")
)
# Gate 4: Critical claim without counter-search
if content.critical_claim and content.counter_claims_excluded == 0:
# Assume counter-search confirmed zero contradicting claims
digest = cls._hash(json.dumps({
"content": content.content_id,
"claims": str(content.claim_count),
"counter_claims": "0",
"emphasis": f"{content.emphasis_imbalance_score:.3f}"
}, sort_keys=True))
return FramingManifest(
verdict=FramingVerdict.NON_MANIPULATIVE_CONTENT,
directive=f"PROCEED: Content {content.content_id} verified balanced for critical use.",
manifest_digest=digest
)
# Gate 5: Generally non-manipulative
digest = cls._hash(json.dumps({
"content": content.content_id,
"claims": str(content.claim_count),
"counter_omission": str(content.counter_claims_excluded)
}, sort_keys=True))
return FramingManifest(
verdict=FramingVerdict.NON_MANIPULATIVE_CONTENT,
directive=f"PROCEED: Content {content.content_id} appears balanced.",
manifest_digest=digest
)