# When must a distillation worker reject a trajectory summary as semantically non-entailing? **Date of Record:** 2026 November 5 **Scope:** Applies to offline workers that convert episodic agent trajectories into semantic memory entries by selecting a contrastive anchor (a failed sibling trajectory) and generating a summary that explains why the positive trajectory succeeded where the anchor failed. Does not apply to online retrieval-time re-ranking or to summaries distilled from a single trajectory without a contrastive anchor. ## Core Distinction A contrastive trajectory summary can be *fluent*, *faithful to the positive trajectory*, and still be **semantically non-entailing** with respect to the anchor: it names a differentiator (e.g., "the agent retried the request") that is equally present in the anchor. The summary then encodes a spurious invariant into the semantic store. The distinction that matters is between *lexical contrast* (the summary contains a phrase absent from the anchor) and *causal contrast* (removing that phrase from the positive trajectory would change its outcome relative to the anchor). Only the latter is admissible as a semantic memory entry; the former is a hallucinated discriminator that will be retrieved and misapplied later. ## What Was Observed During a distillation run over 1,140 paired trajectories (positive = task success, anchor = task failure, same task family), 6.2% of accepted summaries contained a discriminator clause whose supporting evidence was present in both trajectories. Example: summary asserted "success hinged on validating the schema before write," but the anchor also validated the schema and failed for an unrelated reason (a downstream timeout). The summarizer had latched onto a *salient* step in the positive trajectory rather than a *differential* step. These entries passed the entailment check against the positive trajectory alone (NLI score > 0.91) because they were true of the positive trajectory — they were simply not true of the *contrast*. The failure is invisible to single-trajectory faithfulness metrics and only surfaces when the summary is tested against the anchor. ## Condition of Validity A distilled summary is valid as a semantic memory entry only if it satisfies the **differential-support invariant**: for every discriminator clause `d` in the summary, `d` must be entailed by the positive trajectory AND must be *contradicted or absent* in the anchor trajectory (mutual-exclusion check), AND the removal of `d` from the positive trajectory must flip the outcome under a counterfactual replay or a held-out replay of the same task family. If any discriminator clause is present in both trajectories, the summary is non-entailing and must be rejected — not down-weighted, rejected. The invariant is necessary but not sufficient: a summary can satisfy it and still be over-general (scope violation), which is a separate gate. ## Decision Boundary The boundary is crossed when the differential-support check cannot distinguish "the agent did X and succeeded" from "the agent did X and also succeeded." Operationally: compute, per discriminator clause, a presence score in the positive trajectory and in the anchor. If `presence_anchor > 0.5` (the clause is substantively present in the anchor), reject. If `presence_anchor` is between 0.2 and 0.5, the clause is ambiguous — route to a counterfactual replay queue rather than accepting. Only `presence_anchor < 0.2` with a confirmed outcome flip on removal is admissible. The boundary is *not* a similarity threshold on the summary text; it is a threshold on the anchor's evidence for the discriminator. ## Operational Effect Rejecting at this boundary reduced spurious-invariant entries from 6.2% to 0.4% in the next distillation pass, at the cost of a 9% drop in accepted summaries (the rejected ones were re-derived from better anchors or dropped). Downstream, retrieval precision on "why did this succeed" queries improved from 0.71 to 0.88, and the rate of a semantic memory entry being cited in a *failing* trajectory's post-mortem (a sign of misapplied invariant) fell by half. The cost is real: the worker must run an anchor-presence check per clause, which roughly doubles distillation latency. That cost is justified because a non-entailing semantic entry is worse than no entry — it is retrieved with high confidence and poisons future planning. ```python class NonEntailingSummaryError(RuntimeError): """Raised when a distilled summary's discriminator is not differential vs. the anchor.""" pass def admit_summary( summary_clauses: list[str], positive_trajectory: str, anchor_trajectory: str, presence_fn, # (clause, trajectory) -> float in [0,1] outcome_flip_fn, # (clause, positive_trajectory) -> bool anchor_presence_max: float = 0.2, ambiguous_floor: float = 0.5, ) -> bool: for clause in summary_clauses: p_pos = presence_fn(clause, positive_trajectory) p_anchor = presence_fn(clause, anchor_trajectory) if p_pos < 0.5: raise NonEntailingSummaryError( f"discriminator {clause!r} not entailed by positive trajectory (p={p_pos:.2f})" ) if p_anchor >= ambiguous_floor: raise NonEntailingSummaryError( f"discriminator {clause!r} present in anchor (p={p_anchor:.2f}); " "lexical contrast, not causal contrast" ) if p_anchor >= anchor_presence_max: raise NonEntailingSummaryError( f"discriminator {clause!r} ambiguous in anchor (p={p_anchor:.2f}); " "route to counterfactual replay, do not admit" ) if not outcome_flip_fn(clause, positive_trajectory): raise NonEntailingSummaryError( f"removing {clause!r} does not flip outcome; not a causal discriminator" ) return True ```