0.0.2-alpha.5
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
# file: Cargo.toml
|
||||
# version: 24
|
||||
# version: 25
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = [
|
||||
"crates/knowledge-domain-lib",
|
||||
"crates/knowledge-app-lib",
|
||||
"crates/knowledge-git-api",
|
||||
"crates/knowledge-git-lib",
|
||||
"crates/knowledge-sync-api",
|
||||
@@ -15,12 +16,13 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.0.2-alpha.4.fix.1"
|
||||
version = "0.0.2-alpha.5"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge"
|
||||
|
||||
[workspace.dependencies]
|
||||
knowledge-sync-api = { path = "crates/knowledge-sync-api" }
|
||||
knowledge-domain-lib = { path = "crates/knowledge-domain-lib" }
|
||||
knowledge-git-api = { path = "crates/knowledge-git-api" }
|
||||
knowledge-web-lib = { path = "crates/knowledge-web-lib" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 14 -->
|
||||
<!-- version: 15 -->
|
||||
|
||||
# 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).
|
||||
|
||||
`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
|
||||
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
|
||||
|
||||
19
crates/knowledge-app-lib/Cargo.toml
Normal file
19
crates/knowledge-app-lib/Cargo.toml
Normal 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
|
||||
14
crates/knowledge-app-lib/src/lib.rs
Normal file
14
crates/knowledge-app-lib/src/lib.rs
Normal 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;
|
||||
89
crates/knowledge-app-lib/src/repository_sync.rs
Normal file
89
crates/knowledge-app-lib/src/repository_sync.rs
Normal 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;
|
||||
121
crates/knowledge-app-lib/unit_tests/repository_sync.rs
Normal file
121
crates/knowledge-app-lib/unit_tests/repository_sync.rs
Normal 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
138
deltas/0.0.2/alpha.5.md
Normal 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.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/001-PROJECT_PROFILE.md -->
|
||||
<!-- version: 14 -->
|
||||
<!-- version: 15 -->
|
||||
|
||||
# Profil du projet Knowledge
|
||||
|
||||
@@ -119,6 +119,7 @@ Les packages matérialisés sont :
|
||||
|
||||
```text
|
||||
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-lib implémentation Git générique + mirror/refresh/resolve/snapshot + état local contrôlé
|
||||
knowledge-sync-api contrat passif RepositoryEventSource
|
||||
@@ -128,7 +129,7 @@ knowledge-howtos-server launcher HOWTOs 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 :
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md -->
|
||||
<!-- version: 12 -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# 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`
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- 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
|
||||
|
||||
@@ -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
|
||||
|
||||
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.
|
||||
|
||||
@@ -218,15 +218,19 @@ Gate attendue : audits Markdown locaux, audit d'autonomie, audits Rust incluant
|
||||
|
||||
### 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 ;
|
||||
- retourner explicitement un résultat `Unchanged` ou `Changed` avec la révision observée ;
|
||||
- rendre la synchronisation explicite utilisable par un appelant ;
|
||||
- vérifier que `RepositorySyncTrigger::Periodic` peut emprunter la même voie sans matérialiser un scheduler artificiel ;
|
||||
- garder la persistance de dernière révision hors scope.
|
||||
- retourner explicitement `RepositorySyncOutcome::Unchanged` ou `RepositorySyncOutcome::Changed` avec la révision observée ;
|
||||
- préparer le snapshot uniquement lorsque la révision diffère de celle fournie par l'appelant ;
|
||||
- consommer `RepositorySyncSignal` sans donner de sémantique autoritaire à sa cause ;
|
||||
- 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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/400-VALIDATION.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
format
|
||||
-> audits structurels applicables
|
||||
-> cargo check / metadata utile
|
||||
cargo fmt --all
|
||||
-> cargo fmt --all -- --check
|
||||
-> audits Rust structurels applicables
|
||||
-> cargo metadata / cargo check utiles
|
||||
-> clippy strict
|
||||
-> tests ciblés
|
||||
-> tests workspace si justifiés
|
||||
@@ -92,6 +95,8 @@ format
|
||||
-> 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.
|
||||
|
||||
## Régression et dette externe
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/510-RUST_CARGO.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# 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
|
||||
|
||||
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 :
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
||||
<!-- version: 26 -->
|
||||
<!-- version: 27 -->
|
||||
|
||||
# Matrice de validation Knowledge
|
||||
|
||||
@@ -700,3 +700,37 @@ Le correctif doit prouver :
|
||||
- `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`.
|
||||
|
||||
## 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
158
history/0.0.2/alpha.5.md
Normal 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.
|
||||
Reference in New Issue
Block a user