Files
Artificial-Sweetener-Simple…/tools/prompt_control_characterization/source_identity.py
T

94 lines
3.3 KiB
Python

# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
# Copyright (C) 2026 Artificial Sweetener and contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Verify the immutable installed Prompt Control source identity."""
from __future__ import annotations
import hashlib
from dataclasses import dataclass
from pathlib import Path
PINNED_VERSION = "3.0.0-beta.3"
PINNED_TRACKED_PATH_COUNT = 53
PINNED_TRACKED_TREE_SHA256 = (
"eb45f34e976b01f3c4a98318c062ef3d54bfbbfef3e4e76ad8fd6f73b0f1204d"
)
@dataclass(frozen=True)
class PromptControlSourceIdentity:
"""Describe one validated Prompt Control installation without its path."""
version: str
tracked_path_count: int
tracked_tree_sha256: str
def inspect_source(root: Path) -> PromptControlSourceIdentity:
"""Hash sorted tracked paths and bytes using the plan's canonical framing."""
resolved = root.resolve()
tracking = resolved / ".tracking"
pyproject = resolved / "pyproject.toml"
if not tracking.is_file() or not pyproject.is_file():
raise ValueError(
"Prompt Control root must contain .tracking and pyproject.toml."
)
version = _project_version(pyproject.read_text(encoding="utf-8"))
paths = tuple(
sorted(
(
line.strip().replace("\\", "/")
for line in tracking.read_text(encoding="utf-8").splitlines()
),
key=lambda value: value.encode("utf-8"),
)
)
if not paths or any(not path for path in paths):
raise ValueError("Prompt Control .tracking must contain nonempty paths.")
digest = hashlib.sha256()
for relative_path in paths:
candidate = (resolved / Path(relative_path)).resolve()
if not candidate.is_relative_to(resolved) or not candidate.is_file():
raise ValueError(f"Invalid Prompt Control tracked path: {relative_path!r}.")
digest.update(relative_path.encode("utf-8"))
digest.update(b"\0")
digest.update(candidate.read_bytes())
digest.update(b"\0")
return PromptControlSourceIdentity(version, len(paths), digest.hexdigest())
def validate_pinned_source(identity: PromptControlSourceIdentity) -> None:
"""Reject any Prompt Control source other than the investigated install."""
expected = PromptControlSourceIdentity(
PINNED_VERSION,
PINNED_TRACKED_PATH_COUNT,
PINNED_TRACKED_TREE_SHA256,
)
if identity != expected:
raise ValueError(
"Prompt Control source does not match the pinned characterization identity."
)
def _project_version(pyproject: str) -> str:
"""Read the sole project version assignment without a TOML dependency."""
versions = []
in_project = False
for line in pyproject.splitlines():
stripped = line.strip()
if stripped.startswith("["):
in_project = stripped == "[project]"
elif in_project and stripped.startswith("version"):
_, separator, value = stripped.partition("=")
if not separator:
raise ValueError("Prompt Control project version is malformed.")
versions.append(value.strip().strip('"'))
if len(versions) != 1 or not versions[0]:
raise ValueError("Prompt Control pyproject must define one project version.")
return versions[0]