11 KiB
Delta 0.0.3-rc.1 — release candidate
Base requise
État 0.0.3-beta.1 committé et poussé après application du history :
history/0.0.3/beta.1.md = PASS
La version devient :
0.0.3-rc.1
Objet
Geler le scope de 0.0.3 et exécuter sa gate complète de release candidate.
Aucune nouvelle fonctionnalité, dépendance, crate, route, comportement Git, décision PostgreSQL/Web ou modification de l'horizon produit n'est introduite.
Scope
La RC remplace uniquement :
VERSION
Cargo.toml
README.md
docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
et ajoute :
deltas/0.0.3/rc.1.md
Aucun fichier n'est supprimé. crates/, Web/, CHANGELOG.md, ROADMAP.md, docs/architecture/, docs/studies/, docs/rules/ et prompts/ sont gelés.
Histories attendus avant RC
La gate doit retrouver exactement les huit histories antérieurs suivants :
alpha.1 PARTIAL
alpha.1.fix.1 PARTIAL
alpha.1.fix.2 PASS
alpha.2 PASS
alpha.3 FAIL
alpha.3.fix.1 PASS
alpha.4 PASS
beta.1 PASS
Pendant la gate, rc.1.md doit être le seul delta 0.0.3 sans history correspondant.
Présentation candidate
La RC conserve :
CHANGELOG.md -> ## 0.0.3 (candidate)
ROADMAP.md -> 0.0.3 encore engagée + horizon 0.0.4..0.0.10
prompt 004 -> handoff 0.0.4 présent, sans commit/SHA futur inventé
La présentation stable appartient à rel.1, pas à la RC.
Gate opérateur
Exécuter directement dans le shell interactif. Ne pas activer set -e, set -u ou set -o pipefail globalement.
test "$(cat VERSION)" = '0.0.3-rc.1'
grep -F 'version = "0.0.3-rc.1"' Cargo.toml
grep -A2 '^## Statut$' history/0.0.3/beta.1.md | grep -Fx 'PASS'
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-rc.1-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 -p knowledge-git-lib --test git_write_push
cargo test --workspace --all-targets --all-features
(cd Web/knowledge-template-lab && npm ci)
(cd Web/knowledge-template-lab && npm run typecheck)
(cd Web/knowledge-template-lab && npm run build)
python3 -c 'import json; from pathlib import Path; p=Path("../builds/sasedev-knowledge/web/template-lab/.vite/manifest.json"); m=json.loads(p.read_text(encoding="utf-8")); e=m["src/main.ts"]; assert e.get("file"); assert e.get("css"); print("Knowledge 0.0.3-rc.1 Vite manifest audit: clean")'
Contrôles d'intégrité courts
grep -A2 '^## Statut$' history/0.0.3/alpha.1.md | grep -Fx 'PARTIAL'
grep -A2 '^## Statut$' history/0.0.3/alpha.1.fix.1.md | grep -Fx 'PARTIAL'
grep -A2 '^## Statut$' history/0.0.3/alpha.1.fix.2.md | grep -Fx 'PASS'
grep -A2 '^## Statut$' history/0.0.3/alpha.2.md | grep -Fx 'PASS'
grep -A2 '^## Statut$' history/0.0.3/alpha.3.md | grep -Fx 'FAIL'
grep -A2 '^## Statut$' history/0.0.3/alpha.3.fix.1.md | grep -Fx 'PASS'
grep -A2 '^## Statut$' history/0.0.3/alpha.4.md | grep -Fx 'PASS'
grep -A2 '^## Statut$' history/0.0.3/beta.1.md | grep -Fx 'PASS'
test "$(find history/0.0.3 -maxdepth 1 -type f -name '*.md' | wc -l)" -eq 8
test "$(find deltas/0.0.3 -maxdepth 1 -type f -name '*.md' | wc -l)" -eq 9
test ! -e history/0.0.3/rc.1.md
grep -F '## 0.0.3 (candidate)' CHANGELOG.md
grep -F -- '- `( ) 0.0.3` — écriture Git contrôlée et push gardé' ROADMAP.md
grep -F -- '- `(h) 0.0.4` — fondation PostgreSQL partagée' ROADMAP.md
grep -F -- '- `(h) 0.0.10` — gestion, proposition, revue et publication' ROADMAP.md
test -f prompts/004-V0_0_4_START_PROMPT.md
! grep -Eq '[0-9a-f]{40}|[0-9a-f]{64}' prompts/004-V0_0_4_START_PROMPT.md
test ! -e crates/knowledge-store-postgres-lib
test ! -e crates/knowledge-forge-gitea-lib
test ! -e migrations
Vérifier le workspace Cargo sans bloc multi-lignes :
python3 -c 'import json; from pathlib import Path; m=json.loads(Path("/tmp/sasedev-knowledge-0.0.3-rc.1-metadata.json").read_text()); 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 {p["name"] for p in m["packages"]} == expected; assert len(m["workspace_members"]) == 9; print("Knowledge 0.0.3-rc.1 workspace audit: clean")'
Vérifier l'hygiène texte :
python3 -c '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=[p for r in roots for p in ([r] if r.is_file() else r.rglob("*")) if p.is_file()]; bad=[str(p) for p in paths if (lambda b: b"\r" in b or not b.endswith(b"\n") or b.endswith(b"\n\n") or any(line != line.rstrip(" \t") for line in b.decode("utf-8").splitlines()))(p.read_bytes())]; print(f"Knowledge 0.0.3-rc.1 text hygiene: clean ({len(paths)} file(s))") if not bad else (_ for _ in ()).throw(AssertionError(bad))'
Smokes HTTP de production
Construire les trois launchers :
cargo build -p knowledge-pgr-server -p knowledge-howtos-server -p knowledge-snippets-server
Préparer le chemin du manifest et la liste des assets :
export KNOWLEDGE_RC_MANIFEST="$(realpath ../builds/sasedev-knowledge/web/template-lab/.vite/manifest.json)"
python3 -c 'import json,os; m=json.load(open(os.environ["KNOWLEDGE_RC_MANIFEST"],encoding="utf-8")); e=m["src/main.ts"]; print("/"+e["file"].lstrip("/")); print(*["/"+x.lstrip("/") for x in e.get("css",[])],sep="\n")' > /tmp/sasedev-knowledge-0.0.3-rc.1-assets.txt
cat /tmp/sasedev-knowledge-0.0.3-rc.1-assets.txt
PGR
env -u KNOWLEDGE_VITE_DEV_ORIGIN KNOWLEDGE_VITE_MANIFEST_PATH="$KNOWLEDGE_RC_MANIFEST" KNOWLEDGE_PGR_BIND_ADDRESS=127.0.0.1:18181 ../builds/sasedev-knowledge/target/debug/knowledge-pgr-server > /tmp/knowledge-pgr-rc.1.log 2>&1 & echo $! > /tmp/knowledge-pgr-rc.1.pid
sleep 1
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18181/healthz",timeout=2); assert r.status==200 and r.read().decode()=="ok"; print("pgr healthz PASS")'
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18181/",timeout=2); assert r.status==200; open("/tmp/knowledge-pgr-rc.1.html","wb").write(r.read())'
while IFS= read -r asset; do grep -F "$asset" /tmp/knowledge-pgr-rc.1.html >/dev/null && python3 -c 'import sys,urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18181"+sys.argv[1],timeout=2); assert r.status==200' "$asset" || exit 1; done < /tmp/sasedev-knowledge-0.0.3-rc.1-assets.txt
kill "$(cat /tmp/knowledge-pgr-rc.1.pid)"
wait "$(cat /tmp/knowledge-pgr-rc.1.pid)" 2>/dev/null || true
echo 'knowledge-pgr-server smoke PASS'
HOWTOs
env -u KNOWLEDGE_VITE_DEV_ORIGIN KNOWLEDGE_VITE_MANIFEST_PATH="$KNOWLEDGE_RC_MANIFEST" KNOWLEDGE_HOWTOS_BIND_ADDRESS=127.0.0.1:18182 ../builds/sasedev-knowledge/target/debug/knowledge-howtos-server > /tmp/knowledge-howtos-rc.1.log 2>&1 & echo $! > /tmp/knowledge-howtos-rc.1.pid
sleep 1
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18182/healthz",timeout=2); assert r.status==200 and r.read().decode()=="ok"; print("howtos healthz PASS")'
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18182/",timeout=2); assert r.status==200; open("/tmp/knowledge-howtos-rc.1.html","wb").write(r.read())'
while IFS= read -r asset; do grep -F "$asset" /tmp/knowledge-howtos-rc.1.html >/dev/null && python3 -c 'import sys,urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18182"+sys.argv[1],timeout=2); assert r.status==200' "$asset" || exit 1; done < /tmp/sasedev-knowledge-0.0.3-rc.1-assets.txt
kill "$(cat /tmp/knowledge-howtos-rc.1.pid)"
wait "$(cat /tmp/knowledge-howtos-rc.1.pid)" 2>/dev/null || true
echo 'knowledge-howtos-server smoke PASS'
Snippets
env -u KNOWLEDGE_VITE_DEV_ORIGIN KNOWLEDGE_VITE_MANIFEST_PATH="$KNOWLEDGE_RC_MANIFEST" KNOWLEDGE_SNIPPETS_BIND_ADDRESS=127.0.0.1:18183 ../builds/sasedev-knowledge/target/debug/knowledge-snippets-server > /tmp/knowledge-snippets-rc.1.log 2>&1 & echo $! > /tmp/knowledge-snippets-rc.1.pid
sleep 1
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18183/healthz",timeout=2); assert r.status==200 and r.read().decode()=="ok"; print("snippets healthz PASS")'
python3 -c 'import urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18183/",timeout=2); assert r.status==200; open("/tmp/knowledge-snippets-rc.1.html","wb").write(r.read())'
while IFS= read -r asset; do grep -F "$asset" /tmp/knowledge-snippets-rc.1.html >/dev/null && python3 -c 'import sys,urllib.request; r=urllib.request.urlopen("http://127.0.0.1:18183"+sys.argv[1],timeout=2); assert r.status==200' "$asset" || exit 1; done < /tmp/sasedev-knowledge-0.0.3-rc.1-assets.txt
kill "$(cat /tmp/knowledge-snippets-rc.1.pid)"
wait "$(cat /tmp/knowledge-snippets-rc.1.pid)" 2>/dev/null || true
echo 'knowledge-snippets-server smoke PASS'
Scope gelé et staging
test -z "$(git diff --name-only -- crates Web CHANGELOG.md ROADMAP.md docs/architecture docs/studies docs/rules prompts)"
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
Le staging final attendu avant history est limité à :
M Cargo.toml
M README.md
M VERSION
A deltas/0.0.3/rc.1.md
M docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md
M docs/validation/001-VALIDATION_MATRIX.md
Transition
PASS
Produire history/0.0.3/rc.1.md, l'appliquer, commit/push 0.0.3-rc.1, puis préparer 0.0.3-rel.1 comme promotion mécanique stable pré-tag.
FAIL
Produire le history avec le résultat exact puis une tranche rc.1.fix.1 strictement bornée à la régression observée. Ne pas promouvoir la stable tant que la RC n'est pas PASS.