10 KiB
Delta 0.0.3-alpha.3 — worktree d'écriture et commit candidat
Baseline requise
Partir de 0.0.3-alpha.2 après application, commit et push de son history PASS.
La version devient :
0.0.3-alpha.3
Objet
Implémenter dans knowledge-git-lib la création locale réelle d'une révision candidate à partir d'une base Git explicite, sans mettre encore à jour de branche distante.
La tranche :
- ajoute un worktree d'écriture temporaire et déterministe sous la racine d'état du backend ;
- réutilise le mirror contrôlé du
SourceIdet exige uneGitRevisionde base sûre ; - applique exactement les mutations
Write/Deletedemandées ; - refuse toute cible ou tout parent filesystem qui est un symlink ;
- stage uniquement les chemins demandés puis vérifie que l'index contient exactement cet ensemble ;
- neutralise la configuration Git système/globale ambiante pertinente et conserve
core.hooksPathsous contrôle ; - crée le commit avec auteur et committer explicitement issus de
GitCommitIdentity,--no-verifyet--no-gpg-sign; - vérifie que le candidat a exactement la base demandée comme premier parent ;
- retient l'objet candidat sous
refs/knowledge/candidates/<revision>avant suppression du worktree ; - retire le worktree possédé après succès et tente une suppression forcée après une erreur survenue dans ce worktree ;
- refuse un worktree
candidatepréexistant au lieu de le supprimer silencieusement ; - ajoute des tests d'intégration Git réels pour le candidat et l'échappement par symlink.
alpha.3 ne met à jour aucun remote et n'implémente pas encore GitRepositoryWriter sur GitBackend, car ce trait exige également push_candidate. L'implémentation complète du trait et le compare-and-exchange distant restent réservés à alpha.4.
Scope des fichiers
REPLACE :
VERSION
Cargo.toml
README.md
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
docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
ADD :
crates/knowledge-git-lib/src/write.rs
crates/knowledge-git-lib/tests/git_write_candidate.rs
deltas/0.0.3/alpha.3.md
DELETE : aucun.
knowledge-git-api, knowledge-app-lib, Web/, CHANGELOG.md et ROADMAP.md ne sont pas modifiés.
Aucun history alpha.3 n'est inclus dans ce delta.
Contrat backend matérialisé
Le chemin local devient :
GitRevision de base
-> mirror contrôlé
-> write-worktrees/<source-key>/candidate
-> mutations confinées
-> git add limité aux chemins demandés
-> commit avec identité explicite
-> vérification HEAD / HEAD^1
-> refs/knowledge/candidates/<revision>
-> suppression du worktree temporaire
-> GitRevision candidate
La racine d'état contrôlée contient désormais également :
empty-global.gitconfig
write-worktrees/
empty-global.gitconfig neutralise la configuration utilisateur globale pour les commandes possédées par le backend ; GIT_CONFIG_NOSYSTEM=1 neutralise la configuration système. La configuration repository nécessaire au mirror reste disponible, tandis que core.hooksPath est forcé vers hooks-disabled.
Confinement filesystem
GitMutationPath fournit déjà le confinement lexical. alpha.3 ajoute le contrôle physique : avant toute écriture ou suppression, chaque composant existant du chemin sous le worktree est inspecté avec symlink_metadata.
Un symlink rencontré produit UnsafeMutationTarget. Une suppression d'une cible absente produit MutationTargetMissing. Les erreurs filesystem restent récupérables et ne contiennent pas le chemin ou le contenu sensible dans leur texte public.
Un worktree préexistant à l'emplacement contrôlé produit WriteWorktreeExists. Il n'est pas supprimé automatiquement.
Candidate et nettoyage
Une candidate n'est valide que si :
- les chemins réellement stagés correspondent exactement aux mutations demandées ;
- le commit est créé avec l'identité explicite de la requête ;
HEADest une révision Git sûre ;HEAD^1est exactement la base demandée ;- une référence interne
refs/knowledge/candidates/<revision>conserve l'objet avant retrait du worktree.
Le retrait normal n'utilise pas --force. Si une erreur survient après création du worktree possédé par l'opération, le backend utilise worktree remove --force pour retirer uniquement cet état temporaire connu. Un échec de nettoyage devient WriteCleanupFailed afin qu'un état inattendu ne soit pas masqué.
Gate opérateur
Exécuter depuis la racine du dépôt après application du delta :
test "$(cat VERSION)" = '0.0.3-alpha.3'
grep -F 'version = "0.0.3-alpha.3"' Cargo.toml
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.3-alpha.3-metadata.json
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p knowledge-git-lib --test git_read_path
cargo test -p knowledge-git-lib --test git_write_candidate
cargo test --workspace --all-targets --all-features
python3 - <<'PYGATE'
from pathlib import Path
history = Path('history/0.0.3/alpha.2.md').read_text(encoding='utf-8')
assert '\nPASS\n' in history
write = Path('crates/knowledge-git-lib/src/write.rs').read_text(encoding='utf-8')
backend = Path('crates/knowledge-git-lib/src/backend.rs').read_text(encoding='utf-8')
errors = Path('crates/knowledge-git-lib/src/error.rs').read_text(encoding='utf-8')
api = Path('crates/knowledge-git-api/src/write.rs').read_text(encoding='utf-8')
plan = Path('docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md').read_text(encoding='utf-8')
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
for required in (
'pub fn create_candidate(',
'symlink_metadata',
'CandidateMutationMismatch',
'GIT_AUTHOR_NAME',
'GIT_COMMITTER_NAME',
'--no-verify',
'--no-gpg-sign',
'HEAD^1',
'refs/knowledge/candidates/',
'RemoveWriteWorktree',
):
assert required in write, required
assert 'GIT_CONFIG_GLOBAL' in backend
assert 'GIT_CONFIG_NOSYSTEM' in backend
assert 'core.hooksPath' in backend
assert 'write_worktrees_path' in backend
assert 'empty_global_config_path' in backend
for required_error in (
'WriteWorktreeExists',
'UnsafeMutationTarget',
'MutationTargetMissing',
'MutationFilesystemFailed',
'CandidateMutationMismatch',
'InvalidCandidate',
'WriteCleanupFailed',
):
assert required_error in errors, required_error
assert 'trait GitRepositoryWriter' in api
assert 'fn create_candidate(' in api
assert 'fn push_candidate(' in api
assert 'impl knowledge_git_api::GitRepositoryWriter for crate::GitBackend' not in write
assert 'GitPushRequest' not in write
assert 'push_candidate' not in write
assert '`alpha.2` a ensuite matérialisé le contrat d\'écriture provider-neutral et sa gate opérateur est `PASS`' in plan
assert '## 0.0.3' not in changelog
assert not Path('history/0.0.3/alpha.3.md').exists()
assert not Path('crates/knowledge-forge-gitea-lib').exists()
assert not Path('crates/knowledge-store-postgres-lib').exists()
assert not Path('migrations').exists()
print('Knowledge 0.0.3-alpha.3 candidate-worktree audit: clean')
PYGATE
python3 - <<'PYTEXT'
from pathlib import Path
roots = [Path('README.md'), Path('RULES.md'), Path('ROADMAP.md'), Path('CHANGELOG.md'), Path('docs'), Path('prompts'), Path('deltas'), Path('history')]
paths = []
for root in roots:
if root.is_file():
paths.append(root)
elif root.is_dir():
paths.extend(path for path in root.rglob('*') if path.is_file())
for path in paths:
data = path.read_bytes()
assert b'\r' not in data, path
assert data.endswith(b'\n'), path
assert not data.endswith(b'\n\n'), path
text = data.decode('utf-8')
for number, line in enumerate(text.splitlines(), start=1):
assert line == line.rstrip(' \t'), (path, number)
print(f'Knowledge 0.0.3-alpha.3 text hygiene: clean ({len(paths)} file(s))')
PYTEXT
test -z "$(git diff --name-only -- crates/knowledge-git-api crates/knowledge-app-lib Web CHANGELOG.md ROADMAP.md)"
test ! -e history/0.0.3/alpha.3.md
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 -f Web/knowledge-template-lab/package-lock.json
git add -A
git diff --cached --check
git status --short
La gate ne rejoue pas npm/Vite/HTTP : aucun fichier Web/, launcher ou contrat runtime Web n'est modifié.
Transition
PASS
Produire history/0.0.3/alpha.3.md, l'appliquer, commit/push 0.0.3-alpha.3, puis préparer 0.0.3-alpha.4 pour l'observation distante, le compare-and-exchange et le push gardé avec conflits explicites.
FAIL / PARTIAL / BLOCKED
Conserver le résultat réel dans son history avant toute correction. Une correction bornée utilise alpha.3.fix.N ; une remise en cause du cycle de vie des worktrees, de la frontière provider-neutral ou de la stratégie process Git exige un REPLAN explicite.