Files
sasedev-knowledge/deltas/0.0.3/alpha.3.md
2026-09-29 11:39:02 +02:00

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 SourceId et exige une GitRevision de base sûre ;
  • applique exactement les mutations Write / Delete demandé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.hooksPath sous contrôle ;
  • crée le commit avec auteur et committer explicitement issus de GitCommitIdentity, --no-verify et --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 candidate pré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 ;
  • HEAD est une révision Git sûre ;
  • HEAD^1 est 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.