# Delta `0.3.16-pre.007` — conflit RAW durable minimal et Worker non terminal ## Base requise ```text 0.3.16-pre.006-fix.001 appliqué workspace.package.version = 0.3.16-pre.6.fix.1 ``` Le gate opérateur fourni pour cette base est entièrement propre : audits Rust/export/KSP/Markdown, `cargo check --workspace`, Clippy `-D warnings`, les 29 tests unitaires `ksp-store-api`, les 87 tests unitaires `ksp-store-postgres-lib` et les suites d'intégration ciblées passent. Les trois preuves PostgreSQL live restent opt-in et sont ignorées par le gate déterministe normal. ## Version Cette tranche modifie les contrats Store, le runtime PostgreSQL, le Worker et la projection Backfill : ```text workspace.package.version = 0.3.16-pre.7 ``` ## Objectif Fermer le comportement durable minimal prévu par le plan 038 pour `Conflict` et `Incomparable` : ```text incoming divergent/incomparable -> variante entrante conservée -> canonique courant inchangé -> conflict case durable Open -> observation liée à la variante entrante -> COMMIT atomique -> outcome QuarantinedConflict -> Worker continue en Running -> health Degraded ``` Cette tranche n'introduit ni résolution manuelle/automatique du conflict case, ni historique append-only complet, ni politique générale de retry Store. Ces responsabilités restent différées selon le plan 038. ## Contrat Store variant-aware `RawAcquisitionWriteOutcome` conserve son constructeur historique `new(entity, observation)` pour les backends et consommateurs existants. Il expose désormais en plus une classification transactionnelle optionnelle : ```text transaction_variant: Option ``` Le constructeur `with_transaction_variant(...)` permet à un backend transaction-aware de retourner explicitement le verdict de convergence. PostgreSQL renseigne cette classification pour toutes les acquisitions RAW Transaction : ```text InsertedCanonical ObservedExact ObservedCompatibleLessComplete PromotedCompatibleMoreComplete QuarantinedConflict Rehydrated SkippedPurged ``` `QuarantinedConflict` reste un succès de durabilité Store et non une erreur terminale. `ksp-store-lib` réexporte `RawTransactionVariantWriteOutcome` afin que les consumers restent dépendants de la façade et non de `ksp-store-api` directement. ## Conflict case PostgreSQL Aucune migration V003 n'est modifiée : la table `ksp_raw_transaction_conflicts` et ses contraintes appartiennent déjà au schéma figé livré en amont. Lorsqu'un comparateur partagé retourne `Conflict` ou `Incomparable`, `persist_raw_transaction_acquisition(...)` : ```text verrouille l'identité transactionnelle existante persiste/reuse la variante entrante exacte verrouille le conflict case existant FOR UPDATE insère un case Open revision 1 s'il n'existe pas ou valide/met à jour le case existant avec garde de revision persiste l'observation lie observation -> variante entrante COMMIT émet le journal opérationnel minimal après commit retourne QuarantinedConflict ``` Le canonique courant et son selector ne sont pas modifiés par ce chemin. Une réobservation strictement identique d'un même case déjà `Open` est idempotente : elle ne fabrique pas une nouvelle révision. Une modification réelle du couple canonique/entrant, de la relation ou du reason code incrémente la révision par `checked_add`; l'épuisement est fail-closed. Le conflit reste dans la même transaction que la variante, l'observation et le lien observation-variante. Tout échec avant `COMMIT` laisse PostgreSQL rollbacker l'ensemble. ## Arbitrage Worker La convergence run-local ne conserve plus de représentation locale du contenu canonique et ne peut plus rejeter une divergence avant Store. La cache bornée `(network, signature)` reste uniquement un verrou de sérialisation run-local. Chaque acquisition, y compris une réobservation ou une forme divergente, repasse par `RawTransactionWrite::persist_raw_transaction_acquisition(...)`. Le Store reste donc l'unique autorité de comparaison et de convergence durable. Le Worker valide la cohérence entre l'outcome entity/observation et l'outcome transactionnel. Pour : ```text QuarantinedConflict ``` il considère la persistence comme réussie, incrémente `persisted_total` et `content_conflict_total`, reste `Running` et projette une health `Degraded`. Un backend legacy qui retourne encore `ERROR_CODE_RAW_CONFLICT` reste converti vers l'erreur Worker terminale historique. Ce chemin est conservé uniquement pour compatibilité ; PostgreSQL `pre.007` n'utilise plus cette erreur pour un conflit actif variant-aware. ## Projection Backfill Le Job Backfill reconnaît également `QuarantinedConflict` comme résultat Store durable. Il projette l'entité vers `BackfillEntityPersistence::Conflict` tout en conservant l'outcome réel de l'observation (`Inserted` ou `AlreadyPresent`). L'ancien mapping d'un `ERROR_CODE_RAW_CONFLICT` vers `Conflict + NotRecorded` est conservé pour un backend legacy. Le delta ne change pas la politique de progression/frontier Backfill ; le hardening cross-layer final appartient à `pre.008`. ## Documentation Worker Le README et le USAGE du Worker ne décrivent plus la divergence comme nécessairement terminale ni la cache run-local comme autorité de contenu. Ils documentent le passage systématique par Store, la quarantaine durable et la health `Degraded`. ## Tests et canaris Les tests ajoutés/révisés verrouillent notamment : - l'exposition publique de la classification transactionnelle dans `RawAcquisitionWriteOutcome` ; - le réexport façade de `RawTransactionVariantWriteOutcome` ; - les SQL conflict `INSERT`, `FOR UPDATE` et update compare-and-set sur `revision` ; - l'ordre transactionnel variante -> conflict case -> observation -> commit -> journal ; - la conservation du canonique lors d'un conflit ; - la suppression de l'arbitrage run-local par contenu dans le Worker ; - le passage de chaque acquisition par Store malgré la cache de sérialisation ; - `QuarantinedConflict` comme succès Worker explicite ; - `Running + Degraded`, `persisted_total + 1`, `content_conflict_total + 1` et absence de `store_failure_total` pour la quarantaine ; - la compatibilité terminale du legacy `ERROR_CODE_RAW_CONFLICT` ; - la projection Backfill explicite du conflit durable avec conservation de l'observation. ## Fichiers modifiés ```text Cargo.toml crates/ksp-job-backfill-lib/src/persistence.rs crates/ksp-job-backfill-lib/unit_tests/persistence.rs crates/ksp-store-api/src/capability/raw_transaction.rs crates/ksp-store-api/src/model/raw_outcome.rs crates/ksp-store-api/tests/public_api.rs crates/ksp-store-lib/src/lib.rs crates/ksp-store-lib/tests/hardening_completeness.rs crates/ksp-store-postgres-lib/src/raw_transaction.rs crates/ksp-store-postgres-lib/tests/hardening_completeness.rs crates/ksp-store-postgres-lib/tests/v003_variant_persistence.rs crates/ksp-store-postgres-lib/unit_tests/raw_transaction.rs crates/ksp-worker-raw-transaction-ingest-lib/README.md crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md crates/ksp-worker-raw-transaction-ingest-lib/src/persistence.rs crates/ksp-worker-raw-transaction-ingest-lib/src/snapshot.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/cross_layer_completeness.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/persistence.rs crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime.rs ``` ## Fichier ajouté ```text deltas/0.3.16/pre.007.md ``` ## Fichiers supprimés ```text aucun ``` ## Validation exécutée lors de la génération Sur le checkout complet final : ```bash python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas ``` Le toolchain Rust n'est pas installé dans l'environnement de génération ; `cargo fmt`, `cargo check`, Clippy et les tests Cargo ne sont donc pas déclarés exécutés ici. La base `pre.006-fix.001` dispose en revanche du gate Cargo opérateur entièrement vert fourni avant l'ouverture de cette tranche. Le ZIP minimal doit être rejoué sur une copie fraîche de `pre.006-fix.001`, avec réexécution des audits Python, vérification byte-exacte du payload et confirmation que toutes les ressources de migration PostgreSQL restent inchangées. ## Validation opérateur demandée ```bash cargo fmt --all cargo fmt --all -- --check python3 scripts/audit_rust_workspace_rules.py python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p ksp-store-api --all-targets --all-features cargo test -p ksp-store-lib --all-targets --all-features cargo test -p ksp-store-postgres-lib --all-targets --all-features cargo test -p ksp-job-backfill-lib --all-targets --all-features cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features ``` Les preuves PostgreSQL live restent opt-in et ne sont pas requises dans ce delta fonctionnel minimal ; `pre.008` porte le hardening ciblé et les régressions finales prévues par le plan. ## Décisions prises - `Conflict` et `Incomparable` actifs deviennent des résultats durables non terminaux ; - le canonique courant n'est jamais remplacé par un conflit ; - la variante entrante et son observation sont conservées dans la même transaction que le conflict case ; - le conflict case minimal réutilise le schéma V003 existant sans migration ; - la cache Worker ne possède plus d'autorité de contenu supérieure au Store ; - `QuarantinedConflict` dégrade la health mais ne fault pas le Worker ; - les backends legacy peuvent encore omettre l'outcome transactionnel et retourner l'ancien conflit terminal ; - la résolution des conflits, l'historique append-only et le retry Store restent hors scope. ## Questions ouvertes Aucune question bloquante pour cette tranche. ## Suite Après gate propre : `0.3.16-pre.008` — hardening ciblé de la vertical slice : concurrence, rollback transactionnel, régressions Store/Backfill/Worker, gates workspace, validation documentaire et préparation de `0.3.16-rel.001`.