# Delta `0.3.16-pre.006` — promotion atomique du canonique RAW ## Base requise ```text 0.3.16-pre.005-fix.001 appliqué workspace.package.version = 0.3.16-pre.5.fix.1 ``` Le gate opérateur fourni pour la base est propre : audits Rust/export/KSP/Markdown, `cargo check --workspace`, Clippy `-D warnings`, toutes les suites `ksp-store-api` et `ksp-store-postgres-lib` ciblées passent. Les preuves PostgreSQL live restent opt-in. L'audit de l'archive source fournie a relevé un unique artefact ignoré, `scripts/__pycache__/audit_rust_general_rules.cpython-313.pyc`, alors que `.gitignore` exclut `__pycache__/`. Cet artefact n'appartient pas au source ni au delta et est explicitement exclu de l'archive `pre.006`. Aucun autre candidat correspondant aux familles ignorées de `.gitignore` n'a été trouvé. ## Version Cette tranche modifie le runtime PostgreSQL : ```text workspace.package.version = 0.3.16-pre.6 ``` ## Objectif Rendre effectif le sens déjà reconnu par le comparateur partagé : ```text canonique logMessages tronqué + incoming logMessages complet strictement prouvé => CompatibleMoreComplete => variante entrante durable => promotion canonique atomique => ancien canonique conservé ``` Aucune règle de dominance nouvelle n'est ajoutée. `logMessages` reste la seule preuve automatique de complétude et les autres différences continuent à suivre la politique fail-closed de `pre.005`. ## Promotion atomique Le chemin PostgreSQL `persist_raw_transaction_acquisition` traite désormais `CompatibleMoreComplete` dans la même transaction que l'acquisition : ```text lock identité V001 ensure bootstrap V003 compare canonique / incoming persist ou reuse variante incoming exacte charger selector + revision conserver l'ancien canonique mettre à jour la projection V001 mettre à jour selector + canonical_revision persist observation lier observation -> variante incoming COMMIT ``` Le selector est modifié avec une garde exacte sur : ```text transaction_signature canonical_variant_id attendu canonical_revision attendue ``` La nouvelle révision est calculée par incrément borné `u64`; l'épuisement de la révision est fail-closed avant mutation canonique. Toute cardinalité inattendue ou changement du selector observé pendant la transaction provoque une erreur et laisse PostgreSQL rollbacker l'ensemble de la promotion. ## Projection V001 cohérente Lors d'une promotion, la projection de compatibilité `ksp_raw_transactions` est remplacée par la représentation entrante complète : ```text slot block_time_unix_millis format_id format_version content_hash payload retention_state = full ``` Le selector V003 n'est déplacé qu'au sein de la même transaction. Il ne peut donc pas être durablement avancé si la projection V001 échoue, ni inversement. ## Conservation de l'ancien canonique L'ancienne variante canonique n'est jamais supprimée ni écrasée par la nouvelle variante. Cas `Full` : l'ancienne variante V003 est confirmée byte-exactement sur slot, block time, format, version, hash et payload avant tout remplacement de projection. Cas projection V001 `Archived` : les bytes encore disponibles dans `ksp_raw_transaction_archive_payloads` sont d'abord copiés ou confirmés byte-exacts dans l'ancienne variante V003, avec la même vérification de métadonnées, puis l'archive V001 devenue obsolète est supprimée avant de remettre la projection V001 à `Full` sur le nouveau canonique. Cette copie de sauvegarde est une nécessité de promotion/rollback local, pas l'ouverture de la politique générale de rétention des variantes prévue en `0.3.17`. Aucune reconstruction réseau n'est utilisée. ## Révision et historique minimal `canonical_revision` devient effectivement monotone lors d'une promotion automatique et constitue la garde durable du selector courant. Un journal opérationnel minimal est émis uniquement après le `COMMIT` réussi de l'acquisition. Il porte seulement le réseau, le slot, l'ancien/nouveau `variant_id` et l'ancienne/nouvelle `canonical_revision`; aucun payload ni signature n'est journalisé. Une promotion rollbackée n'est donc jamais annoncée comme commitée. Cette tranche n'ajoute pas de table append-only supplémentaire : le journal durable complet des actions/résolutions et les participants de conflit restent explicitement différés par le plan 038 à `0.3.17`. `pre.006` conserve donc le scope V003 déjà figé et n'altère aucun checksum de migration. ## Conflits toujours différés Cette tranche ne modifie pas le comportement durable de : ```text Conflict Incomparable ``` Ils restent projetés vers `raw_acquisition_content_conflict` jusqu'à `0.3.16-pre.007`. En particulier, `pre.006` n'écrit toujours pas dans : ```text ksp_raw_transaction_conflicts ``` et ne rend encore aucun conflit non terminal côté Worker. ## Tests et canaris Les tests unitaires PostgreSQL ajoutés verrouillent : - l'incrément borné de `canonical_revision` ; - la garde selector par ancien `canonical_variant_id` et ancienne revision ; - la projection V001 complète vers le nouveau canonique `Full` ; - la conservation locale d'une ancienne variante `Archived` ou déjà `Full`. Le canari `v003_variant_persistence.rs` est avancé de `pre.005` vers `pre.006` et exige désormais : - le chemin `ActiveCompatibleMoreComplete` ; - la persistance de la variante avant promotion ; - la promotion avant l'observation et avant le commit final ; - l'update du selector et de `canonical_revision` ; - l'update de la projection V001 ; - la conservation de l'ancien canonique ; - le journal opérationnel de promotion placé après le commit réussi ; - l'absence persistante d'écriture dans la table de conflits avant `pre.007`. ## Fichiers modifiés ```text Cargo.toml crates/ksp-store-postgres-lib/src/raw_transaction.rs crates/ksp-store-postgres-lib/tests/v003_variant_persistence.rs crates/ksp-store-postgres-lib/unit_tests/raw_transaction.rs ``` ## Fichier ajouté ```text deltas/0.3.16/pre.006.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 ``` Résultat : audits Rust/export/KSP et Markdown propres. Le ZIP minimal final est ensuite appliqué sur une copie fraîche de `0.3.16-pre.005-fix.001`. Les mêmes audits y restent propres, les cinq fichiers livrés sont byte-identiques au checkout de génération et les 98 ressources de migration PostgreSQL restent byte-identiques à la base. Des canaris statiques supplémentaires ont été rejoués sur le source final et sur le replay pour confirmer l'ordre : variante -> promotion -> observation -> mapping -> commit -> journal opérationnel, l'existence des updates selector/projection, la conservation byte-exacte de l'ancien canonique et l'absence d'écriture de conflit. 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. Le gate Cargo propre de la base provient du log opérateur fourni avec `pre.005-fix.001`. ## 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-postgres-lib --all-targets --all-features ``` Les preuves PostgreSQL live restent opt-in pour cette tranche ; elles pourront être rejouées séparément sur une base dédiée. ## Décisions prises - une promotion automatique n'est admise que pour `CompatibleMoreComplete` déjà prouvé par le comparateur partagé ; - la projection V001 et le selector V003 restent une seule mutation transactionnelle ; - l'ancien canonique est conservé localement avant tout remplacement de projection ; - `canonical_revision` est incrémentée avec garde compare-and-set ; - aucune migration existante n'est modifiée ; - le journal append-only complet reste reporté selon le plan 038. ## Questions ouvertes Aucune question bloquante pour cette tranche. Les conflict cases durables et l'outcome Worker non terminal appartiennent à `pre.007`. ## Suite Après gate propre : `0.3.16-pre.007` — conflit durable minimal + intégration Worker : variante divergente conservée, case `Open`, outcome Store non terminal, arbitrage run-local limité à l'autorité du Store et health `Degraded` lorsque requis.