0.0.2-alpha.2
This commit is contained in:
324
deltas/0.0.2/alpha.2.md
Normal file
324
deltas/0.0.2/alpha.2.md
Normal file
@@ -0,0 +1,324 @@
|
||||
<!-- file: deltas/0.0.2/alpha.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.0.2-alpha.2 — contrats minimaux et backend process Git
|
||||
|
||||
## Base requise
|
||||
|
||||
Partir de `0.0.2-alpha.1.fix.1` après application de son history `PASS`, commit et push :
|
||||
|
||||
```text
|
||||
history/0.0.2/alpha.1.md FAIL
|
||||
history/0.0.2/alpha.1.fix.1.md PASS
|
||||
```
|
||||
|
||||
Le workspace doit être propre avant application du présent delta.
|
||||
|
||||
La version devient :
|
||||
|
||||
```text
|
||||
0.0.2-alpha.2
|
||||
```
|
||||
|
||||
## Objet
|
||||
|
||||
Matérialiser la première responsabilité runtime Git réelle sans anticiper la tranche suivante :
|
||||
|
||||
- créer `knowledge-git-lib` comme crate d'implémentation réutilisable ;
|
||||
- posséder une racine d'état explicitement fournie au backend ;
|
||||
- posséder la configuration physique d'une source locale ou remote ;
|
||||
- dériver une `source-key` sûre sans interpoler directement `SourceId` ou URL dans le filesystem ;
|
||||
- encapsuler `std::process::Command` derrière un runner interne testable, sans shell ;
|
||||
- préparer les répertoires `hooks-disabled/`, `repositories/` et `snapshots/` ;
|
||||
- initialiser un mirror avec `git clone --mirror`, et `--no-local` pour une source locale ;
|
||||
- inspecter un mirror existant comme repository bare avant réutilisation ;
|
||||
- ne pas supprimer/recréer silencieusement un mirror invalide ;
|
||||
- ne pas exposer URL, arguments, stderr ou credentials dans les erreurs publiques du runner.
|
||||
|
||||
`refresh`, résolution vers commit et snapshot/worktree fonctionnel restent réservés à `alpha.3`.
|
||||
|
||||
## Scope
|
||||
|
||||
ADD :
|
||||
|
||||
```text
|
||||
crates/knowledge-git-lib/Cargo.toml
|
||||
crates/knowledge-git-lib/src/backend.rs
|
||||
crates/knowledge-git-lib/src/error.rs
|
||||
crates/knowledge-git-lib/src/lib.rs
|
||||
crates/knowledge-git-lib/unit_tests/backend.rs
|
||||
deltas/0.0.2/alpha.2.md
|
||||
```
|
||||
|
||||
REPLACE :
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
RULES.md
|
||||
VERSION
|
||||
docs/architecture/001-PROJECT_PROFILE.md
|
||||
docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
|
||||
docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md
|
||||
docs/validation/001-VALIDATION_MATRIX.md
|
||||
```
|
||||
|
||||
DELETE : aucun.
|
||||
|
||||
Le history `history/0.0.2/alpha.1.fix.1.md` appartient à la base requise mais n'est pas inclus dans ce delta.
|
||||
|
||||
Aucun fichier sous `Web/` n'est modifié.
|
||||
|
||||
## Contrat de `knowledge-git-lib`
|
||||
|
||||
La crate dépend uniquement de `knowledge-domain-lib` dans cette tranche.
|
||||
|
||||
Elle expose :
|
||||
|
||||
```text
|
||||
GitBackend
|
||||
GitBackendConfig
|
||||
GitSourceConfig
|
||||
GitSourceKind
|
||||
GitSourceKey
|
||||
GitMirror
|
||||
GitMirrorStatus
|
||||
GitBackendError
|
||||
GitOperation
|
||||
```
|
||||
|
||||
`knowledge-git-api` reste inchangée : son trait `GitRepository` possède déjà `refresh` et `resolve_revision`, qui ne doivent pas être implémentés artificiellement avant la tranche qui matérialise ces comportements.
|
||||
|
||||
La dépendance et l'implémentation explicite de ce trait seront introduites lorsque le backend possédera effectivement les opérations requises.
|
||||
|
||||
## Layout d'état
|
||||
|
||||
Une configuration valide possède obligatoirement une racine d'état non vide :
|
||||
|
||||
```text
|
||||
<git-state-root>/
|
||||
hooks-disabled/
|
||||
repositories/
|
||||
<source-key>.git/
|
||||
snapshots/
|
||||
```
|
||||
|
||||
Le répertoire `snapshots/` est réservé dès maintenant par le layout mais aucun snapshot n'est créé dans `alpha.2`.
|
||||
|
||||
La `source-key` est obtenue par encodage hexadécimal déterministe des octets UTF-8 du `SourceId`, préfixé par `source-`. Cette stratégie évite les collisions entre octets distincts et interdit qu'un séparateur de chemin, `..`, une URL ou un credential provenant de l'entrée logique devienne un composant de chemin brut.
|
||||
|
||||
## Runner Git contrôlé
|
||||
|
||||
Le runner système :
|
||||
|
||||
- utilise `std::process::Command` directement ;
|
||||
- passe chaque argument séparément ;
|
||||
- pose `GIT_TERMINAL_PROMPT=0` ;
|
||||
- retire les variables `GIT_*` qui peuvent rediriger implicitement repository, worktree, index ou object database ;
|
||||
- force `core.hooksPath` vers le répertoire vide contrôlé via l'environnement de configuration Git ;
|
||||
- transforme un échec de spawn ou exit non nul en erreur récupérable ;
|
||||
- ne copie jamais arguments, source, stdout/stderr ou credentials dans l'erreur publique.
|
||||
|
||||
Les sources locales utilisent :
|
||||
|
||||
```text
|
||||
git clone --mirror --no-local -- <source> <mirror>
|
||||
```
|
||||
|
||||
Les sources remote utilisent :
|
||||
|
||||
```text
|
||||
git clone --mirror -- <source> <mirror>
|
||||
```
|
||||
|
||||
Un mirror existant est inspecté avec :
|
||||
|
||||
```text
|
||||
git --git-dir <mirror> rev-parse --is-bare-repository
|
||||
```
|
||||
|
||||
Une réponse différente de `true` produit une erreur sans suppression destructive.
|
||||
|
||||
## Tests de la tranche
|
||||
|
||||
Les tests unitaires de `knowledge-git-lib` utilisent un runner enregistré injecté uniquement sous `cfg(test)` pour vérifier sans réseau :
|
||||
|
||||
- rejet des chemins de configuration vides ;
|
||||
- dérivation sûre de `source-key` ;
|
||||
- arguments exacts de clone local ;
|
||||
- absence de `--no-local` pour un remote ;
|
||||
- redaction des erreurs contenant potentiellement une URL avec credentials ;
|
||||
- inspection d'un mirror existant sans clone ;
|
||||
- refus d'un mirror invalide sans suppression.
|
||||
|
||||
Les tests réels sur repositories Git temporaires appartiennent à `alpha.3`, avec refresh, résolution et snapshot.
|
||||
|
||||
## Gate opérateur
|
||||
|
||||
Après application du history `alpha.1.fix.1`, commit/push de cet état, puis application du présent delta :
|
||||
|
||||
```bash
|
||||
test "$(cat VERSION)" = '0.0.2-alpha.2'
|
||||
grep -F 'version = "0.0.2-alpha.2"' Cargo.toml
|
||||
grep -A2 '^## Statut$' history/0.0.2/alpha.1.fix.1.md | grep -Fx 'PASS'
|
||||
|
||||
git diff --check
|
||||
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import re
|
||||
import tomllib
|
||||
|
||||
required = (
|
||||
"crates/knowledge-git-lib/Cargo.toml",
|
||||
"crates/knowledge-git-lib/src/backend.rs",
|
||||
"crates/knowledge-git-lib/src/error.rs",
|
||||
"crates/knowledge-git-lib/src/lib.rs",
|
||||
"crates/knowledge-git-lib/unit_tests/backend.rs",
|
||||
"deltas/0.0.2/alpha.2.md",
|
||||
)
|
||||
for value in required:
|
||||
assert Path(value).is_file(), value
|
||||
|
||||
root = tomllib.loads(Path("Cargo.toml").read_text(encoding="utf-8"))
|
||||
manifest = tomllib.loads(Path("crates/knowledge-git-lib/Cargo.toml").read_text(encoding="utf-8"))
|
||||
assert "crates/knowledge-git-lib" in root["workspace"]["members"]
|
||||
assert set(manifest["dependencies"]) == {"knowledge-domain-lib"}, manifest["dependencies"]
|
||||
|
||||
backend = Path("crates/knowledge-git-lib/src/backend.rs").read_text(encoding="utf-8")
|
||||
error = Path("crates/knowledge-git-lib/src/error.rs").read_text(encoding="utf-8")
|
||||
for phrase in (
|
||||
"std::process::Command::new",
|
||||
'command.env("GIT_TERMINAL_PROMPT", "0")',
|
||||
'command.env_remove("GIT_DIR")',
|
||||
'command.env_remove("GIT_WORK_TREE")',
|
||||
'command.env_remove("GIT_INDEX_FILE")',
|
||||
'command.env_remove("GIT_OBJECT_DIRECTORY")',
|
||||
'command.env_remove("GIT_ALTERNATE_OBJECT_DIRECTORIES")',
|
||||
'command.env("GIT_CONFIG_KEY_0", "core.hooksPath")',
|
||||
'std::ffi::OsString::from("--mirror")',
|
||||
'std::ffi::OsString::from("--no-local")',
|
||||
'std::ffi::OsString::from("--")',
|
||||
'std::ffi::OsString::from("--is-bare-repository")',
|
||||
):
|
||||
assert phrase in backend, phrase
|
||||
|
||||
for forbidden in (
|
||||
'Command::new("sh")',
|
||||
'Command::new("bash")',
|
||||
'Command::new("cmd")',
|
||||
'Command::new("powershell")',
|
||||
"stderr: String",
|
||||
"arguments: Vec<String>",
|
||||
):
|
||||
assert forbidden not in backend + error, forbidden
|
||||
|
||||
for forbidden in ("refresh(", "resolve_revision(", "worktree add", "knowledge-app-lib"):
|
||||
assert forbidden not in backend, forbidden
|
||||
|
||||
for path in Path("crates/knowledge-git-lib").rglob("*.rs"):
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for forbidden in ("unwrap()", "expect(", "panic!("):
|
||||
assert forbidden not in text, (path, forbidden)
|
||||
|
||||
for path in Path(".").rglob("*.md"):
|
||||
if ".git" in path.parts:
|
||||
continue
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
assert lines[0] == f"<!-- file: {path.as_posix()} -->", path
|
||||
assert re.fullmatch(r"<!-- version: [1-9][0-9]* -->", lines[1]), path
|
||||
|
||||
print("Knowledge 0.0.2-alpha.2 structural audit: clean")
|
||||
PY
|
||||
|
||||
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_export_completeness.py --root . --summary-only
|
||||
|
||||
cargo fmt --all -- --check
|
||||
cargo metadata --format-version 1 --no-deps > /tmp/sasedev-knowledge-0.0.2-alpha.2-metadata.json
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p knowledge-git-lib --all-targets --all-features
|
||||
cargo test --workspace --all-targets --all-features
|
||||
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
metadata = json.loads(Path("/tmp/sasedev-knowledge-0.0.2-alpha.2-metadata.json").read_text(encoding="utf-8"))
|
||||
packages = {package["name"] for package in metadata["packages"]}
|
||||
expected = {
|
||||
"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 packages == expected, packages
|
||||
assert len(metadata["workspace_members"]) == 8, metadata["workspace_members"]
|
||||
print("Knowledge 0.0.2-alpha.2 Cargo metadata audit: clean")
|
||||
PY
|
||||
|
||||
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 -z "$(git diff --name-only -- crates/knowledge-git-api crates/knowledge-sync-api)"
|
||||
test ! -e crates/knowledge-app-lib
|
||||
test ! -e crates/knowledge-forge-gitea-lib
|
||||
test ! -e crates/knowledge-store-postgres-lib
|
||||
|
||||
git add -A
|
||||
git diff --cached --check
|
||||
git status --short
|
||||
```
|
||||
|
||||
## Résultats attendus
|
||||
|
||||
La gate doit notamment produire :
|
||||
|
||||
```text
|
||||
Knowledge 0.0.2-alpha.2 structural audit: clean
|
||||
Rust test-layout audit: clean (8 crate(s))
|
||||
Rust export completeness audit: 0 candidate(s) across 8 package(s)
|
||||
Knowledge 0.0.2-alpha.2 Cargo metadata audit: clean
|
||||
```
|
||||
|
||||
La suite ciblée `knowledge-git-lib` doit exécuter `7` tests unitaires `PASS`.
|
||||
|
||||
`git diff --name-only -- Web` et le diff ciblant les deux crates `-api` doivent rester vides.
|
||||
|
||||
Le staging final doit contenir uniquement le scope annoncé par ce delta. Aucun `history/0.0.2/alpha.2.md` ne doit exister avant réception des résultats opérateur.
|
||||
|
||||
## Revue opérateur complémentaire
|
||||
|
||||
Vérifier que :
|
||||
|
||||
- `knowledge-git-lib` possède bien une responsabilité d'implémentation et n'est pas une crate placeholder ;
|
||||
- le runner ne passe jamais par un shell ;
|
||||
- les erreurs process restent exploitables sans recopier des informations sensibles ;
|
||||
- le layout généré reste reconstructible et distinct du stockage métier ;
|
||||
- `knowledge-git-api` n'est pas artificiellement étendue pour des opérations qui n'existent pas encore ;
|
||||
- `alpha.3` reste propriétaire du refresh, de la résolution et du snapshot réel.
|
||||
|
||||
## Transition
|
||||
|
||||
### PASS
|
||||
|
||||
Produire `history/0.0.2/alpha.2.md`, appliquer ce history, committer/pousser `0.0.2-alpha.2`, puis seulement préparer `0.0.2-alpha.3`.
|
||||
|
||||
### FAIL / PARTIAL / BLOCKED
|
||||
|
||||
Conserver le résultat réel dans `history/0.0.2/alpha.2.md` et rester dans le scope `alpha.2` avec `alpha.2.fix.1` si nécessaire, sauf déclencheur de REPLAN explicitement satisfait.
|
||||
Reference in New Issue
Block a user