Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Hangboards/nature-stone-hanger-mini/assets/primary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Hangboards/nature-stone-hanger-mini/assets/side.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Hangboards/yy-baguette/assets/reverse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Hangboards/yy-travelboard/assets/reverse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions Hangboards/yy-travelboard/board.json
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,10 @@
"geometry": [
{
"frame": {
"x": 0.222,
"y": 0.506,
"width": 0.556,
"height": 0.102
"x": 0.231,
"y": 0.654,
"width": 0.538,
"height": 0.095
},
"shape": {
"type": "path",
Expand Down
1 change: 0 additions & 1 deletion Tools/HangboardPackages/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ dependencies = []

[project.optional-dependencies]
dev = ["Pillow>=12.3.0", "pytest>=9.1.1", "PyYAML>=6.0.2"]
backdrop = ["rembg[cpu]==2.0.75"]

[project.scripts]
hangboard-packages = "hangboard_packages.cli:main"
Expand Down
234 changes: 0 additions & 234 deletions Tools/HangboardPackages/scripts/remove_primary_backdrops.py

This file was deleted.

Binary file not shown.
53 changes: 53 additions & 0 deletions Tools/HangboardPackages/tests/test_authoring_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from __future__ import annotations

import ast
from pathlib import Path
import tomllib


TOOL_ROOT = Path(__file__).resolve().parents[1]
PRODUCTION_PYTHON_ROOTS = (TOOL_ROOT / "src", TOOL_ROOT / "scripts")
FORBIDDEN_IMPORT_ROOTS = frozenset({"PIL", "cv2", "rembg", "skimage"})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This guard only detects four imported roots, so production tooling can still perform segmentation, mask generation, or pixel cleanup through the standard library or another image library without failing the policy test. Inspect the prohibited operations or enforce an explicit production-capability allowlist instead of relying on this incomplete import list.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Tools/HangboardPackages/tests/test_authoring_policy.py, line 10:

<comment>This guard only detects four imported roots, so production tooling can still perform segmentation, mask generation, or pixel cleanup through the standard library or another image library without failing the policy test. Inspect the prohibited operations or enforce an explicit production-capability allowlist instead of relying on this incomplete import list.</comment>

<file context>
@@ -0,0 +1,53 @@
+
+TOOL_ROOT = Path(__file__).resolve().parents[1]
+PRODUCTION_PYTHON_ROOTS = (TOOL_ROOT / "src", TOOL_ROOT / "scripts")
+FORBIDDEN_IMPORT_ROOTS = frozenset({"PIL", "cv2", "rembg", "skimage"})
+FORBIDDEN_DEPENDENCY_PREFIXES = (
+    "opencv",
</file context>

FORBIDDEN_DEPENDENCY_PREFIXES = (
"opencv",
"pillow",
"rembg",
"scikit-image",
)


def _imported_roots(path: Path) -> set[str]:
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
roots: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
roots.update(alias.name.partition(".")[0] for alias in node.names)
elif isinstance(node, ast.ImportFrom) and node.module is not None:
roots.add(node.module.partition(".")[0])
return roots


def test_production_tooling_has_no_image_driven_authoring_capability() -> None:
"""Keep raster segmentation, masks, contours, and cropping out of tooling."""
violations: list[str] = []
for root in PRODUCTION_PYTHON_ROOTS:
for path in sorted(root.rglob("*.py")):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The test passes vacuously if src/ or scripts/ are renamed or removed: rglob("*.py") on a missing directory yields nothing, so no files are scanned and assert violations == [] still succeeds. A fail-closed policy guard should assert that production files were actually scanned.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Tools/HangboardPackages/tests/test_authoring_policy.py, line 34:

<comment>The test passes vacuously if `src/` or `scripts/` are renamed or removed: `rglob("*.py")` on a missing directory yields nothing, so no files are scanned and `assert violations == []` still succeeds. A fail-closed policy guard should assert that production files were actually scanned.</comment>

<file context>
@@ -0,0 +1,53 @@
+    """Keep raster segmentation, masks, contours, and cropping out of tooling."""
+    violations: list[str] = []
+    for root in PRODUCTION_PYTHON_ROOTS:
+        for path in sorted(root.rglob("*.py")):
+            forbidden = sorted(_imported_roots(path) & FORBIDDEN_IMPORT_ROOTS)
+            if forbidden:
</file context>

forbidden = sorted(_imported_roots(path) & FORBIDDEN_IMPORT_ROOTS)
Comment on lines +30 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (broader_impact): The authoring-policy guard only rejects four imported module roots and non-dev dependency names; production tooling that performs segmentation, generates masks, or hard-codes pixel cleanup using the standard library or an unlisted/custom image library passes this test. This does not enforce the policy described by the test and allows the deleted destructive authoring path to be reintroduced in a different implementation.

Triggers: When a future production script implements image manipulation without importing PIL, cv2, rembg, or skimage.

Suggested fix: Add structural checks for the prohibited authoring operations and production-file patterns, or enforce the policy through an explicit allowlist of production modules and capabilities rather than only checking imports and dependency prefixes.

if forbidden:
violations.append(
f"{path.relative_to(TOOL_ROOT)} imports {', '.join(forbidden)}"
)

pyproject = tomllib.loads(
(TOOL_ROOT / "pyproject.toml").read_text(encoding="utf-8")
)
optional_dependencies = pyproject["project"].get("optional-dependencies", {})
for extra, dependencies in sorted(optional_dependencies.items()):
if extra == "dev":
continue
for dependency in dependencies:
normalized = dependency.casefold()
if normalized.startswith(FORBIDDEN_DEPENDENCY_PREFIXES):
violations.append(f"optional extra {extra} includes {dependency}")
Comment on lines +44 to +51

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The guard only inspects optional-dependencies and never checks the top-level project.dependencies list. A forbidden package (rembg, Pillow, opencv, scikit-image) added to dependencies would bypass the policy even though the README contract says validation is stdlib-only. Check both lists.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Tools/HangboardPackages/tests/test_authoring_policy.py, line 44:

<comment>The guard only inspects `optional-dependencies` and never checks the top-level `project.dependencies` list. A forbidden package (rembg, Pillow, opencv, scikit-image) added to `dependencies` would bypass the policy even though the README contract says validation is stdlib-only. Check both lists.</comment>

<file context>
@@ -0,0 +1,53 @@
+    pyproject = tomllib.loads(
+        (TOOL_ROOT / "pyproject.toml").read_text(encoding="utf-8")
+    )
+    optional_dependencies = pyproject["project"].get("optional-dependencies", {})
+    for extra, dependencies in sorted(optional_dependencies.items()):
+        if extra == "dev":
</file context>
Suggested change
optional_dependencies = pyproject["project"].get("optional-dependencies", {})
for extra, dependencies in sorted(optional_dependencies.items()):
if extra == "dev":
continue
for dependency in dependencies:
normalized = dependency.casefold()
if normalized.startswith(FORBIDDEN_DEPENDENCY_PREFIXES):
violations.append(f"optional extra {extra} includes {dependency}")
project = pyproject["project"]
for dependency in project.get("dependencies", []):
normalized = dependency.casefold()
if normalized.startswith(FORBIDDEN_DEPENDENCY_PREFIXES):
violations.append(f"project dependencies include {dependency}")
optional_dependencies = project.get("optional-dependencies", {})
for extra, dependencies in sorted(optional_dependencies.items()):
if extra == "dev":
continue
for dependency in dependencies:
normalized = dependency.casefold()
if normalized.startswith(FORBIDDEN_DEPENDENCY_PREFIXES):
violations.append(f"optional extra {extra} includes {dependency}")


assert violations == []
Loading
Loading