# Delta 0.0.3-alpha.2 — contrat d'écriture Git provider-neutral ## Baseline requise Partir de `0.0.3-alpha.1.fix.2` après application, commit et push de son history `PASS`. La version devient : ```text 0.0.3-alpha.2 ``` ## Objet Matérialiser uniquement la frontière publique provider-neutral nécessaire aux futures opérations d'écriture Git, sans implémenter encore le worktree d'écriture ou le push distant réel. La tranche : - conserve `GitRepository` comme contrat de lecture inchangé ; - ajoute `GitRepositoryWriter` comme capacité distincte afin de ne pas imposer l'écriture aux consommateurs/fakes lecture seule ; - introduit `GitMutationPath` pour des chemins relatifs normalisés, sans `.` / `..`, séparateur plateforme, chemin absolu, drive Windows ou composant `.git` ; - introduit `GitFileMutation` pour écrire/créer/remplacer ou supprimer un fichier ; - introduit `GitCommitIdentity` et exige une identité explicite ; - introduit `GitBranch` et borne la publication à une référence complète valide sous `refs/heads/...` ; - introduit `GitRemoteState` pour représenter explicitement branche absente ou révision attendue ; - introduit `GitWriteRequest`, `GitPushRequest` et `GitPushOutcome` pour séparer création de candidate, mise à jour distante gardée et conflit ; - rejette une requête sans mutation, un message vide/NUL et plusieurs mutations visant le même chemin ; - documente la matérialisation de la frontière sans déplacer les responsabilités backend prévues pour `alpha.3` / `alpha.4`. Aucun processus Git d'écriture n'est lancé par cette tranche. ## Scope des fichiers REPLACE : ```text VERSION Cargo.toml README.md crates/knowledge-git-api/src/lib.rs crates/knowledge-git-api/unit_tests/lib.rs docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md docs/validation/001-VALIDATION_MATRIX.md ``` ADD : ```text crates/knowledge-git-api/src/write.rs deltas/0.0.3/alpha.2.md ``` DELETE : aucun. Aucun fichier sous `knowledge-git-lib`, `knowledge-app-lib` ou `Web/` n'est modifié. Aucun history `alpha.2` n'est inclus dans ce delta. ## Contrat public matérialisé Le contrat expose les valeurs suivantes depuis la façade `knowledge_git_api` : ```text GitWriteInputError GitMutationPath GitFileMutation GitCommitIdentity GitBranch GitRemoteState GitWriteRequest GitPushRequest GitPushOutcome GitRepositoryWriter ``` Le chemin conceptuel reste : ```text GitRevision de base + mutations confinées + identité/message explicites -> create_candidate -> GitRevision candidate GitBranch + GitRemoteState attendu + GitRevision candidate -> push_candidate -> Updated ou Conflict ``` `alpha.2` définit ce contrat mais ne prétend pas encore prouver le confinement filesystem face aux symlinks, la neutralisation des hooks, la création effective d'un commit ou le compare-and-exchange distant. Ces preuves appartiennent au backend `knowledge-git-lib` des tranches suivantes. ## Gate opérateur Exécuter depuis la racine du dépôt après application du delta : ```bash test "$(cat VERSION)" = '0.0.3-alpha.2' grep -F 'version = "0.0.3-alpha.2"' 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.2-metadata.json cargo check --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test -p knowledge-git-api --all-targets --all-features cargo test --workspace --all-targets --all-features python3 - <<'PYGATE' from pathlib import Path api = Path('crates/knowledge-git-api/src/lib.rs').read_text(encoding='utf-8') write = Path('crates/knowledge-git-api/src/write.rs').read_text(encoding='utf-8') read_contract = Path('crates/knowledge-git-api/src/repository.rs').read_text(encoding='utf-8') manifest = Path('crates/knowledge-git-api/Cargo.toml').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 item in ( 'GitWriteInputError', 'GitMutationPath', 'GitFileMutation', 'GitCommitIdentity', 'GitBranch', 'GitRemoteState', 'GitWriteRequest', 'GitPushRequest', 'GitPushOutcome', 'GitRepositoryWriter', ): assert item in api, item assert item in write, item assert 'fn refresh(' in read_contract assert 'fn resolve_revision(' in read_contract assert 'fn prepare_snapshot(' in read_contract assert 'create_candidate' not in read_contract assert 'push_candidate' not in read_contract assert 'refs/heads/' in write assert 'ProtectedGitPath' in write assert 'DuplicateMutationPath' in write assert 'GitRemoteState::Absent' not in write or 'GitRemoteState' in write assert 'rebase' not in write.lower() assert 'merge' not in write.lower() for forbidden in ('actix', 'tokio', 'gitea', 'gitlab', 'github', 'postgres', 'sqlx', 'diesel'): assert forbidden not in manifest.lower(), forbidden assert '`alpha.1.fix.2` a complété la gate documentaire et technique en `PASS`' in plan assert '### alpha.2 — contrat d\'écriture provider-neutral' in plan assert '## 0.0.3' not in changelog assert Path('history/0.0.3/alpha.1.fix.2.md').is_file() assert not Path('history/0.0.3/alpha.2.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.2 write-contract 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.2 text hygiene: clean ({len(paths)} file(s))') PYTEXT test -z "$(git diff --name-only -- crates/knowledge-git-lib crates/knowledge-app-lib Web)" test ! -e history/0.0.3/alpha.2.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 : `Web/`, les launchers et leur contrat runtime ne sont pas modifiés. ## Transition ### PASS Produire `history/0.0.3/alpha.2.md`, l'appliquer, commit/push `0.0.3-alpha.2`, puis préparer `0.0.3-alpha.3` pour le worktree d'écriture isolé et le commit candidat réel dans `knowledge-git-lib`. ### FAIL / PARTIAL / BLOCKED Conserver le résultat réel dans son history avant toute correction. Une correction bornée utilise `alpha.2.fix.N` ; une modification de la mission ou de la frontière d'ownership exige un `REPLAN` explicite plutôt qu'un fix absorbant une nouvelle fonctionnalité.