File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 6363from autoskillit .recipe ._rule_helpers import (
6464 _is_failure_sentinel_value ,
6565 extract_sentinel_json_blocks ,
66+ filter_pruning_false_positives ,
6667)
6768from autoskillit .recipe .contracts import (
6869 check_contract_staleness ,
@@ -430,14 +431,9 @@ def load_and_validate(
430431 t0 = _t ("semantic_rules" , t0 , name )
431432
432433 if _skip_resolutions and any (v is False for v in _skip_resolutions .values ()):
433- _pre_prune_finding_keys : frozenset [ tuple [ str , str , str ]] = frozenset (
434- ( f . rule , f . step_name , f . message ) for f in _pre_prune_findings
434+ semantic_findings = filter_pruning_false_positives (
435+ semantic_findings , _pre_prune_findings
435436 )
436- semantic_findings = [
437- f
438- for f in semantic_findings
439- if (f .rule , f .step_name , f .message ) in _pre_prune_finding_keys
440- ]
441437 semantic_suggestions = findings_to_dicts (semantic_findings )
442438
443439 _suppressed = suppressed or []
Original file line number Diff line number Diff line change 99from autoskillit .recipe ._analysis import make_validation_context
1010from autoskillit .recipe ._recipe_composition import _prune_skipped_steps
1111from autoskillit .recipe ._recipe_ingredients import RecipeListItem
12+ from autoskillit .recipe ._rule_helpers import filter_pruning_false_positives
1213from autoskillit .recipe .contracts import load_recipe_card , validate_recipe_cards
1314from autoskillit .recipe .io import (
1415 RecipeInfo ,
@@ -146,14 +147,7 @@ def validate_from_path(
146147 report = ctx .dataflow
147148 semantic_findings = run_semantic_rules (ctx )
148149 if _skip_resolutions and any (v is False for v in _skip_resolutions .values ()):
149- _pre_prune_finding_keys : frozenset [tuple [str , str , str ]] = frozenset (
150- (f .rule , f .step_name , f .message ) for f in _pre_prune_findings
151- )
152- semantic_findings = [
153- f
154- for f in semantic_findings
155- if (f .rule , f .step_name , f .message ) in _pre_prune_finding_keys
156- ]
150+ semantic_findings = filter_pruning_false_positives (semantic_findings , _pre_prune_findings )
157151
158152 quality = build_quality_dict (report )
159153 semantic = findings_to_dicts (semantic_findings )
Original file line number Diff line number Diff line change 1515
1616if TYPE_CHECKING :
1717 from autoskillit .recipe ._contracts_types import SkillContract
18+ from autoskillit .recipe .registry import RuleFinding
1819 from autoskillit .recipe .schema import CampaignDispatch , Recipe , RecipeStep
1920
2021logger = get_logger (__name__ )
@@ -268,3 +269,19 @@ def _identify_optional_output_fields(contract: SkillContract) -> set[str]:
268269 if m and m .group (1 ) in output_names :
269270 optional .add (m .group (1 ))
270271 return optional
272+
273+
274+ def filter_pruning_false_positives (
275+ post_prune_findings : list [RuleFinding ],
276+ pre_prune_findings : list [RuleFinding ],
277+ ) -> list [RuleFinding ]:
278+ """Keep only post-prune findings that also appeared pre-prune.
279+
280+ Graph-aware rules (dead-output, capture-inversion) produce false positives
281+ when pruning changes step-graph reachability. Intersecting with the
282+ pre-prune baseline suppresses findings introduced by pruning.
283+ """
284+ pre_prune_keys : frozenset [tuple [str , str , str ]] = frozenset (
285+ (f .rule , f .step_name , f .message ) for f in pre_prune_findings
286+ )
287+ return [f for f in post_prune_findings if (f .rule , f .step_name , f .message ) in pre_prune_keys ]
You can’t perform that action at this time.
0 commit comments