chore(packaging): document hygiene boundaries

This commit is contained in:
rookiestar28
2026-06-04 14:40:09 +08:00
parent 4cfa9fba39
commit db9067a380
5 changed files with 194 additions and 4 deletions
+5 -1
View File
@@ -31,7 +31,7 @@ Icon = ""
[tool.ruff]
# Ruff replaces flake8, isort, and other linters
target-version = "py310"
line-length = 120
line-length = 88
indent-width = 4
[tool.ruff.lint]
@@ -64,6 +64,10 @@ indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "lf"
[tool.black]
line-length = 88
target-version = ["py310"]
[tool.mypy]
python_version = "3.10"
warn_return_any = true
@@ -3,11 +3,13 @@ Debug script for S35 Transform Isolation.
Verifies that the correct executor (TransformProcessRunner) is allowed/loaded.
"""
import os
from pathlib import Path
import sys
# Ensure project root is in path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from services.constrained_transforms import get_transform_executor
from services.transform_runner import TransformProcessRunner
@@ -3,10 +3,13 @@ Verify S30 Security Doctor output.
"""
import os
from pathlib import Path
import sys
# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from services.security_doctor import run_security_doctor
+84
View File
@@ -0,0 +1,84 @@
"""
Dependency-light package hygiene contract for repo packaging/tooling ownership.
Keep this import-safe: tests and future packaging checks should be able to read
the contract without importing ComfyUI, aiohttp, connector adapters, or stateful
runtime modules.
"""
from __future__ import annotations
import copy
from typing import Any, Dict
PACKAGE_HYGIENE_CONTRACT_VERSION = 1
_PACKAGE_HYGIENE_CONTRACT: Dict[str, Any] = {
"version": PACKAGE_HYGIENE_CONTRACT_VERSION,
"developer_helpers": [
{
"id": "s35_transform_isolation_debug",
"path": "scripts/devtools/debug_s35_import.py",
"owner": "devtools",
"root_tracked": False,
"rationale": "developer-only transform isolation probe; not a package entrypoint",
},
{
"id": "s30_security_doctor_verify",
"path": "scripts/devtools/verify_s30_doctor.py",
"owner": "devtools",
"root_tracked": False,
"rationale": "developer-only Security Doctor probe; not a package entrypoint",
},
],
"retained_artifacts": [
{
"path": "package-lock.json",
"owner": "frontend",
"tracked": True,
"rationale": (
"retained as the npm ci source of truth for Playwright/Vitest "
"validation and supply-chain lockfile scanning"
),
},
{
"path": "pyproject.toml",
"owner": "python_package",
"tracked": True,
"rationale": (
"retained as package metadata plus formatter, coverage, and "
"quality-gate configuration source of truth"
),
},
],
"cache_ownership": [
{
"id": "runtime_state_cache",
"owner": "state_dir",
"tracked": False,
"path_contract": "services.state_dir.get_cache_dir()",
"cleanup": "preserve_unless_operator_requests_state_cleanup",
"rationale": "runtime cache belongs under configured OpenClaw state, not package source",
},
{
"id": "repo_local_tool_cache",
"owner": "validation_tooling",
"tracked": False,
"path_contract": ".tmp/",
"cleanup": "safe_to_delete_when_tools_are_not_running",
"rationale": "pre-commit, Black, Playwright, and test temp caches are generated local artifacts",
},
{
"id": "frontend_dependencies",
"owner": "npm",
"tracked": False,
"path_contract": "node_modules/",
"cleanup": "recreate_with_npm_ci",
"rationale": "dependency install output is regenerated from package-lock.json",
},
],
}
def get_package_hygiene_contract() -> Dict[str, Any]:
return copy.deepcopy(_PACKAGE_HYGIENE_CONTRACT)
+97
View File
@@ -0,0 +1,97 @@
import pathlib
import runpy
import unittest
ROOT = pathlib.Path(__file__).resolve().parents[1]
def _read_simple_toml_value(section_name: str, key_name: str):
current_section = None
for raw_line in (ROOT / "pyproject.toml").read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if line.startswith("[") and line.endswith("]"):
current_section = line.strip("[]")
continue
if current_section == section_name and "=" in line:
key, value = [part.strip() for part in line.split("=", 1)]
if key == key_name:
return int(value.split("#", 1)[0].strip())
raise AssertionError(f"missing pyproject value: [{section_name}] {key_name}")
class R173PackageHygieneTests(unittest.TestCase):
def test_developer_helpers_are_not_tracked_at_repo_root(self):
forbidden_root_helpers = {
"debug_s35_import.py",
"verify_s30_doctor.py",
}
for helper_name in forbidden_root_helpers:
self.assertFalse(
(ROOT / helper_name).exists(),
f"{helper_name} should live under scripts/devtools, not repo root",
)
expected_devtools = {
"scripts/devtools/debug_s35_import.py",
"scripts/devtools/verify_s30_doctor.py",
}
for helper_path in expected_devtools:
self.assertTrue(
(ROOT / helper_path).is_file(),
f"missing relocated helper: {helper_path}",
)
def test_relocated_developer_helpers_resolve_repo_root(self):
for helper_path in (
"scripts/devtools/debug_s35_import.py",
"scripts/devtools/verify_s30_doctor.py",
):
namespace = runpy.run_path(str(ROOT / helper_path))
self.assertEqual(namespace["ROOT"], ROOT)
def test_python_formatter_line_lengths_are_aligned(self):
ruff_line_length = _read_simple_toml_value("tool.ruff", "line-length")
black_line_length = _read_simple_toml_value("tool.black", "line-length")
isort_line_length = _read_simple_toml_value("tool.isort", "line_length")
self.assertEqual(ruff_line_length, black_line_length)
self.assertEqual(black_line_length, isort_line_length)
def test_package_hygiene_contract_documents_artifact_and_cache_ownership(self):
from services.package_hygiene import get_package_hygiene_contract
contract = get_package_hygiene_contract()
retained_artifacts = {
artifact["path"]: artifact for artifact in contract["retained_artifacts"]
}
self.assertIn("package-lock.json", retained_artifacts)
self.assertEqual(retained_artifacts["package-lock.json"]["owner"], "frontend")
self.assertIn("npm ci", retained_artifacts["package-lock.json"]["rationale"])
cache_owners = {
cache["id"]: cache for cache in contract["cache_ownership"]
}
self.assertEqual(cache_owners["runtime_state_cache"]["owner"], "state_dir")
self.assertFalse(cache_owners["runtime_state_cache"]["tracked"])
self.assertEqual(
cache_owners["repo_local_tool_cache"]["cleanup"],
"safe_to_delete_when_tools_are_not_running",
)
helper_paths = {
helper["path"] for helper in contract["developer_helpers"]
}
self.assertEqual(
helper_paths,
{
"scripts/devtools/debug_s35_import.py",
"scripts/devtools/verify_s30_doctor.py",
},
)
if __name__ == "__main__":
unittest.main()