# Pipeline de replay Le replay ne doit pas être global par défaut. Chaque campagne reçoit un `campaign_id` et cible un ensemble explicite de processors, une version et un périmètre borné d’inputs. ## Étapes ```text ingest -> extract -> observe -> decode -> materialize -> aggregate -> validate ``` Chaque étape doit être rejouable séparément avec son propre ledger versionné. ## Sélection de décodage La sélection opérateur peut utiliser : - des signatures ; - une plage de slots ; - des `program_id` ; - des instruction paths ; - des états lifecycle ; - une limite stricte. Le pipeline calcule ensuite `effective_program_ids` comme l’union des programmes déclarés par les décodeurs activés. Sans filtre program ID explicite, cette union est appliquée automatiquement au store. Avec un filtre explicite, chaque valeur doit être supportée par au moins un décodeur activé, sinon la campagne est refusée avant la requête SQL. Cette règle évite qu’un classifieur natif sélectionne des instructions SPL, Jupiter, Pump ou d’autres programmes non compatibles. Elle empêche également la resélection infinie d’un lot entièrement `unmatched` uniquement parce que les processors choisis ne couvrent pas ses programmes. ## Force replay Le force replay contourne le skip processor/version/input/hash, mais reste borné par une liste de signatures explicites ou par une autorisation opérateur « toutes les signatures » combinée aux autres filtres et à la limite. Une requête sans l’un de ces deux scopes est refusée. Lorsqu’une campagne contient des signatures explicites, `force_replay=true` retire le filtre lifecycle pour ces signatures. Les inputs déjà terminaux peuvent alors être réellement rejoués. Le mode explicite « toutes les signatures » retire également ce filtre, mais conserve obligatoirement le scope des programmes compatibles, les slots et instruction paths éventuels ainsi que la limite. Sans signatures ni autorisation « toutes les signatures », la requête est refusée. Le remplacement ne touche que les sorties du processor, de la version et de l’input ciblés. Les autres processors et les autres versions restent intacts. ## Skip Sans force replay, un input est skippé uniquement lorsque le ledger contient un succès ayant exactement : ```text stage processor_name processor_version input_key input_hash ``` Une campagne de validation doit pouvoir montrer successivement : ```text premier passage -> decoded/ignored/unsupported second passage -> skipped force replay -> exécution sans skip passage suivant -> skipped ``` ## Unmatched `unmatched` signifie qu’aucun décodeur compatible n’a accepté l’input après le filtre exact de programme. L’instruction n’est pas marquée globalement comme définitivement ignorée, car un futur processor peut la supporter. Les décodeurs doivent classer comme `unsupported` les instructions inconnues de leurs propres programmes afin de produire une couverture exploitable. ## Traçabilité Les logs de campagne conservent : ```text campaign_id signature_count signature_sample decoder_names requested_program_ids effective_program_ids requested_processing_states effective_processing_states force_replay ``` Les logs par input conservent ensuite la signature exacte, le path, le programme, le processor, le hash et la décision terminale.