v0.3.6-pre.003

This commit is contained in:
2026-09-01 11:58:38 +02:00
parent cb670952e8
commit f92c22d55a
12 changed files with 604 additions and 48 deletions

180
deltas/0.3.6/pre.003.md Normal file
View File

@@ -0,0 +1,180 @@
<!-- file: deltas/0.3.6/pre.003.md -->
<!-- version: 1 -->
# Delta `0.3.6-pre.003` — notifications Job latest-value génériques
## Base requise
```text
0.3.6-pre.002-fix.001
workspace.package.version = 0.3.6-pre.2.fix.1
SHA-256 archive = 0b6640155786b92e27508637af2bcc7a0a34e5e8e4185d76ac4dd6d71aa7a869
```
Le gate opérateur fourni pour cette base confirme `cargo fmt`, audits Rust/Markdown, `cargo check --workspace`, Clippy, les dix tests unitaires et onze canaries `ksp-job-api`, les suites individuelles, `cargo test --workspace`, les arbres Cargo Job API et l'examen des doublons.
## Objectif
Matérialiser la tranche `pre.003` du plan 027 : observation Job latest-value runtime-neutral avec séquence monotone, snapshot complet courant, attente abstraite d'une valeur plus récente et resynchronisation multi-listeners, sans ouvrir encore `ksp-job-backfill-lib` ni imposer Tokio à l'API.
## Audit des archives et des règles
Les deux archives fournies ont été testées avant modification :
```text
KSP 0.3.6-pre.002-fix.001
SHA-256 = 0b6640155786b92e27508637af2bcc7a0a34e5e8e4185d76ac4dd6d71aa7a869
1541 entrées / aucune duplication / aucune traversée / aucun chemin absolu / aucun lien symbolique ZIP
unzip -t = propre
kbot3 v0.5.3-pre.005-fix010
SHA-256 = ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318
2501 entrées / aucune duplication / aucune traversée / aucun chemin absolu / aucun lien symbolique ZIP
unzip -t = propre
```
La base KSP ne contient ni `Cargo.lock`, ni `.env`, ni `target`, ni `node_modules`, ni secret ou artefact de build détecté par l'inventaire statique. L'archive kbot3 reste une référence historique et contient notamment un `scripts/__pycache__`; ce contenu n'est ni copié ni livré.
Les autorités relues incluent `RULES.md`, `docs/000-README.md`, les règles sous `docs/rules/`, les architectures Layers/Dependencies, Component Contracts, Dependency Graph et Acquisition/Workers/Jobs, le prompt 025, le plan 027, la validation 023 et les deltas `pre.001` à `pre.002-fix.001`.
Pour cette tranche, kbot3 confirme uniquement le besoin fonctionnel historique : `BackfillObserver::on_progress` appelait directement le consumer applicatif et exposait timestamp, niveau, message libre et compteurs optionnels. KSP conserve l'observabilité mais rejette cette forme callback/producteur ; aucun code, DTO, ID, message ou runtime kbot3 n'est repris.
## Surface ajoutée
`JobNotificationSequence` :
- position initiale contrôlée par l'API ;
- progression unitaire par `checked_add` ;
- ordre total et test `is_after` ;
- erreur stable `job_api.job_notification_sequence_exhausted` avant tout wrap.
`JobNotification<S>` :
- `JobId`, `JobKindCode`, séquence, `JobState` et snapshot complet ;
- champs privés et valeur immutable ;
- `Debug` structurel qui masque toujours le snapshot générique.
`JobSnapshotFuture<'a, S>` et `JobSnapshotSource` :
- futur abstrait fondé uniquement sur `std::future::Future`, `Pin` et `Box` ;
- lecture du snapshot courant ;
- attente d'une valeur plus récente après une séquence observée ;
- coalescence autorisée des progressions intermédiaires, avec resynchronisation sur le snapshot complet courant ;
- aucun callback producteur, channel Tokio, event log, Tauri ou historique public.
La source runtime concrète n'est pas créée dans Job API. Elle restera possédée par `ksp-job-backfill-lib` lorsque cette crate ouvrira ; les canaries de `pre.003` prouvent le contrat externe, sans annoncer comme acquises les propriétés runtime O(1), wake-up ou isolation du producteur avant ce consumer réel.
## Tests ajoutés
Trois unitaires :
- progression stricte et ordre de séquence ;
- épuisement `u64::MAX` explicite sans wrap ;
- conservation de la valeur et redaction du snapshot en `Debug`.
Trois canaries externes :
- consommation de l'enveloppe depuis le crate-root ;
- deux listeners indépendants resynchronisés vers la dernière valeur après séquences anciennes différentes ;
- snapshot terminal encore lisible depuis un handle partagé.
Les canaries de dépendances et de complétude existantes sont étendues pour couvrir `notification.rs`, les nouveaux exports et l'absence de fuite Backfill/Worker/runtime.
## Fichiers ajoutés
```text
crates/ksp-job-api/src/notification.rs
crates/ksp-job-api/tests/notifications.rs
crates/ksp-job-api/unit_tests/notification.rs
deltas/0.3.6/pre.003.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-job-api/src/error.rs
crates/ksp-job-api/src/lib.rs
crates/ksp-job-api/tests/dependency_boundary.rs
crates/ksp-job-api/tests/release_completeness.rs
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
```
Mécanique Cargo :
```text
header version: 396 -> 397
workspace.package.version: 0.3.6-pre.2.fix.1 -> 0.3.6-pre.3
workspace members: inchangés
workspace dependencies: inchangées
```
## Fichiers supprimés
Aucun.
## Décisions prises
- une séquence publique ne se construit pas depuis un entier arbitraire ; elle part de `initial()` puis progresse via `next()` ;
- `JobNotification<S>` reste générique afin que Job API ne possède aucun snapshot Backfill prématuré ;
- le `Debug` de l'enveloppe ne demande pas `S: Debug` et ne rend jamais le snapshot ;
- le contrat d'attente expose un futur `std` boxed plutôt qu'un type Tokio ou un callback ;
- la sémantique publique est latest-value, pas une queue et pas un event log durable ;
- une séquence manquée n'exige aucun replay : le listener reprend le snapshot complet le plus récent ;
- la source concrète et son wake-up ne sont pas simulés comme fonctionnalité de production dans Job API ; ils seront prouvés avec le premier consumer réel ;
- `ksp-job-api` conserve exactement sa dépendance normale Core-only et aucune feature/dev-dependency/build-dependency n'est ajoutée ;
- aucun README/USAGE intermédiaire n'est créé avant la surface consommable réconciliée prévue par le plan.
## Validations exécutées
```text
unzip -tq des deux archives
-> propre
inventaire ZIP
-> KSP: 1541 entrées, 0 duplicate, 0 traversal, 0 absolute, 0 symlink
-> kbot3: 2501 entrées, 0 duplicate, 0 traversal, 0 absolute, 0 symlink
python3 scripts/audit_rust_workspace_rules.py
-> General Rust rule audit: clean
-> Rust export completeness audit: 0 candidate(s)
-> KSP workspace Rust rule audit: clean
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
-> Markdown table audit: clean (264 tables / 144 fichiers)
python3 -m unittest scripts/tests/test_audit_markdown_tables.py
-> 5 tests / OK
inventaire statique ksp-job-api
-> 13 tests unitaires
-> 14 canaries d'intégration
```
L'inventaire différentiel base/travail confirme que seuls les fichiers listés par ce delta sont ajoutés ou modifiés, hors caches Python temporaires supprimés avant assemblage.
## Validations non exécutées
L'environnement d'assemblage ne fournit ni `cargo` ni `rustfmt`. Les commandes Rust de `pre.003` ne sont donc pas annoncées comme réussies localement.
Le smoke réseau et PostgreSQL ne concernent pas cette tranche API-only.
## Gate opérateur demandé
```bash
cargo fmt --all
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/0.3.6
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-job-api
cargo tree -p ksp-job-api --edges normal
cargo tree -p ksp-job-api -e features
```
Le résultat attendu pour `ksp-job-api` après cette tranche est treize tests unitaires et quatorze canaries d'intégration, sans nouvelle dépendance normale ou feature.
## Questions ouvertes
Aucune question ne bloque `pre.004` après un gate opérateur vert de `pre.003`.