| 1 | """Auto-discovered X handles must reach resolved_handles. |
| 2 | |
| 3 | resolved_handles gates every first-party protection downstream: the entity-miss |
| 4 | exemption in rerank, FIRST_PARTY_FLOOR, the interaction floor, and the |
| 5 | retrieval-floor exemption in signals. It was built only from --x-handle, |
| 6 | --github-user and --x-related, so on any run that did not pass --x-handle |
| 7 | (the overwhelmingly common case) the whole mechanism was inert. |
| 8 | """ |
| 9 | |
| 10 | import inspect |
| 11 | |
| 12 | from lib import pipeline |
| 13 | |
| 14 | |
| 15 | def _call_supplements(**overrides): |
| 16 | """Drive _run_supplemental_searches far enough to populate the out-param. |
| 17 | |
| 18 | The function bails early when no X or Reddit dicts are present unless a |
| 19 | handle was supplied, so an explicit x_handle is the cheapest way to reach |
| 20 | the resolution block without standing up a full retrieval bundle. |
| 21 | """ |
| 22 | out: list[str] = [] |
| 23 | kwargs = dict( |
| 24 | topic="Peter Steinberger steipete", |
| 25 | bundle=overrides.pop("bundle"), |
| 26 | plan=overrides.pop("plan"), |
| 27 | config={}, |
| 28 | depth="default", |
| 29 | date_range=("2026-07-14", "2026-08-13"), |
| 30 | runtime=overrides.pop("runtime"), |
| 31 | mock=True, |
| 32 | rate_limited_sources=set(), |
| 33 | rate_limit_lock=overrides.pop("lock"), |
| 34 | resolved_handles_out=out, |
| 35 | ) |
| 36 | kwargs.update(overrides) |
| 37 | pipeline._run_supplemental_searches(**kwargs) |
| 38 | return out |
| 39 | |
| 40 | |
| 41 | def test_out_param_is_part_of_the_contract(): |
| 42 | sig = inspect.signature(pipeline._run_supplemental_searches) |
| 43 | assert "resolved_handles_out" in sig.parameters, ( |
| 44 | "the supplement pass must be able to report the handles it resolved; " |
| 45 | "without it resolved_handles cannot see auto-discovered subjects" |
| 46 | ) |
| 47 | assert sig.parameters["resolved_handles_out"].default is None, ( |
| 48 | "the out-param must stay optional so existing callers are unaffected" |
| 49 | ) |
| 50 | |
| 51 | |
| 52 | def test_resolved_handles_includes_supplemental_handles(): |
| 53 | """The merge site must read the supplement pass's output. |
| 54 | |
| 55 | Matched on the assignment rather than an exact literal: an earlier version |
| 56 | pinned "resolved_handles = {" and broke when the construction changed to |
| 57 | merge the explicit set, proving nothing about behavior either way. |
| 58 | """ |
| 59 | src = inspect.getsource(pipeline) |
| 60 | start = src.index("resolved_handles =") |
| 61 | block = src[start:start + 400] |
| 62 | assert "supplemental_handles" in block, ( |
| 63 | "resolved_handles is still built without the handles the supplement " |
| 64 | "pass discovered; auto-discovered subjects stay unprotected" |
| 65 | ) |
| 66 | assert "explicit_first_party" in block, ( |
| 67 | "the user-named handles must still be part of resolved_handles" |
| 68 | ) |
| 69 | |
| 70 | |
| 71 | def test_supplemental_handles_is_seeded_before_the_call(): |
| 72 | src = inspect.getsource(pipeline) |
| 73 | assert "supplemental_handles: list[str] = []" in src |
| 74 | assert "resolved_handles_out=supplemental_handles," in src, ( |
| 75 | "the supplement call must pass the collector it later merges from" |
| 76 | ) |
| 77 | |
| 78 | |
| 79 | def test_handles_are_normalized_and_deduped(): |
| 80 | """Normalization must match resolved_handles' own lstrip/strip/lower form.""" |
| 81 | src = inspect.getsource(pipeline._run_supplemental_searches) |
| 82 | block = src[src.index("resolved_handles_out is not None"):] |
| 83 | assert 'lstrip("@")' in block and ".lower()" in block, ( |
| 84 | "handles must be normalized the same way resolved_handles normalizes, " |
| 85 | "or the set comparison in rerank/_is_first_party will miss them" |
| 86 | ) |
| 87 | assert "seen" in block, "duplicate handles must not accumulate" |
| 88 | |
| 89 | |
| 90 | def test_population_precedes_the_no_handles_early_return(): |
| 91 | """A run whose lanes cannot execute must still contribute its handles.""" |
| 92 | src = inspect.getsource(pipeline._run_supplemental_searches) |
| 93 | populate_at = src.index("resolved_handles_out is not None") |
| 94 | early_return_at = src.index("if not handles and not related_handles:") |
| 95 | assert populate_at < early_return_at, ( |
| 96 | "handles are surfaced after the early return, so a run with no usable " |
| 97 | "handle lane would silently contribute nothing to resolved_handles" |
| 98 | ) |
| 99 |