Prepare accepted layer v0.8 publication and preserve immutable ADR history

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
tegwick 2026-10-11 02:06:56 +02:00
parent bfef142d4c
commit 5c41564f04
5 changed files with 307 additions and 2 deletions

View file

@ -111,6 +111,8 @@ def load_manifest(path: Path) -> dict[str, Any]:
document["canonical_path"],
document["revision_path"].replace("{revision}", "revision"),
*document.get("legacy_paths", []),
*(document["revision_path"].format(revision=h["revision"])
for h in document.get("historical_revisions", [])),
):
path_value = _safe_path(raw)
if path_value in seen:
@ -119,6 +121,44 @@ def load_manifest(path: Path) -> dict[str, Any]:
return manifest
def _restore_historical_revisions(
document: dict[str, Any], repo: Path, output: Path, current_revision: str,
) -> None:
"""Retain explicitly pinned served revision bytes even in a clean build."""
for historical in document.get("historical_revisions", []):
revision = historical["revision"]
if revision == current_revision:
raise ValueError("historical revision must differ from current revision")
source = (repo / historical["source_path"]).resolve()
page = (repo / historical["rendered_page_path"]).resolve()
for artifact in (source, page):
if repo not in artifact.parents or not artifact.is_file():
raise ValueError("historical artifact must be a file inside source repository")
source_bytes, page_bytes = source.read_bytes(), page.read_bytes()
if hashlib.sha256(source_bytes).hexdigest() != historical["source_digest"]:
raise RuntimeError("historical source digest mismatch")
if hashlib.sha256(page_bytes).hexdigest() != historical["rendered_page_digest"]:
raise RuntimeError("historical rendered page digest mismatch")
meta, _ = split_frontmatter(source_bytes.decode("utf-8"))
if meta.get("id") != document["id"] or meta.get("revision") != revision:
raise ValueError("historical source id/revision mismatch")
page_text = page_bytes.decode("utf-8")
source_revision = SOURCE_REVISION.search(page_text)
source_digest = SOURCE_DIGEST.search(page_text)
expected_revision = historical["source_revision"]
if not CLEAN_GIT_REVISION.fullmatch(expected_revision):
raise ValueError("historical source revision must be a clean Git commit")
if (not source_revision or not source_digest
or html.unescape(source_revision.group(1)) != expected_revision
or html.unescape(source_digest.group(1)) != historical["source_digest"]):
raise RuntimeError("historical page/source provenance mismatch")
target = output / _safe_path(document["revision_path"].format(revision=revision))
if target.exists() and target.read_bytes() != page_bytes:
raise RuntimeError("immutable historical revision already has different bytes")
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(page_bytes)
def _redirect(target: str, title: str) -> str:
escaped = html.escape(target, quote=True)
return (
@ -214,6 +254,7 @@ def build(
revision = meta.get("revision") or meta.get("version")
if not revision:
raise ValueError(f"{source}: revision or version is required")
_restore_historical_revisions(document, repo, temporary, revision)
source_revision = _source_revision(repo, source)
source_digest = hashlib.sha256(source.read_bytes()).hexdigest()
reviewed = meta.get("last_reviewed") or meta.get("updated")