0.0.2-alpha.5

This commit is contained in:
2026-09-29 05:59:03 +02:00
parent 1fe39dfdeb
commit da5445354e
15 changed files with 613 additions and 26 deletions

View File

@@ -1,10 +1,11 @@
# file: Cargo.toml # file: Cargo.toml
# version: 24 # version: 25
[workspace] [workspace]
resolver = "3" resolver = "3"
members = [ members = [
"crates/knowledge-domain-lib", "crates/knowledge-domain-lib",
"crates/knowledge-app-lib",
"crates/knowledge-git-api", "crates/knowledge-git-api",
"crates/knowledge-git-lib", "crates/knowledge-git-lib",
"crates/knowledge-sync-api", "crates/knowledge-sync-api",
@@ -15,12 +16,13 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.0.2-alpha.4.fix.1" version = "0.0.2-alpha.5"
edition = "2024" edition = "2024"
publish = false publish = false
repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge" repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge"
[workspace.dependencies] [workspace.dependencies]
knowledge-sync-api = { path = "crates/knowledge-sync-api" }
knowledge-domain-lib = { path = "crates/knowledge-domain-lib" } knowledge-domain-lib = { path = "crates/knowledge-domain-lib" }
knowledge-git-api = { path = "crates/knowledge-git-api" } knowledge-git-api = { path = "crates/knowledge-git-api" }
knowledge-web-lib = { path = "crates/knowledge-web-lib" } knowledge-web-lib = { path = "crates/knowledge-web-lib" }

View File

@@ -1,5 +1,5 @@
<!-- file: README.md --> <!-- file: README.md -->
<!-- version: 14 --> <!-- version: 15 -->
# SaseDev Knowledge # SaseDev Knowledge
@@ -11,9 +11,9 @@ Le dépôt applicatif retenu est `sasedev-knowledge`. Le nom court du projet et
La version courante est définie par [`VERSION`](VERSION). La version courante est définie par [`VERSION`](VERSION).
`0.0.1` est la première stable de fondation de SaseDev Knowledge. `0.0.2-alpha.3.fix.1` ferme en `PASS` le chemin Git générique de lecture. `0.0.2-alpha.4` termine l'autonomie normative après l'adoption ponctuelle PGR `v0.1.3` et normalise les crate-roots bibliothèque comme façades. `0.0.1` est la première stable de fondation de SaseDev Knowledge. `0.0.2-alpha.3.fix.1` ferme en `PASS` le chemin Git générique de lecture. `0.0.2-alpha.4.fix.1` ferme en `PASS` l'autonomie normative après l'adoption ponctuelle PGR `v0.1.3`. `0.0.2-alpha.5` matérialise le cas d'usage partagé de synchronisation de lecture.
`knowledge-git-lib` implémente `knowledge-git-api::GitRepository` pour des sources physiques enregistrées : mirror contrôlé, refresh avec pruning, résolution d'une référence vers un commit et snapshot/worktree détaché adressé par révision. `alpha.4` ne change pas cette sémantique. Les règles nécessaires au développement courant sont désormais possédées localement sous `docs/rules/`, et les futurs prompts Knowledge ne chargent pas PGR sauf réévaluation explicitement engagée. Le cas d'usage de synchronisation reste réservé à `alpha.5`. `knowledge-git-lib` implémente `knowledge-git-api::GitRepository` pour des sources physiques enregistrées : mirror contrôlé, refresh avec pruning, résolution d'une référence vers un commit et snapshot/worktree détaché adressé par révision. `alpha.4` ne change pas cette sémantique. Les règles nécessaires au développement courant sont désormais possédées localement sous `docs/rules/`, et les futurs prompts Knowledge ne chargent pas PGR sauf réévaluation explicitement engagée. `knowledge-app-lib` compose maintenant refresh, résolution, comparaison avec la révision précédente et préparation de snapshot en un résultat explicite `Changed` / `Unchanged`, sans persister la dernière révision ni matérialiser de scheduler.
## Topologie produit de fondation ## Topologie produit de fondation
@@ -33,7 +33,7 @@ PostgreSQL est mutualisable et constitue la baseline retenue pour l'état transv
Chaque application Web doit pouvoir exposer sa propre surface d'administration protégée pour son domaine. Les chemins HTTP exacts ne sont pas encore figés. Une éventuelle quatrième application d'administration pourra agréger des fonctions transversales, mais elle ne remplacera pas les contrôles d'autorisation propres aux trois serveurs. Chaque application Web doit pouvoir exposer sa propre surface d'administration protégée pour son domaine. Les chemins HTTP exacts ne sont pas encore figés. Une éventuelle quatrième application d'administration pourra agréger des fonctions transversales, mais elle ne remplacera pas les contrôles d'autorisation propres aux trois serveurs.
Le workspace Rust matérialise huit packages : les trois frontières de fondation `knowledge-domain-lib`, `knowledge-git-api` et `knowledge-sync-api`, le backend `knowledge-git-lib`, la composition partagée `knowledge-web-lib`, puis les trois launchers `knowledge-pgr-server`, `knowledge-howtos-server` et `knowledge-snippets-server`. Les deux crates `-api` restent passives et indépendantes d'Actix, Gitea et PostgreSQL. Le workspace Rust matérialise neuf packages : les trois frontières de fondation `knowledge-domain-lib`, `knowledge-git-api` et `knowledge-sync-api`, le backend `knowledge-git-lib`, la couche application partagée `knowledge-app-lib`, la composition Web `knowledge-web-lib`, puis les trois launchers `knowledge-pgr-server`, `knowledge-howtos-server` et `knowledge-snippets-server`. Les deux crates `-api` restent passives et indépendantes d'Actix, Gitea et PostgreSQL.
## Frontend de référence et rendu Maud ## Frontend de référence et rendu Maud

View File

@@ -1 +1 @@
0.0.2-alpha.4.fix.1 0.0.2-alpha.5

View File

@@ -0,0 +1,19 @@
# file: crates/knowledge-app-lib/Cargo.toml
# version: 1
[package]
name = "knowledge-app-lib"
version.workspace = true
edition.workspace = true
publish.workspace = true
repository.workspace = true
[dependencies]
knowledge-git-api.workspace = true
knowledge-sync-api.workspace = true
[dev-dependencies]
knowledge-domain-lib.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,14 @@
// file: crates/knowledge-app-lib/src/lib.rs
// version: 1
//! Shared application use cases for SaseDev Knowledge.
//!
//! This crate composes provider-neutral application contracts. It owns no Git process, scheduler,
//! database, HTTP runtime or forge integration.
mod repository_sync;
/// Result of reconciling one repository-backed content source.
pub use self::repository_sync::RepositorySyncOutcome;
/// Reconcile one source through the provider-neutral Git repository contract.
pub use self::repository_sync::synchronize_repository;

View File

@@ -0,0 +1,89 @@
// file: crates/knowledge-app-lib/src/repository_sync.rs
// version: 1
/// Result of reconciling one repository-backed content source.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RepositorySyncOutcome {
/// The observed revision matches the revision already known by the caller.
Unchanged {
/// Authoritative revision observed after refresh and resolution.
revision: knowledge_git_api::GitRevision,
},
/// The observed revision differs and a read snapshot has been prepared.
Changed {
/// Authoritative revision observed after refresh and resolution.
revision: knowledge_git_api::GitRevision,
/// Read-only snapshot prepared for the new authoritative revision.
snapshot: knowledge_git_api::GitSnapshot,
},
}
impl crate::RepositorySyncOutcome {
/// Return the authoritative revision observed by reconciliation.
pub fn revision(&self) -> &knowledge_git_api::GitRevision {
match self {
crate::RepositorySyncOutcome::Unchanged { revision } => return revision,
crate::RepositorySyncOutcome::Changed { revision, snapshot: _ } => return revision,
}
}
/// Return the prepared snapshot when reconciliation detected a change.
pub fn snapshot(&self) -> Option<&knowledge_git_api::GitSnapshot> {
match self {
crate::RepositorySyncOutcome::Unchanged { revision: _ } => return None,
crate::RepositorySyncOutcome::Changed { revision: _, snapshot } => return Some(snapshot),
}
}
/// Return whether reconciliation detected a new authoritative revision.
pub fn is_changed(&self) -> bool {
match self {
crate::RepositorySyncOutcome::Unchanged { revision: _ } => return false,
crate::RepositorySyncOutcome::Changed { revision: _, snapshot: _ } => return true,
}
}
}
/// Reconcile one source through the provider-neutral Git repository contract.
///
/// The signal cause does not change the reconciliation path: explicit, periodic and external
/// signals all request the same authoritative refresh/resolve/compare operation. The caller owns
/// persistence of the previous revision and any scheduling policy.
pub fn synchronize_repository<R>(
repository: &mut R,
signal: &knowledge_sync_api::RepositorySyncSignal,
reference: &knowledge_git_api::GitReference,
previous_revision: Option<&knowledge_git_api::GitRevision>,
) -> Result<crate::RepositorySyncOutcome, R::Error>
where
R: knowledge_git_api::GitRepository,
{
let refresh_result = knowledge_git_api::GitRepository::refresh(repository, signal.source_id());
match refresh_result {
Ok(()) => (),
Err(error) => return Err(error),
}
let revision_result = knowledge_git_api::GitRepository::resolve_revision(repository, signal.source_id(), reference);
let revision = match revision_result {
Ok(value) => value,
Err(error) => return Err(error),
};
match previous_revision {
Some(previous) => {
if previous == &revision {
return Ok(crate::RepositorySyncOutcome::Unchanged { revision });
}
},
None => (),
}
let snapshot_result = knowledge_git_api::GitRepository::prepare_snapshot(repository, signal.source_id(), &revision);
let snapshot = match snapshot_result {
Ok(value) => value,
Err(error) => return Err(error),
};
return Ok(crate::RepositorySyncOutcome::Changed { revision, snapshot });
}
#[cfg(test)]
#[path = "../unit_tests/repository_sync.rs"]
mod tests;

View File

@@ -0,0 +1,121 @@
// file: crates/knowledge-app-lib/unit_tests/repository_sync.rs
// version: 1
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct FakeRepositoryError;
struct FakeRepository {
observed_revision: knowledge_git_api::GitRevision,
reject_snapshot: bool,
}
impl FakeRepository {
fn new(observed_revision: &str, reject_snapshot: bool) -> FakeRepository {
return FakeRepository { observed_revision: knowledge_git_api::GitRevision::new(observed_revision), reject_snapshot };
}
}
impl knowledge_git_api::GitRepository for FakeRepository {
type Error = FakeRepositoryError;
fn refresh(&mut self, _source_id: &knowledge_domain_lib::SourceId) -> Result<(), Self::Error> {
return Ok(());
}
fn resolve_revision(
&self,
_source_id: &knowledge_domain_lib::SourceId,
_reference: &knowledge_git_api::GitReference,
) -> Result<knowledge_git_api::GitRevision, Self::Error> {
return Ok(self.observed_revision.clone());
}
fn prepare_snapshot(
&self,
_source_id: &knowledge_domain_lib::SourceId,
revision: &knowledge_git_api::GitRevision,
) -> Result<knowledge_git_api::GitSnapshot, Self::Error> {
if self.reject_snapshot {
return Err(FakeRepositoryError);
}
return Ok(knowledge_git_api::GitSnapshot::new(revision.clone(), std::path::PathBuf::from("/controlled/snapshot")));
}
}
fn source_id() -> Option<knowledge_domain_lib::SourceId> {
let result = knowledge_domain_lib::SourceId::new("snippets");
match result {
Ok(value) => return Some(value),
Err(_) => return None,
}
}
fn signal(cause: knowledge_sync_api::RepositorySyncCause) -> Option<knowledge_sync_api::RepositorySyncSignal> {
let id = match source_id() {
Some(value) => value,
None => return None,
};
return Some(knowledge_sync_api::RepositorySyncSignal::new(id, cause));
}
#[test]
fn changed_revision_prepares_snapshot_and_returns_observed_revision() {
let mut repository = FakeRepository::new("bbbb", false);
let request = match signal(knowledge_sync_api::RepositorySyncCause::Explicit) {
Some(value) => value,
None => return,
};
let reference = knowledge_git_api::GitReference::new("refs/heads/main");
let previous = knowledge_git_api::GitRevision::new("aaaa");
let result = crate::synchronize_repository(&mut repository, &request, &reference, Some(&previous));
assert!(result.is_ok());
let outcome = match result {
Ok(value) => value,
Err(_) => return,
};
assert!(outcome.is_changed());
assert_eq!(outcome.revision().as_str(), "bbbb");
assert!(outcome.snapshot().is_some());
return;
}
#[test]
fn unchanged_revision_does_not_prepare_snapshot() {
let mut repository = FakeRepository::new("bbbb", true);
let request = match signal(knowledge_sync_api::RepositorySyncCause::Explicit) {
Some(value) => value,
None => return,
};
let reference = knowledge_git_api::GitReference::new("refs/heads/main");
let previous = knowledge_git_api::GitRevision::new("bbbb");
let result = crate::synchronize_repository(&mut repository, &request, &reference, Some(&previous));
assert!(result.is_ok());
let outcome = match result {
Ok(value) => value,
Err(_) => return,
};
assert!(!outcome.is_changed());
assert_eq!(outcome.revision().as_str(), "bbbb");
assert!(outcome.snapshot().is_none());
return;
}
#[test]
fn periodic_signal_uses_the_same_reconciliation_path() {
let mut repository = FakeRepository::new("cccc", false);
let request = match signal(knowledge_sync_api::RepositorySyncCause::Periodic) {
Some(value) => value,
None => return,
};
let reference = knowledge_git_api::GitReference::new("refs/heads/main");
let result = crate::synchronize_repository(&mut repository, &request, &reference, None);
assert!(result.is_ok());
let outcome = match result {
Ok(value) => value,
Err(_) => return,
};
assert!(outcome.is_changed());
assert_eq!(outcome.revision().as_str(), "cccc");
assert!(outcome.snapshot().is_some());
return;
}

138
deltas/0.0.2/alpha.5.md Normal file
View File

@@ -0,0 +1,138 @@
<!-- file: deltas/0.0.2/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.5 — cas d'usage partagé de synchronisation
## Statut
À appliquer après commit/push du history `0.0.2-alpha.4.fix.1` `PASS`.
## Scope
Cette tranche matérialise `knowledge-app-lib` comme owner de l'orchestration partagée de synchronisation de lecture. Elle compose les contrats Git et sync déjà prouvés sans introduire de stockage, scheduler, forge ou runtime réseau.
Le cas d'usage :
```text
RepositorySyncSignal
-> GitRepository::refresh
-> GitRepository::resolve_revision
-> comparaison previous_revision
-> Unchanged si identique
-> GitRepository::prepare_snapshot si changement
-> Changed { revision, snapshot }
```
La cause du signal n'altère pas le chemin de vérité Git. `Periodic` est prouvée comme une autre origine du même appel, sans scheduler concret.
## Règle de formatage
La gate applique le formatter avant les audits Rust :
```bash
cargo fmt --all
cargo fmt --all -- --check
```
Les audits du code Rust viennent seulement ensuite. Cette règle est maintenant possédée localement par `docs/rules/400-VALIDATION.md` et `docs/rules/510-RUST_CARGO.md`.
## Gate opérateur
```bash
test "$(cat VERSION)" = '0.0.2-alpha.5'
grep -F 'version = "0.0.2-alpha.5"' Cargo.toml
grep -A2 '^## Statut$' history/0.0.2/alpha.4.fix.1.md | grep -Fx 'PASS'
git diff --check
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
cargo fmt --all
cargo fmt --all -- --check
python3 -B scripts/audit_rust_test_layout.py crates
python3 -B scripts/audit_rust_blank_lines.py crates
python3 -B scripts/audit_rust_item_spacing.py crates
python3 -B scripts/audit_rust_module_order.py crates
python3 -B scripts/audit_rust_trait_import_blocks.py crates
python3 -B scripts/audit_rust_reexport_blocks.py crates
python3 -B scripts/audit_rust_crate_root_facades.py crates
python3 -B scripts/audit_rust_export_completeness.py --root . --summary-only
cargo metadata --format-version 1 --no-deps > /tmp/sasedev-knowledge-0.0.2-alpha.5-metadata.json
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p knowledge-app-lib --all-targets --all-features
cargo test -p knowledge-git-api --all-targets --all-features
cargo test -p knowledge-git-lib --all-targets --all-features
cargo test -p knowledge-sync-api --all-targets --all-features
cargo test --workspace --all-targets --all-features
python3 - <<'PYGATE'
import json
from pathlib import Path
metadata = json.loads(Path('/tmp/sasedev-knowledge-0.0.2-alpha.5-metadata.json').read_text(encoding='utf-8'))
expected = {
'knowledge-app-lib',
'knowledge-domain-lib',
'knowledge-git-api',
'knowledge-git-lib',
'knowledge-sync-api',
'knowledge-web-lib',
'knowledge-pgr-server',
'knowledge-howtos-server',
'knowledge-snippets-server',
}
assert {package['name'] for package in metadata['packages']} == expected
assert len(metadata['workspace_members']) == 9
manifest = Path('crates/knowledge-app-lib/Cargo.toml').read_text(encoding='utf-8')
assert 'knowledge-git-api.workspace = true' in manifest
assert 'knowledge-sync-api.workspace = true' in manifest
assert '[dev-dependencies]' in manifest
assert 'knowledge-domain-lib.workspace = true' in manifest
source = Path('crates/knowledge-app-lib/src/repository_sync.rs').read_text(encoding='utf-8')
for phrase in (
'RepositorySyncOutcome',
'Unchanged',
'Changed',
'GitRepository::refresh',
'GitRepository::resolve_revision',
'GitRepository::prepare_snapshot',
'previous_revision',
):
assert phrase in source, phrase
for forbidden in ('postgres', 'gitea', 'github', 'gitlab', 'actix', 'tokio', 'scheduler'):
assert forbidden not in source.lower(), forbidden
rule400 = Path('docs/rules/400-VALIDATION.md').read_text(encoding='utf-8')
rule510 = Path('docs/rules/510-RUST_CARGO.md').read_text(encoding='utf-8')
assert rule400.index('cargo fmt --all') < rule400.index('audits Rust structurels applicables')
assert rule510.index('cargo fmt --all') < rule510.index('audit_rust_test_layout.py')
print('Knowledge 0.0.2-alpha.5 sync/format-order audit: clean')
PYGATE
test -f Cargo.lock
git check-ignore -q Cargo.lock
if git ls-files --error-unmatch Cargo.lock >/dev/null 2>&1; then
echo 'Cargo.lock must remain untracked for Knowledge' >&2
exit 1
fi
test -z "$(git diff --name-only -- Web)"
test ! -e crates/knowledge-forge-gitea-lib
test ! -e crates/knowledge-store-postgres-lib
git add -A
git diff --cached --check
git status --short
```
## Transition
Un `PASS` autorise uniquement `0.0.2-beta.1`. Un échec requis produit un history factuel et un `alpha.5.fix.N` ou un REPLAN selon la nature du défaut.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/001-PROJECT_PROFILE.md --> <!-- file: docs/architecture/001-PROJECT_PROFILE.md -->
<!-- version: 14 --> <!-- version: 15 -->
# Profil du projet Knowledge # Profil du projet Knowledge
@@ -119,6 +119,7 @@ Les packages matérialisés sont :
```text ```text
knowledge-domain-lib types métier stables de famille/source knowledge-domain-lib types métier stables de famille/source
knowledge-app-lib cas d'usage applicatifs partagés, dont synchronisation de lecture
knowledge-git-api contrat passif GitRepository provider-neutral knowledge-git-api contrat passif GitRepository provider-neutral
knowledge-git-lib implémentation Git générique + mirror/refresh/resolve/snapshot + état local contrôlé knowledge-git-lib implémentation Git générique + mirror/refresh/resolve/snapshot + état local contrôlé
knowledge-sync-api contrat passif RepositoryEventSource knowledge-sync-api contrat passif RepositoryEventSource
@@ -128,7 +129,7 @@ knowledge-howtos-server launcher HOWTOs mince
knowledge-snippets-server launcher snippets mince knowledge-snippets-server launcher snippets mince
``` ```
`knowledge-git-lib` devient réelle en `0.0.2-alpha.2` puis implémente le chemin de lecture Git dans `alpha.3`. `knowledge-app-lib` reste seulement l'owner candidat du cas d'usage de synchronisation partagé et ne sera matérialisée que si l'orchestration réelle démontre cette responsabilité. `knowledge-git-lib` devient réelle en `0.0.2-alpha.2` puis implémente le chemin de lecture Git dans `alpha.3`. `knowledge-app-lib` devient réelle en `0.0.2-alpha.5` : l'orchestration refresh / résolution / comparaison / snapshot confirme une responsabilité application partagée distincte du backend Git et des launchers.
Les responsabilités suivantes restent candidates et non matérialisées : Les responsabilités suivantes restent candidates et non matérialisées :

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md --> <!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md -->
<!-- version: 12 --> <!-- version: 13 -->
# Architecture de fondation Knowledge # Architecture de fondation Knowledge
@@ -226,7 +226,7 @@ Un webhook peut être perdu ou dupliqué. Le commit Git résolu reste l'identit
### Ownership de `0.0.2` ### Ownership de `0.0.2`
La synchronisation partagée est une responsabilité de couche application, distincte du backend Git et des producteurs de signaux. La candidate existante `knowledge-app-lib` devient l'owner naturel si l'orchestration réelle confirme qu'une crate partagée est nécessaire ; elle n'est pas créée en `alpha.1` comme placeholder. La synchronisation partagée est une responsabilité de couche application, distincte du backend Git et des producteurs de signaux. `0.0.2-alpha.5` confirme cette responsabilité et matérialise `knowledge-app-lib` comme owner du cas d'usage provider-neutral ; les launchers n'ont pas à dupliquer cette orchestration.
Sans PostgreSQL dans cette release, la dernière révision connue n'est pas stockée dans un fichier ad hoc caché. Le cas d'usage reçoit `previous_revision` de l'appelant et retourne explicitement la révision observée ainsi qu'un résultat `Changed` ou `Unchanged`. La future persistance pourra remplacer cet état appelant sans modifier la frontière Git. Sans PostgreSQL dans cette release, la dernière révision connue n'est pas stockée dans un fichier ad hoc caché. Le cas d'usage reçoit `previous_revision` de l'appelant et retourne explicitement la révision observée ainsi qu'un résultat `Changed` ou `Unchanged`. La future persistance pourra remplacer cet état appelant sans modifier la frontière Git.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md --> <!-- file: docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md -->
<!-- version: 9 --> <!-- version: 10 -->
# Plan 0.0.2 — Git générique et synchronisation de lecture # Plan 0.0.2 — Git générique et synchronisation de lecture
@@ -186,7 +186,7 @@ La revue de tranche a déclenché un REPLAN explicite : l'autonomie normative ap
### alpha.4 — autonomie normative et structure interne des crates ### alpha.4 — autonomie normative et structure interne des crates
Statut opérateur initial : **FAIL**. Statut opérateur initial : **FAIL**. `alpha.4.fix.1` : **PASS**. Tranche fermée.
La matérialisation normative, les audits locaux, les façades crate-root, rustfmt et les métadonnées sont propres. La compilation échoue uniquement parce que `GitReference` et `GitRevision`, déplacés dans leurs modules propriétaires, tentent encore de construire leurs tuple structs privés via les réexports crate-root. La matérialisation normative, les audits locaux, les façades crate-root, rustfmt et les métadonnées sont propres. La compilation échoue uniquement parce que `GitReference` et `GitRevision`, déplacés dans leurs modules propriétaires, tentent encore de construire leurs tuple structs privés via les réexports crate-root.
@@ -218,15 +218,19 @@ Gate attendue : audits Markdown locaux, audit d'autonomie, audits Rust incluant
### alpha.5 — cas d'usage de synchronisation ### alpha.5 — cas d'usage de synchronisation
Composer les primitives Git en un cas d'usage réellement consommable : La matérialisation de l'orchestration confirme un ownership application partagé : `knowledge-app-lib` devient justifiée et doit éviter que les trois launchers recomposent chacun le même flux.
Scope :
- créer `knowledge-app-lib` comme façade bibliothèque mince de cas d'usage partagés ;
- enchaîner refresh, résolution, comparaison avec `previous_revision` et snapshot ; - enchaîner refresh, résolution, comparaison avec `previous_revision` et snapshot ;
- retourner explicitement un résultat `Unchanged` ou `Changed` avec la révision observée ; - retourner explicitement `RepositorySyncOutcome::Unchanged` ou `RepositorySyncOutcome::Changed` avec la révision observée ;
- rendre la synchronisation explicite utilisable par un appelant ; - préparer le snapshot uniquement lorsque la révision diffère de celle fournie par l'appelant ;
- vérifier que `RepositorySyncTrigger::Periodic` peut emprunter la même voie sans matérialiser un scheduler artificiel ; - consommer `RepositorySyncSignal` sans donner de sémantique autoritaire à sa cause ;
- garder la persistance de dernière révision hors scope. - prouver qu'une cause `Periodic` emprunte exactement le même cas d'usage qu'une cause explicite sans matérialiser de scheduler ;
- garder la persistance de dernière révision, PostgreSQL, worker réseau, forge et publication Git hors scope.
`knowledge-app-lib` n'est créée que si cette orchestration possède effectivement un ownership partagé et évite une duplication réelle. Sinon la tranche reste dans les crates déjà justifiées. La gate Rust applique désormais explicitement `cargo fmt --all`, puis `cargo fmt --all -- --check`, avant les audits du code Rust. Cette normalisation précède les contrôles structurels afin que les audits observent l'état réellement formaté.
### beta.1 — réconciliation et revue d'horizon ### beta.1 — réconciliation et revue d'horizon

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/400-VALIDATION.md --> <!-- file: docs/rules/400-VALIDATION.md -->
<!-- version: 1 --> <!-- version: 2 -->
# Validation locale Knowledge # Validation locale Knowledge
@@ -79,12 +79,15 @@ Lorsqu'un audit lexical rencontre un cas que son modèle ne sait pas interpréte
## Ordre normal ## Ordre normal
Pour une tranche Rust transverse, la séquence habituelle est : Pour une tranche Rust transverse, le formatter officiel normalise d'abord les sources. `cargo fmt --all` est une étape mutante volontaire et doit être exécutée avant tout audit du code Rust ; `cargo fmt --all -- --check` confirme immédiatement l'état obtenu.
La séquence habituelle est :
```text ```text
format cargo fmt --all
-> audits structurels applicables -> cargo fmt --all -- --check
-> cargo check / metadata utile -> audits Rust structurels applicables
-> cargo metadata / cargo check utiles
-> clippy strict -> clippy strict
-> tests ciblés -> tests ciblés
-> tests workspace si justifiés -> tests workspace si justifiés
@@ -92,6 +95,8 @@ format
-> git diff --cached --check / status -> git diff --cached --check / status
``` ```
Les audits Markdown ou autres contrôles documentaires peuvent être exécutés avant ou après le formatage Rust puisqu'ils ne portent pas sur les sources Rust.
Pour une tranche Web, les preuves npm/typecheck/build sont ajoutées lorsque `Web/` ou son contrat d'intégration est touché. Une tranche documentaire ou Rust sans diff Web ne rejoue pas automatiquement le frontend. Pour une tranche Web, les preuves npm/typecheck/build sont ajoutées lorsque `Web/` ou son contrat d'intégration est touché. Une tranche documentaire ou Rust sans diff Web ne rejoue pas automatiquement le frontend.
## Régression et dette externe ## Régression et dette externe

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/510-RUST_CARGO.md --> <!-- file: docs/rules/510-RUST_CARGO.md -->
<!-- version: 1 --> <!-- version: 2 -->
# Rust / Cargo local Knowledge # Rust / Cargo local Knowledge
@@ -57,6 +57,8 @@ Les tests ne rendent pas l'API produit plus visible uniquement pour accéder à
## Formatage et audits ## Formatage et audits
Le formatter est appliqué, pas seulement interrogé : `cargo fmt --all` précède obligatoirement les audits du code Rust, puis `cargo fmt --all -- --check` vérifie immédiatement le résultat.
La séquence normale d'un changement Rust pertinent inclut : La séquence normale d'un changement Rust pertinent inclut :
```bash ```bash

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/001-VALIDATION_MATRIX.md --> <!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
<!-- version: 26 --> <!-- version: 27 -->
# Matrice de validation Knowledge # Matrice de validation Knowledge
@@ -700,3 +700,37 @@ Le correctif doit prouver :
- `Cargo.lock` ignoré/non suivi et `git diff --cached --check` propre. - `Cargo.lock` ignoré/non suivi et `git diff --cached --check` propre.
Le `PASS` de `alpha.4.fix.1` ferme `alpha.4`, termine l'adoption PGR `v0.1.3` comme migration ponctuelle et autorise uniquement la préparation de `0.0.2-alpha.5`. Le `PASS` de `alpha.4.fix.1` ferme `alpha.4`, termine l'adoption PGR `v0.1.3` comme migration ponctuelle et autorise uniquement la préparation de `0.0.2-alpha.5`.
## Ordre canonique des validations Rust à partir de `0.0.2-alpha.5`
Toute gate qui audite du code Rust applique d'abord le formatter :
```bash
cargo fmt --all
cargo fmt --all -- --check
```
Les audits Rust sont exécutés seulement après ces deux commandes. Viennent ensuite `cargo metadata`/`cargo check`, Clippy et les tests requis par le scope. Les audits Markdown peuvent être placés avant ou après cette séquence puisqu'ils ne lisent pas la forme du code Rust.
## Gate de `0.0.2-alpha.5`
La tranche de cas d'usage de synchronisation doit prouver :
- `VERSION = 0.0.2-alpha.5` et version workspace identique ;
- history `history/0.0.2/alpha.4.fix.1.md` présent avec statut `PASS` et committé avant application ;
- neuf packages Cargo exactement, avec `knowledge-app-lib` comme nouvel owner application réel ;
- `knowledge-app-lib` dépendant seulement de `knowledge-git-api` et `knowledge-sync-api` en production ;
- `src/lib.rs` de `knowledge-app-lib` conforme au contrat de façade crate-root ;
- cas d'usage public enchaînant refresh, résolution, comparaison de `previous_revision` puis snapshot seulement si changement ;
- résultat explicite `Changed` / `Unchanged` exposant toujours la révision observée et le snapshot uniquement en cas de changement ;
- absence de persistance implicite de la dernière révision ;
- cause `Periodic` prouvée sur le même chemin que la synchronisation explicite, sans scheduler concret ;
- aucune dépendance forge, PostgreSQL, Actix, worker réseau ou écriture Git dans `knowledge-app-lib` ;
- `cargo fmt --all` exécuté avant tout audit Rust ;
- `cargo fmt --all -- --check` exécuté immédiatement après le formatage et avant tout audit Rust ;
- audits Rust locaux propres, y compris façade crate-root et complétude d'exports ;
- `cargo metadata`, `cargo check --workspace`, Clippy strict, tests ciblés `knowledge-app-lib`/Git et tests workspace propres ;
- `Web/` sans diff et `Cargo.lock` ignoré/non suivi ;
- `git diff --cached --check` propre avant commit.
Le `PASS` d'`alpha.5` ferme le scope fonctionnel alpha de `0.0.2` et autorise uniquement la préparation de `beta.1` de réconciliation et revue d'horizon.

158
history/0.0.2/alpha.5.md Normal file
View File

@@ -0,0 +1,158 @@
<!-- file: history/0.0.2/alpha.5.md -->
<!-- version: 1 -->
# History 0.0.2-alpha.5 — cas d'usage partagé de synchronisation
## Statut
PASS
La gate opérateur de `0.0.2-alpha.5` exécutée le `2026-09-28` est propre. La tranche matérialise `knowledge-app-lib` comme owner du cas d'usage partagé de synchronisation de lecture et rend durable l'ordre de validation Rust `cargo fmt --all` puis `cargo fmt --all -- --check` avant les audits du code Rust.
## Baseline opérateur
`alpha.4.fix.1` `PASS` a été historisé, committé et poussé avant application de `alpha.5` :
```text
history/0.0.2/alpha.4.fix.1.md PASS
commit 1fe39df
message 0.0.2-alpha.4.fix.1
branch master
push origin/master PASS
workspace après push propre
```
Le push observé a avancé `origin/master` de `3f8c795` à `1fe39df`.
## Version, documentation et formatage
Les contrôles passent :
```text
VERSION 0.0.2-alpha.5
Cargo workspace version 0.0.2-alpha.5
git diff --check PASS
Markdown header audit clean (84 file(s))
Markdown link audit clean (71 local link(s), 84 file(s))
Markdown table audit clean (4 table(s), 84 file(s))
cargo fmt --all PASS
cargo fmt --all -- --check PASS
```
Le formatter est exécuté avant les audits Rust, conformément au contrat local désormais possédé par Knowledge.
## Audits Rust
Après formatage, les audits Rust passent :
```text
Rust test-layout audit: clean (9 crate(s))
Rust blank-line audit: clean (32 file(s))
Rust item-spacing audit: clean (32 file(s))
Rust module-order audit: clean (32 file(s))
Rust trait-import-block audit: clean (32 file(s))
Rust re-export-block audit: clean (32 file(s))
Rust crate-root facade audit: clean (6 crate root(s))
Rust export completeness audit: 0 candidate(s) across 9 package(s)
```
## Compilation et Clippy
Les commandes suivantes passent :
```text
cargo metadata --format-version 1 --no-deps PASS
cargo check --workspace PASS
cargo clippy --workspace --all-targets --all-features
-- -D warnings PASS
```
Les neuf packages attendus sont détectés, dont le nouveau `knowledge-app-lib`.
## Cas d'usage de synchronisation
`knowledge-app-lib` compose les contrats existants sans introduire de persistance, de scheduler ou de forge :
```text
RepositorySyncSignal
-> GitRepository::refresh
-> GitRepository::resolve_revision
-> comparaison previous_revision
-> RepositorySyncOutcome::Unchanged
ou
-> GitRepository::prepare_snapshot
-> RepositorySyncOutcome::Changed
```
Les trois tests ciblés passent :
```text
changed_revision_prepares_snapshot_and_returns_observed_revision PASS
unchanged_revision_does_not_prepare_snapshot PASS
periodic_signal_uses_the_same_reconciliation_path PASS
```
La cause `Periodic` emprunte donc le même cas d'usage que la synchronisation explicite sans matérialiser de scheduler concret.
## Tests ciblés et workspace
Les suites ciblées passent :
```text
knowledge-app-lib 3 PASS
knowledge-git-api 1 PASS
knowledge-git-lib 8 unit PASS + 2 integration PASS
knowledge-sync-api 1 PASS
```
La suite workspace passe intégralement :
```text
knowledge-app-lib 3 PASS
knowledge-domain-lib 3 PASS
knowledge-git-api 1 PASS
knowledge-git-lib 8 unit PASS + 2 integration PASS
knowledge-sync-api 1 PASS
knowledge-web-lib 4 PASS
launchers 0 test chacun
```
Les deux tests d'intégration Git réels continuent de prouver refresh, résolution, snapshots, référence invalide et snapshot sale.
## Contrôles structurels et frontières
L'audit spécifique passe :
```text
Knowledge 0.0.2-alpha.5 sync/format-order audit: clean
```
Il confirme notamment :
- neuf packages Cargo exactement ;
- `knowledge-app-lib` dépend uniquement de `knowledge-git-api` et `knowledge-sync-api` en production ;
- `knowledge-domain-lib` reste uniquement une dépendance de test pour cette crate ;
- `Changed` / `Unchanged`, `previous_revision`, refresh, résolution et snapshot sont matérialisés ;
- aucune dépendance PostgreSQL, Gitea/GitHub/GitLab, Actix, Tokio ou scheduler dans le cas d'usage ;
- `cargo fmt --all` précède les audits Rust dans les owners locaux de validation.
`Cargo.lock` est présent localement, ignoré et non suivi. `Web/` reste sans diff. Aucun adapter forge ni store PostgreSQL n'est créé.
Après staging, `git diff --cached --check` passe.
## Décision
`0.0.2-alpha.5` est `PASS`.
Le scope fonctionnel alpha de `0.0.2` est fermé. La transition autorisée est :
```text
appliquer ce history
-> git add / diff --cached --check / status
-> commit exact "0.0.2-alpha.5"
-> push origin master
-> vérifier le workspace propre
-> appliquer seulement ensuite 0.0.2-beta.1
```
`beta.1` doit rester une tranche de réconciliation, stabilisation et revue d'horizon sans grande fonctionnalité nouvelle.