0.0.2-beta.1.fix.1

This commit is contained in:
2026-09-29 06:24:50 +02:00
parent 5cee2a65b0
commit 4b51098911
7 changed files with 476 additions and 9 deletions

View File

@@ -0,0 +1,270 @@
<!-- file: deltas/0.0.2/beta.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-beta.1.fix.1 — clôture de la stabilisation runtime
## Base requise
État `0.0.2-beta.1` committé et poussé après application du history :
```text
history/0.0.2/beta.1.md = PARTIAL
```
La version devient :
```text
0.0.2-beta.1.fix.1
```
## Cause
`beta.1` acquiert la réconciliation, la revue d'horizon, les audits Markdown/Rust, Cargo/Clippy/tests, la baseline Web et le manifest Vite. La gate générée n'exécute toutefois pas les trois smokes HTTP requis par le plan pendant la stabilisation.
Cette omission appartient au contrat de validation livré, pas à une défaillance de l'opérateur. Le history `beta.1` reste donc `PARTIAL`.
## Objet du fix
Le fix n'introduit aucune fonctionnalité. Il :
- rend explicite chez `400-VALIDATION` qu'un smoke de stabilisation exigé par le plan ne peut pas être omis au motif qu'il n'existe aucun diff runtime ;
- documente `beta.1 = PARTIAL` dans le plan et la matrice ;
- rejoue la gate beta complète ;
- ajoute les trois smokes HTTP production manquants avant d'autoriser la RC.
## Scope
Fichiers remplacés :
```text
VERSION
Cargo.toml
docs/rules/400-VALIDATION.md
docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
```
Fichier ajouté :
```text
deltas/0.0.2/beta.1.fix.1.md
```
Aucun fichier sous `crates/` ou `Web/` n'est remplacé. Aucun package, dépendance, contrat métier, comportement Git ou prochaine release n'est ajouté.
## Gate opérateur
```bash
set -euo pipefail
test "$(cat VERSION)" = '0.0.2-beta.1.fix.1'
grep -F 'version = "0.0.2-beta.1.fix.1"' Cargo.toml
grep -A2 '^## Statut$' history/0.0.2/beta.1.md | grep -Fx 'PARTIAL'
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-beta.1.fix.1-metadata.json
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets --all-features
(
cd Web/knowledge-template-lab
npm ci
npm run typecheck
npm run build
)
python3 - <<'PYGATE'
import json
from pathlib import Path
metadata = json.loads(Path('/tmp/sasedev-knowledge-0.0.2-beta.1.fix.1-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 = Path('../builds/sasedev-knowledge/web/template-lab/.vite/manifest.json')
assert manifest_path.is_file(), manifest_path
manifest = json.loads(manifest_path.read_text(encoding='utf-8'))
assert 'src/main.ts' in manifest, manifest.keys()
study = Path('docs/studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md').read_text(encoding='utf-8')
assert 'Aucun prompt `0.0.3` n'est créé' in study
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '0.0.3' not in roadmap
assert not Path('prompts/003-V0_0_3_START_PROMPT.md').exists()
assert not Path('history/0.0.2/beta.1.fix.1.md').exists()
rule400 = Path('docs/rules/400-VALIDATION.md').read_text(encoding='utf-8')
assert 'Lorsqu'un plan exige un smoke de stabilisation, cette preuve est obligatoire' in rule400
print('Knowledge 0.0.2-beta.1.fix.1 stabilization audit: clean')
PYGATE
python3 - <<'PYSMOKE'
import json
import os
from pathlib import Path
import signal
import subprocess
import time
import urllib.request
root = Path.cwd()
build_root = (root / "../builds/sasedev-knowledge").resolve()
manifest_path = build_root / "web/template-lab/.vite/manifest.json"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
entry = manifest["src/main.ts"]
asset_paths = ["/" + entry["file"].lstrip("/")]
asset_paths.extend("/" + value.lstrip("/") for value in entry.get("css", []))
subprocess.run([
"cargo", "build",
"-p", "knowledge-pgr-server",
"-p", "knowledge-howtos-server",
"-p", "knowledge-snippets-server",
], check=True)
servers = (
("knowledge-pgr-server", "KNOWLEDGE_PGR_BIND_ADDRESS", 18181),
("knowledge-howtos-server", "KNOWLEDGE_HOWTOS_BIND_ADDRESS", 18182),
("knowledge-snippets-server", "KNOWLEDGE_SNIPPETS_BIND_ADDRESS", 18183),
)
for binary_name, bind_variable, port in servers:
binary = build_root / "target/debug" / binary_name
assert binary.is_file(), binary
env = os.environ.copy()
env.pop("KNOWLEDGE_VITE_DEV_ORIGIN", None)
env["KNOWLEDGE_VITE_MANIFEST_PATH"] = str(manifest_path)
env[bind_variable] = f"127.0.0.1:{port}"
process = subprocess.Popen(
[str(binary)],
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
text=True,
)
try:
health_url = f"http://127.0.0.1:{port}/healthz"
for attempt in range(50):
try:
with urllib.request.urlopen(health_url, timeout=1) as response:
body = response.read().decode("utf-8")
assert response.status == 200
assert body == "ok"
break
except Exception:
if process.poll() is not None:
stdout, stderr = process.communicate()
raise AssertionError((binary_name, process.returncode, stdout, stderr))
if attempt == 49:
raise
time.sleep(0.1)
with urllib.request.urlopen(f"http://127.0.0.1:{port}/", timeout=2) as response:
html = response.read().decode("utf-8")
assert response.status == 200
for asset_path in asset_paths:
assert asset_path in html, (binary_name, asset_path)
with urllib.request.urlopen(f"http://127.0.0.1:{port}{asset_path}", timeout=2) as response:
assert response.status == 200, (binary_name, asset_path, response.status)
print(f"{binary_name} smoke PASS")
finally:
if process.poll() is None:
os.killpg(process.pid, signal.SIGTERM)
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
os.killpg(process.pid, signal.SIGKILL)
process.wait(timeout=5)
print("Knowledge 0.0.2-beta.1.fix.1 HTTP smoke: clean")
PYSMOKE
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
text = data.decode('utf-8')
for number, line in enumerate(text.splitlines(), start=1):
assert line == line.rstrip(' \t'), (path, number)
print(f'Knowledge beta.1.fix.1 text hygiene: clean ({len(paths)} file(s))')
PYTEXT
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 -- crates 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
```
## Résultat attendu
Le `PASS` doit notamment afficher :
```text
Knowledge 0.0.2-beta.1.fix.1 stabilization audit: clean
knowledge-pgr-server smoke PASS
knowledge-howtos-server smoke PASS
knowledge-snippets-server smoke PASS
Knowledge 0.0.2-beta.1.fix.1 HTTP smoke: clean
```
Les warnings npm/Sass déjà observés restent non bloquants si les commandes terminent avec succès.
## Transition
`PASS` autorise uniquement :
```text
0.0.2-rc.1
```
Le history `beta.1.fix.1` est produit seulement après réception de la gate opérateur complète.