Files
wehub-resource-sync 2c632336aa
CI / Viewer CI (push) Successful in 13m37s
CI / Core CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:38 +08:00

1391 lines
48 KiB
Python

from __future__ import annotations
import hashlib
import linecache
import math
import re
import traceback
from dataclasses import dataclass
from pathlib import Path
from typing import Iterable, Literal, Protocol, TypeAlias, runtime_checkable
from agent.models import CompileSignal, CompileSignalBundle
_EXCEPTION_PREFIX_RE = re.compile(r"^(?:[A-Za-z_][A-Za-z0-9_]*(?:Error|Exception|Failure)):\s*")
LOFT_PROFILE_AREA_ERROR = "Loft profile area must be non-zero"
LOFT_PROFILE_AREA_HINT = (
"Hint: LoftGeometry checks profile area in the XY projection. "
"Use closed loops like `(x_i, y_i, z_const)`. "
"If you need an XZ/YZ section, author it in XY first and rotate the mesh afterward."
)
SDK_SUBMODULE_IMPORT_HINT = (
"Hint: Public authoring helpers import from top-level `sdk`. "
"Use `from sdk import place_on_face`, `TestContext`, or `MotionLimits`, "
"not guessed submodules like `sdk.placement`, `sdk.testing`, or `sdk.core_types`."
)
MAX_RISK_PATTERN = re.compile(r"max_risk=(low|medium|high)", re.IGNORECASE)
SignalSeverity: TypeAlias = Literal["failure", "warning", "note"]
SignalSource: TypeAlias = Literal["compiler", "tests", "harness"]
SignalGroup: TypeAlias = Literal["build", "qc", "design", "hygiene"]
CompileStatus: TypeAlias = Literal["success", "failure"]
class TestFailureLike(Protocol):
name: str
details: str
@runtime_checkable
class TestReportLike(Protocol):
failures: tuple[TestFailureLike, ...]
warnings: tuple[str, ...]
allowances: tuple[str, ...]
@dataclass(frozen=True, slots=True)
class ParsedTextBlock:
text: str
headline: str
details: str
lower: str
@dataclass(frozen=True, slots=True)
class ParsedTestWarning:
text: str
headline: str
details: str
lower: str
check_name: str
detail_text: str
max_risk: str | None
@dataclass(frozen=True, slots=True)
class ParsedTestFailure:
name: str
details: str
lower_name: str
lower_details: str
@dataclass(frozen=True, slots=True)
class SignalSpec:
severity: SignalSeverity
kind: str
code: str
source: SignalSource = "compiler"
group: SignalGroup = "qc"
blocking: bool = False
@dataclass(frozen=True, slots=True)
class CompilerWarningRule:
needle: str
spec: SignalSpec
summary: str
COMPILER_WARNING_RULES: tuple[CompilerWarningRule, ...] = (
CompilerWarningRule(
needle="non-finite or absurd geometry dimensions detected",
spec=SignalSpec(
severity="warning",
kind="geometry_scale",
code="WARN_GEOMETRY_ABSURD",
group="design",
),
summary="Non-finite or absurd geometry dimensions detected.",
),
CompilerWarningRule(
needle="geometry outlier dimensions detected",
spec=SignalSpec(
severity="warning",
kind="geometry_scale",
code="WARN_GEOMETRY_OUTLIER",
group="design",
),
summary="Geometry outlier dimensions detected.",
),
CompilerWarningRule(
needle="visual connectivity check failed",
spec=SignalSpec(
severity="warning",
kind="visual_connectivity",
code="WARN_VISUAL_CONNECTIVITY",
group="design",
),
summary="Visual connectivity check failed.",
),
CompilerWarningRule(
needle="geometry overlap check reported overlaps",
spec=SignalSpec(
severity="warning",
kind="geometry_overlap",
code="WARN_GEOMETRY_OVERLAP",
),
summary="Geometry overlap check reported overlaps.",
),
CompilerWarningRule(
needle="cwd-relative asset paths detected",
spec=SignalSpec(
severity="warning",
kind="path_hygiene",
code="WARN_CWD_RELATIVE_ASSET_PATH",
group="hygiene",
),
summary="cwd-relative asset paths detected.",
),
)
COMPILER_WARNING_FALLBACK_SPEC = SignalSpec(
severity="warning",
kind="compiler_warning",
code="WARN_COMPILER",
)
ISOLATED_PART_WARNING_SPEC = SignalSpec(
severity="warning",
kind="isolated_part",
code="WARN_ISOLATED_PART",
group="design",
)
ISOLATED_PART_FAILURE_SPEC = SignalSpec(
severity="failure",
kind="isolated_part",
code="TEST_ISOLATED_PART",
source="tests",
group="qc",
blocking=True,
)
ALLOWED_ISOLATED_PART_SPEC = SignalSpec(
severity="note",
kind="allowed_isolated_part",
code="NOTE_ALLOWED_ISOLATED_PART",
group="design",
)
TEST_FAILURE_SPEC = SignalSpec(
severity="failure",
kind="test_failure",
code="TEST_FAILURE",
source="tests",
group="qc",
blocking=True,
)
COPLANAR_HINT_SPEC = SignalSpec(
severity="note",
kind="coplanar_surface_hint",
code="NOTE_COPLANAR_SURFACE",
source="tests",
group="qc",
)
COPLANAR_WARNING_SPEC = SignalSpec(
severity="warning",
kind="coplanar_surface",
code="WARN_COPLANAR_SURFACE",
source="tests",
group="qc",
)
ALLOWED_OVERLAP_SPEC = SignalSpec(
severity="note",
kind="allowed_overlap",
code="NOTE_ALLOWED_OVERLAP",
source="tests",
group="qc",
)
OVERLAP_WARNING_SPEC = SignalSpec(
severity="warning",
kind="overlap_warning",
code="WARN_OVERLAP_SENSOR",
source="tests",
group="qc",
)
DISCONNECTED_GEOMETRY_SPEC = SignalSpec(
severity="warning",
kind="disconnected_geometry",
code="WARN_DISCONNECTED_GEOMETRY",
source="tests",
group="qc",
)
ARTICULATION_ORIGIN_SPEC = SignalSpec(
severity="warning",
kind="articulation_origin",
code="WARN_ARTICULATION_ORIGIN",
source="tests",
group="qc",
)
TEST_WARNING_FALLBACK_SPEC = SignalSpec(
severity="warning",
kind="test_warning",
code="TEST_WARNING",
source="tests",
group="qc",
)
DEPRECATED_TEST_API_SPEC = SignalSpec(
severity="warning",
kind="deprecated_test_api",
code="WARN_DEPRECATED_TEST_API",
source="tests",
group="hygiene",
)
ALLOWANCE_SPEC = SignalSpec(
severity="note",
kind="allowance",
code="ALLOWANCE",
source="tests",
group="qc",
)
COMPILE_RUNTIME_SPEC = SignalSpec(
severity="failure",
kind="compile_runtime",
code="COMPILE_RUNTIME_FAILURE",
source="compiler",
group="build",
blocking=True,
)
MISSING_EXACT_GEOMETRY_SPEC = SignalSpec(
severity="failure",
kind="missing_exact_geometry",
code="TEST_MISSING_EXACT_GEOMETRY",
source="tests",
group="qc",
blocking=True,
)
EXACT_CONTACT_GAP_SPEC = SignalSpec(
severity="failure",
kind="exact_contact_gap",
code="TEST_EXACT_CONTACT_GAP",
source="tests",
group="qc",
blocking=True,
)
REAL_OVERLAP_TEST_SPEC = SignalSpec(
severity="failure",
kind="real_overlap",
code="TEST_REAL_OVERLAP",
source="tests",
group="qc",
blocking=True,
)
REAL_OVERLAP_COMPILER_SPEC = SignalSpec(
severity="failure",
kind="real_overlap",
code="QC_REAL_OVERLAP",
source="compiler",
group="qc",
blocking=True,
)
SINGLE_ROOT_POLICY_SPEC = SignalSpec(
severity="failure",
kind="single_root_policy",
code="QC_SINGLE_ROOT_POLICY",
source="compiler",
group="build",
blocking=True,
)
MODEL_VALIDITY_SPEC = SignalSpec(
severity="failure",
kind="model_validity",
code="QC_MODEL_VALIDITY",
source="compiler",
group="build",
blocking=True,
)
MESH_ASSETS_SPEC = SignalSpec(
severity="failure",
kind="mesh_assets",
code="QC_MESH_ASSETS",
source="compiler",
group="build",
blocking=True,
)
ISOLATED_PART_COMPILER_SPEC = SignalSpec(
severity="failure",
kind="isolated_part",
code="QC_ISOLATED_PART",
source="compiler",
group="qc",
blocking=True,
)
_MIN_DISTANCE_RE = re.compile(
r"min_distance=(?P<distance>[-+0-9.eE]+)\s+contact_tol=(?P<tol>[-+0-9.eE]+)"
)
_TRACEBACK_FRAME_RE = re.compile(r'^\s*File "([^"]+)", line (\d+), in .+$')
_WINDOWS_ABSOLUTE_PATH_RE = re.compile(r"^[A-Za-z]:[\\/]")
_REPO_ROOT = Path(__file__).resolve().parents[1]
_REPO_ROOT_NAME = _REPO_ROOT.name.casefold()
try:
_REPO_TOP_LEVEL_ENTRY_NAMES = frozenset(path.name.casefold() for path in _REPO_ROOT.iterdir())
except OSError:
_REPO_TOP_LEVEL_ENTRY_NAMES = frozenset()
def _compile_hint_lines(detail_lines: list[str]) -> list[str]:
if any(LOFT_PROFILE_AREA_ERROR in line for line in detail_lines):
return [LOFT_PROFILE_AREA_HINT]
lower_lines = [line.lower() for line in detail_lines]
if any(
"no module named 'sdk." in line or 'no module named "sdk.' in line for line in lower_lines
):
return [SDK_SUBMODULE_IMPORT_HINT]
return []
def _sanitize_display_path(path_text: str) -> str:
raw = path_text.strip()
if not raw:
return raw
normalized = raw.replace("\\", "/")
if normalized.startswith("<") and normalized.endswith(">"):
return raw
if not (
normalized.startswith("/")
or normalized.startswith("\\")
or _WINDOWS_ABSOLUTE_PATH_RE.match(raw)
):
return normalized
repo_root = _REPO_ROOT.as_posix().rstrip("/")
if normalized == repo_root:
return "."
if repo_root and normalized.startswith(f"{repo_root}/"):
return normalized[len(repo_root) + 1 :]
parts = [part for part in normalized.split("/") if part]
for marker in ("site-packages", "dist-packages"):
if marker in parts:
return "/".join(parts[parts.index(marker) :])
for idx, part in enumerate(parts[:-1]):
if part.casefold() != _REPO_ROOT_NAME:
continue
remainder = parts[idx + 1 :]
if remainder and remainder[0].casefold() in _REPO_TOP_LEVEL_ENTRY_NAMES:
return "/".join(remainder)
if len(parts) <= 2:
return "/".join(parts)
return f".../{'/'.join(parts[-3:])}"
def _display_exception_type(exc: BaseException) -> str:
remote_error_type = getattr(exc, "remote_error_type", None)
if isinstance(remote_error_type, str) and remote_error_type.strip():
return remote_error_type.strip()
return type(exc).__name__
def _remote_traceback_text(exc: BaseException) -> str:
remote_traceback = getattr(exc, "remote_traceback", None)
if not isinstance(remote_traceback, str):
return ""
return remote_traceback.strip()
def _remote_traceback_exception_line(exc: BaseException) -> str | None:
remote_traceback = _remote_traceback_text(exc)
if not remote_traceback:
return None
for line in reversed(remote_traceback.splitlines()):
cleaned = line.strip()
if cleaned:
return cleaned
return None
def _is_low_information_exception_text(text: str) -> bool:
stripped = text.strip()
if not stripped:
return True
normalized = stripped
while True:
match = _EXCEPTION_PREFIX_RE.match(normalized)
if match is None:
break
normalized = normalized[match.end() :].lstrip()
if not normalized:
return True
return normalized.endswith(":") and " " not in normalized[:-1]
def _strip_redundant_exception_prefix(text: str, exc_type: str) -> str:
stripped = text.strip()
prefix = f"{exc_type}:"
while stripped.startswith(prefix):
stripped = stripped[len(prefix) :].lstrip()
return stripped or text.strip()
def _exception_detail_lines(exc: BaseException, *, max_detail_lines: int = 40) -> list[str]:
raw_message = str(exc).strip()
if raw_message:
tb_marker = "Traceback (most recent call last):"
marker_idx = raw_message.find(tb_marker)
if marker_idx >= 0:
raw_message = raw_message[:marker_idx].rstrip()
detail_lines: list[str] = []
seen: set[str] = set()
for line in raw_message.splitlines():
cleaned = line.rstrip()
if not cleaned:
continue
if cleaned in seen:
continue
seen.add(cleaned)
detail_lines.append(cleaned)
remote_exception_line = _remote_traceback_exception_line(exc)
if remote_exception_line and remote_exception_line not in seen:
if not detail_lines or _is_low_information_exception_text(detail_lines[0]):
detail_lines.insert(0, remote_exception_line)
seen.add(remote_exception_line)
warnings = getattr(exc, "warnings", None)
if isinstance(warnings, list):
for warning in warnings:
cleaned = str(warning).strip()
if not cleaned or cleaned in seen:
continue
seen.add(cleaned)
detail_lines.append(cleaned)
if len(detail_lines) > max_detail_lines:
omitted = len(detail_lines) - max_detail_lines
detail_lines = detail_lines[:max_detail_lines]
detail_lines.append(f"... ({omitted} more lines)")
for hint in _compile_hint_lines(detail_lines):
if hint not in seen:
detail_lines.append(hint)
seen.add(hint)
return detail_lines
def _location_lines_from_traceback_text(traceback_text: str) -> list[str]:
if not traceback_text:
return []
lines = traceback_text.splitlines()
last_frame_idx = -1
last_filename = ""
last_lineno = ""
for idx, line in enumerate(lines):
match = _TRACEBACK_FRAME_RE.match(line)
if match is None:
continue
last_frame_idx = idx
last_filename = match.group(1).strip()
last_lineno = match.group(2).strip()
if last_frame_idx < 0 or not last_filename or not last_lineno:
return []
rendered = [f"Location: {_sanitize_display_path(last_filename)}:{last_lineno}"]
if last_frame_idx + 1 < len(lines):
code_line = lines[last_frame_idx + 1].strip()
if code_line and _TRACEBACK_FRAME_RE.match(lines[last_frame_idx + 1]) is None:
rendered.append(f"Code: {code_line}")
return rendered
def _exception_location_lines(exc: BaseException) -> list[str]:
remote_lines = _location_lines_from_traceback_text(_remote_traceback_text(exc))
if remote_lines:
return remote_lines
extracted = traceback.extract_tb(exc.__traceback__) if exc.__traceback__ else []
skip_wrapper_location = isinstance(exc, RuntimeError)
if not extracted or skip_wrapper_location:
return []
last = extracted[-1]
location = f"{_sanitize_display_path(last.filename)}:{last.lineno}"
lines = [f"Location: {location}"]
raw_line = linecache.getline(last.filename, last.lineno).rstrip("\n")
if raw_line.strip():
lines.append(f"Code: {raw_line}")
return lines
def _parse_text_block(text: str) -> ParsedTextBlock:
lines = text.splitlines()
headline = lines[0] if lines else ""
details = "\n".join(lines[1:]).strip()
return ParsedTextBlock(text=text, headline=headline, details=details, lower=text.lower())
def _parse_test_warning(text: str) -> ParsedTestWarning:
parsed = _parse_text_block(text)
check_name, has_separator, detail_text = parsed.text.partition(":")
max_risk_match = MAX_RISK_PATTERN.search(parsed.text)
return ParsedTestWarning(
text=parsed.text,
headline=parsed.headline,
details=parsed.details,
lower=parsed.lower,
check_name=check_name.strip(),
detail_text=detail_text.lstrip() if has_separator else "",
max_risk=(max_risk_match.group(1).lower() if max_risk_match is not None else None),
)
def _parse_test_failure(failure: TestFailureLike) -> ParsedTestFailure:
name = str(failure.name)
details = str(failure.details).strip()
return ParsedTestFailure(
name=name,
details=details,
lower_name=name.lower(),
lower_details=details.lower(),
)
def _make_signal(
*,
severity: SignalSeverity,
kind: str,
code: str,
summary: str,
details: str = "",
blocking: bool = False,
source: SignalSource = "compiler",
group: SignalGroup = "qc",
check_name: str | None = None,
) -> CompileSignal:
sig_src = "\n".join(
[
severity,
kind,
code,
summary,
details,
str(blocking),
source,
group,
check_name or "",
]
).encode("utf-8")
return CompileSignal(
severity=severity,
kind=kind,
code=code,
summary=summary,
details=details,
blocking=blocking,
source=source,
group=group,
check_name=check_name,
dedupe_key=hashlib.sha1(sig_src).hexdigest(),
)
def _signal_from_spec(
spec: SignalSpec,
*,
summary: str,
details: str = "",
check_name: str | None = None,
) -> CompileSignal:
return _make_signal(
severity=spec.severity,
kind=spec.kind,
code=spec.code,
summary=summary,
details=details,
blocking=spec.blocking,
source=spec.source,
group=spec.group,
check_name=check_name,
)
def _isolated_part_summary(headline: str) -> str:
summary = "Floating disconnected component(s) detected."
if "(visual" in headline or "(visual," in headline:
return "Floating disconnected visual component(s) detected."
if "(collision" in headline or "(collision," in headline:
return "Floating disconnected collision component(s) detected."
return summary
def _format_distance_summary(value: float) -> str:
magnitude = abs(float(value))
if magnitude >= 0.1:
return f"{value:.3g} m"
mm_value = value * 1000.0
if abs(mm_value - round(mm_value)) < 1e-9:
return f"{int(round(mm_value))} mm"
return f"{mm_value:.3g} mm"
def _warning_signal_from_text(warning: str) -> CompileSignal:
text = str(warning).strip()
if not text:
return _signal_from_spec(
COMPILER_WARNING_FALLBACK_SPEC,
summary="Compiler emitted a warning.",
)
parsed = _parse_text_block(text)
if "isolated parts allowed by justification" in parsed.text:
return _signal_from_spec(
ALLOWED_ISOLATED_PART_SPEC,
summary="Isolated-part findings were allowed by justification.",
details=parsed.details,
)
if "isolated parts detected" in parsed.text:
return _signal_from_spec(
ISOLATED_PART_WARNING_SPEC,
summary=_isolated_part_summary(parsed.headline),
details=parsed.details,
)
for rule in COMPILER_WARNING_RULES:
if rule.needle in parsed.text:
return _signal_from_spec(
rule.spec,
summary=rule.summary,
details=parsed.details,
)
return _signal_from_spec(
COMPILER_WARNING_FALLBACK_SPEC,
summary=parsed.headline.replace("IMPORTANT: ", "").strip(),
details=parsed.details,
)
def _as_test_report(test_report: object | None) -> TestReportLike | None:
if test_report is None or not isinstance(test_report, TestReportLike):
return None
if not isinstance(test_report.failures, tuple):
return None
if not isinstance(test_report.warnings, tuple):
return None
if not isinstance(test_report.allowances, tuple):
return None
return test_report
def _iter_test_failures(test_report: TestReportLike | None) -> Iterable[CompileSignal]:
if test_report is None:
return ()
signals: list[CompileSignal] = []
for failure in test_report.failures:
parsed = _parse_test_failure(failure)
if parsed.name.startswith("fail_if_isolated_parts(") or (
"isolated parts detected" in parsed.lower_details
):
spec = (
ISOLATED_PART_COMPILER_SPEC
if parsed.name == "fail_if_isolated_parts()"
else ISOLATED_PART_FAILURE_SPEC
)
signals.append(
_signal_from_spec(
spec,
summary=_isolated_part_summary(
parsed.details.splitlines()[0] if parsed.details else parsed.name
),
details=parsed.details,
check_name=parsed.name,
)
)
continue
if parsed.name == "check_single_root_part":
signals.append(
_signal_from_spec(
SINGLE_ROOT_POLICY_SPEC,
summary=(
"Compiler-owned global QC requires exactly one root part "
"(`check_single_root_part`)."
),
details=parsed.details,
check_name=parsed.name,
)
)
continue
if parsed.name == "check_model_valid":
signals.append(
_signal_from_spec(
MODEL_VALIDITY_SPEC,
summary=(
"Compiler-owned structural validation rejected the current model "
"(`check_model_valid`)."
),
details=parsed.details,
check_name=parsed.name,
)
)
continue
if parsed.name == "check_mesh_assets_ready":
signals.append(
_signal_from_spec(
MESH_ASSETS_SPEC,
summary=(
"Compiler-owned mesh asset readiness checks found missing or unresolved "
"assets (`check_mesh_assets_ready`)."
),
details=parsed.details,
check_name=parsed.name,
)
)
continue
if "missing exact geometry" in parsed.lower_details:
signals.append(
_signal_from_spec(
MISSING_EXACT_GEOMETRY_SPEC,
summary="Authored exact check references named geometry that is not present.",
details=parsed.details,
check_name=parsed.name,
)
)
continue
gap_match = _MIN_DISTANCE_RE.search(parsed.details)
if gap_match is not None:
try:
min_distance = float(gap_match.group("distance"))
except ValueError:
min_distance = math.nan
gap_summary = "nonzero separation"
if math.isfinite(min_distance):
gap_summary = _format_distance_summary(min_distance)
signals.append(
_signal_from_spec(
EXACT_CONTACT_GAP_SPEC,
summary=(
"Authored exact-contact check found "
f"{gap_summary} where contact was expected."
),
details=parsed.details,
check_name=parsed.name,
)
)
continue
if "part overlaps detected" in parsed.lower_details:
spec = (
REAL_OVERLAP_COMPILER_SPEC
if parsed.name == "fail_if_parts_overlap_in_current_pose()"
else REAL_OVERLAP_TEST_SPEC
)
summary = (
"Compiler-owned global QC reported real 3D overlap in the current pose "
"(`fail_if_parts_overlap_in_current_pose()`)."
if spec is REAL_OVERLAP_COMPILER_SPEC
else "Authored QC check found real 3D overlap in the tested pose."
)
signals.append(
_signal_from_spec(
spec,
summary=summary,
details=parsed.details,
check_name=parsed.name,
)
)
continue
signals.append(
_signal_from_spec(
TEST_FAILURE_SPEC,
summary=parsed.name,
details=parsed.details,
check_name=parsed.name,
)
)
return signals
def _coplanar_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if "coplanar" not in parsed.lower:
return None
max_risk = parsed.max_risk or "medium"
if max_risk == "low":
return _signal_from_spec(
COPLANAR_HINT_SPEC,
summary="Low-confidence coplanar-surface hint.",
details=parsed.text,
)
return _signal_from_spec(
COPLANAR_WARNING_SPEC,
summary=f"Coplanar-surface heuristic reported {max_risk}-risk pair(s).",
details=parsed.text,
)
def _allowed_overlap_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if not parsed.lower.startswith("overlaps detected but allowed by justification"):
return None
return _signal_from_spec(
ALLOWED_OVERLAP_SPEC,
summary="Overlap findings were allowed by justification.",
details=parsed.text,
)
def _allowed_isolated_part_warning_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if not parsed.lower.startswith("isolated parts detected but allowed by justification"):
return None
return _signal_from_spec(
ALLOWED_ISOLATED_PART_SPEC,
summary="Isolated-part findings were allowed by justification.",
details=parsed.text,
)
def _overlap_warning_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if not parsed.check_name.startswith(("warn_if_overlaps(", "warn_if_articulation_overlaps(")):
return None
if parsed.check_name.startswith("warn_if_articulation_overlaps("):
summary = "Articulation overlap sensor reported overlap pair(s)."
else:
summary = "Broad overlap sensor reported overlap pair(s)."
if parsed.detail_text and "overlaps detected" not in parsed.detail_text.lower():
if parsed.check_name.startswith("warn_if_articulation_overlaps("):
summary = "Articulation overlap sensor reported a warning."
else:
summary = "Broad overlap sensor reported a warning."
return _signal_from_spec(
OVERLAP_WARNING_SPEC,
summary=summary,
details=parsed.text,
check_name=parsed.check_name,
)
def _disconnected_geometry_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if not parsed.check_name.startswith("warn_if_part_contains_disconnected_geometry_islands("):
return None
summary = (
"Exact visual connectivity check found disconnected geometry within a part; "
"this may be a real issue and should be investigated."
)
if (
parsed.detail_text
and "disconnected geometry islands detected" not in parsed.detail_text.lower()
):
summary = "Part-geometry connectivity check reported a warning; investigate it."
return _signal_from_spec(
DISCONNECTED_GEOMETRY_SPEC,
summary=summary,
details=parsed.text,
check_name=parsed.check_name,
)
def _articulation_origin_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if not parsed.check_name.startswith("warn_if_articulation_origin_far_from_geometry("):
return None
summary = "Exact articulation-origin distance check reported distant articulation origins."
if parsed.detail_text and "far from geometry" not in parsed.detail_text.lower():
summary = "Articulation-origin distance check reported a warning."
return _signal_from_spec(
ARTICULATION_ORIGIN_SPEC,
summary=summary,
details=parsed.text,
check_name=parsed.check_name,
)
def _deprecated_test_api_signal(parsed: ParsedTestWarning) -> CompileSignal | None:
if parsed.lower.startswith("deprecated as default:"):
return _signal_from_spec(
DEPRECATED_TEST_API_SPEC,
summary="Deprecated default scaffold heuristic used; switch to exact checks or targeted probe-backed sensors.",
details=parsed.text,
check_name=parsed.check_name,
)
if not parsed.lower.startswith("deprecated:"):
return None
if "aabb-envelope semantics" not in parsed.lower and "legacy aabb" not in parsed.lower:
return None
return _signal_from_spec(
DEPRECATED_TEST_API_SPEC,
summary="Deprecated AABB-based test helper used; switch to exact visual checks.",
details=parsed.text,
check_name=parsed.check_name,
)
def _generic_test_warning_signal(parsed: ParsedTestWarning) -> CompileSignal:
return _signal_from_spec(
TEST_WARNING_FALLBACK_SPEC,
summary=parsed.headline,
details=parsed.details,
)
def _warning_signal_from_test_text(text: str) -> CompileSignal:
parsed = _parse_test_warning(text)
for classifier in (
_coplanar_signal,
_allowed_isolated_part_warning_signal,
_allowed_overlap_signal,
_overlap_warning_signal,
_disconnected_geometry_signal,
_articulation_origin_signal,
_deprecated_test_api_signal,
):
signal = classifier(parsed)
if signal is not None:
return signal
return _generic_test_warning_signal(parsed)
def _iter_test_warnings(test_report: TestReportLike | None) -> Iterable[CompileSignal]:
if test_report is None:
return ()
signals: list[CompileSignal] = []
for warning in test_report.warnings:
text = str(warning).strip()
if not text:
continue
signals.append(_warning_signal_from_test_text(text))
return signals
def _iter_allowance_notes(test_report: TestReportLike | None) -> Iterable[CompileSignal]:
if test_report is None:
return ()
signals: list[CompileSignal] = []
structured_allowed_overlaps = tuple(getattr(test_report, "allowed_overlaps", ()))
for allowance in test_report.allowances:
text = str(allowance).strip()
if not text:
continue
if text.startswith("allow_isolated_part("):
signals.append(
_signal_from_spec(
ALLOWED_ISOLATED_PART_SPEC,
summary="Isolated-part allowance declared.",
details=text,
)
)
continue
if text.startswith("allow_overlap(") and structured_allowed_overlaps:
continue
signals.append(
_signal_from_spec(
ALLOWANCE_SPEC,
summary=text,
)
)
for overlap in structured_allowed_overlaps:
link_a = str(getattr(overlap, "link_a", "")).strip()
link_b = str(getattr(overlap, "link_b", "")).strip()
reason = str(getattr(overlap, "reason", "")).strip()
elem_a = getattr(overlap, "elem_a", None)
elem_b = getattr(overlap, "elem_b", None)
details = f"allow_overlap({link_a!r}, {link_b!r})"
if elem_a is not None or elem_b is not None:
details += (
f", elem_a={None if elem_a is None else str(elem_a)!r},"
f" elem_b={None if elem_b is None else str(elem_b)!r}"
)
if reason:
details += f": {reason}"
signals.append(
_signal_from_spec(
ALLOWED_OVERLAP_SPEC,
summary="Overlap allowance declared.",
details=details,
)
)
return signals
def _runtime_failure_signal(exc: BaseException) -> CompileSignal:
detail_lines = _exception_detail_lines(exc)
detail_lines.extend(_exception_location_lines(exc))
exc_type = _display_exception_type(exc)
summary = f"{exc_type}: compile execution failed."
if detail_lines:
first = detail_lines[0]
if first:
summary = f"{exc_type}: {_strip_redundant_exception_prefix(first, exc_type)}"
return _signal_from_spec(
COMPILE_RUNTIME_SPEC,
summary=summary,
details="\n".join(detail_lines),
)
def _signal_key(signal: CompileSignal) -> str:
return signal.dedupe_key or signal.summary
def _failure_sort_key(signal: CompileSignal) -> tuple[int, str, str]:
priority = 90
if signal.kind == "compile_runtime":
priority = 0
elif signal.kind in {"single_root_policy", "model_validity", "mesh_assets"}:
priority = 1
elif signal.source == "compiler" and signal.kind in {"isolated_part", "real_overlap"}:
priority = 2
elif signal.kind == "missing_exact_geometry":
priority = 3
elif signal.kind == "exact_contact_gap":
priority = 4
elif signal.kind == "real_overlap":
priority = 5
elif signal.kind == "isolated_part":
priority = 6
elif signal.kind == "test_failure":
priority = 7
return (priority, signal.kind, signal.summary)
def _ordered_failure_signals(signals: Iterable[CompileSignal]) -> list[CompileSignal]:
return sorted(
(signal for signal in signals if signal.severity == "failure"),
key=_failure_sort_key,
)
def _primary_failure_summary(signals: tuple[CompileSignal, ...]) -> str:
failures = _ordered_failure_signals(signals)
if not failures:
return "Primary issue: compile execution failed."
primary = failures[0]
if primary.kind == "compile_runtime":
primary_summary = primary.summary.strip()
if not primary_summary:
return "Primary issue: compile execution failed."
return f"Primary issue: {primary_summary}"
if primary.kind == "single_root_policy":
return "Primary issue: compiler-owned structural policy checks failed."
if primary.kind == "model_validity":
return "Primary issue: compiler-owned model validation failed."
if primary.kind == "mesh_assets":
return "Primary issue: compiler-owned mesh asset readiness checks failed."
if primary.source == "compiler" and primary.kind == "isolated_part":
return "Primary issue: compiler-owned global QC found floating disconnected parts."
if primary.source == "compiler" and primary.kind == "real_overlap":
return "Primary issue: compiler-owned global QC reported part overlap that needs classification."
if primary.kind == "missing_exact_geometry":
return "Primary issue: authored exact checks reference missing named geometry."
if primary.kind == "exact_contact_gap":
return "Primary issue: authored exact-contact checks found separation where contact was expected."
if primary.kind == "real_overlap":
return "Primary issue: required QC tests reported part overlap."
if primary.kind == "isolated_part":
return "Primary issue: required QC tests found floating disconnected parts."
return "Primary issue: required QC tests failed."
def _build_bundle_summary(status: CompileStatus, signals: tuple[CompileSignal, ...]) -> str:
failure_count = sum(1 for signal in signals if signal.severity == "failure")
warning_count = sum(1 for signal in signals if signal.severity == "warning")
note_count = sum(1 for signal in signals if signal.severity == "note")
if failure_count:
return (
f"status={status} failures={failure_count} warnings={warning_count} notes={note_count}\n"
f"{_primary_failure_summary(signals)}"
)
if warning_count:
return (
f"status={status} failures=0 warnings={warning_count} notes={note_count}\n"
"Primary issue: compile passed with warnings."
)
return f"status={status} failures=0 warnings=0 notes={note_count}\nCompile passed cleanly."
def build_compile_signal_bundle(
*,
status: CompileStatus,
warnings: Iterable[str] = (),
test_report: TestReportLike | None = None,
exc: BaseException | None = None,
) -> CompileSignalBundle:
deduped: dict[str, CompileSignal] = {}
normalized_test_report = _as_test_report(test_report)
test_warning_texts: set[str] = set()
if normalized_test_report is not None:
test_warning_texts = {
text for warning in normalized_test_report.warnings if (text := str(warning).strip())
}
for warning in warnings:
warning_text = str(warning).strip()
if not warning_text or warning_text in test_warning_texts:
continue
signal = _warning_signal_from_text(warning_text)
deduped[_signal_key(signal)] = signal
for signal in _iter_test_warnings(normalized_test_report):
deduped[_signal_key(signal)] = signal
for signal in _iter_allowance_notes(normalized_test_report):
deduped[_signal_key(signal)] = signal
failure_signals = list(_iter_test_failures(normalized_test_report))
if failure_signals:
for signal in failure_signals:
deduped[_signal_key(signal)] = signal
elif exc is not None:
runtime_signal = _runtime_failure_signal(exc)
deduped[_signal_key(runtime_signal)] = runtime_signal
signals = tuple(deduped.values())
summary = _build_bundle_summary(status, signals)
return CompileSignalBundle(status=status, summary=summary, signals=signals)
def compile_signal_bundle_from_exception(exc: BaseException) -> CompileSignalBundle:
existing = getattr(exc, "compile_signal_bundle", None)
if isinstance(existing, CompileSignalBundle):
return existing
warnings = getattr(exc, "warnings", None)
test_report = getattr(exc, "test_report", None)
warning_items = warnings if isinstance(warnings, list) else []
return build_compile_signal_bundle(
status="failure",
warnings=warning_items,
test_report=_as_test_report(test_report),
exc=exc,
)
def _indent_signal_details(details: str) -> str:
return "\n".join(f" {line}" if line else "" for line in details.splitlines())
def _render_signal_lines(signals: Iterable[CompileSignal]) -> str:
rendered: list[str] = []
for signal in signals:
severity = signal.severity.upper()
line = f"- {severity} [{signal.kind}] {signal.summary}"
if signal.details:
line += f"\n{_indent_signal_details(signal.details)}"
rendered.append(line)
return "\n".join(rendered)
def _render_signal_section(heading: str, signals: Iterable[CompileSignal]) -> str:
return f"{heading}\n{_render_signal_lines(signals)}"
def render_compile_signals(
bundle: CompileSignalBundle,
*,
repeated: bool = False,
failure_streak: int = 1,
) -> str:
failures = _ordered_failure_signals(bundle.signals)
warnings = [signal for signal in bundle.signals if signal.severity == "warning"]
notes = [signal for signal in bundle.signals if signal.severity == "note"]
if not failures and not warnings and not notes:
return "\n".join(
[
"<compile_signals>",
"<summary>",
bundle.summary,
"</summary>",
"</compile_signals>",
]
)
summary = bundle.summary
if repeated and failures:
summary += "\nThis failure matches the previous compile attempt."
if failure_streak >= 3 and failures:
summary += f"\nThis is compile failure {failure_streak} in a row."
parts = ["<compile_signals>", "<summary>", summary, "</summary>"]
if failures:
parts.extend(
[
"",
"<failures>",
_render_signal_section("Failures (blocking):", failures),
"</failures>",
]
)
if warnings:
parts.extend(
[
"",
"<warnings>",
_render_signal_section("Warnings (non-blocking):", warnings),
"</warnings>",
]
)
if notes and (failures or warnings):
parts.extend(
[
"",
"<notes>",
_render_signal_section("Notes (informational):", notes),
"</notes>",
]
)
response_rules = _response_rules_for_failures(
failures,
repeated=repeated,
failure_streak=failure_streak,
include_warning_note=bool(warnings),
)
if response_rules:
parts.extend(
[
"",
"<response_rules>",
"Suggested next steps:\n" + "\n".join(response_rules),
"</response_rules>",
]
)
parts.append("</compile_signals>")
return "\n".join(parts)
NAMED_COMPILE_DEFECT_RULE = (
"- Make the next edit a small repair to the named compile defect; do not "
"add new visual detail until that defect is gone."
)
INTENTIONAL_QC_ALLOWANCE_RULE = (
"- If any disconnected or overlapping finding appears intentional, declare "
"or correct explicit allowances for every intentional case. Scope each "
"allowance to the exact reported part or element pair, include a concrete "
"reason, and pair it with an exact proof check such as `expect_overlap`, "
"`expect_contact`, or `expect_within`. Otherwise, use the finding to guide "
"the underlying support path, mount, geometry, or pose fix."
)
EXACT_REPORTED_OVERLAP_RULE = (
"- When authoring an overlap allowance or geometry fix, use the exact "
"reported part/element names; do not authorize nearby geometry while "
"leaving the reported pair unhandled."
)
SMALL_OVERLAP_GEOMETRY_REPAIR_RULE = (
"- If the same overlap pair keeps failing after one allowance/proof attempt, "
"make the smallest geometry edit to the reported elements instead: shorten, "
"thin, offset, or split the colliding feature."
)
PRESERVE_PROMPT_CRITICAL_GEOMETRY_RULE = (
"- Preserve prompt-critical visible geometry while repairing the overlap. "
"Do not replace a hollow/open/cut/curved mesh with a simpler capped "
"primitive unless that simpler shape is still faithful to the requested object."
)
def _response_rules_for_failures(
failures: list[CompileSignal],
*,
repeated: bool,
failure_streak: int,
include_warning_note: bool,
) -> list[str]:
if not failures:
rules: list[str] = []
if include_warning_note:
rules.append(
"- Warnings are not blocking, but they are design evidence and should not be ignored."
)
return rules
primary = failures[0]
rules: list[str]
if primary.kind == "compile_runtime":
rules = [
"- Fix the compile/runtime error first. Geometry repair is blocked until the script executes cleanly.",
"- Read the exception details and location lines before changing unrelated geometry or tests.",
]
elif primary.kind == "single_root_policy":
rules = [
"- Fix the part tree first. This is a structural assembly error, not a local geometry issue.",
"- Add or correct the missing articulation or fixed mount so the model has exactly one rooted assembly.",
"- Do not spend turns tuning geometry until the root structure is valid.",
]
elif primary.kind == "model_validity":
rules = [
"- Fix the model-definition error first. This is a structural validation failure, not a local placement issue.",
"- Read the validation details carefully before changing unrelated geometry or exact checks.",
]
elif primary.kind == "mesh_assets":
rules = [
"- Fix mesh asset readiness first. Missing or unresolved assets block exact geometry checks and downstream QC.",
"- Resolve the referenced mesh names or asset roots before tuning geometry or tests.",
]
elif primary.source == "compiler" and primary.kind == "isolated_part":
rules = [
NAMED_COMPILE_DEFECT_RULE,
"- Treat the compiler-owned floating/disconnected part finding as primary evidence before tuning authored exact checks.",
"- If the support path is not obvious, consider using `probe_model` with `find_floating_parts(...)`, `nearest_neighbors(...)`, or `mount_report(...)` before another geometry edit.",
INTENTIONAL_QC_ALLOWANCE_RULE,
]
elif primary.source == "compiler" and primary.kind == "real_overlap":
rules = [
NAMED_COMPILE_DEFECT_RULE,
"- Compiler-owned overlap QC reported a real 3D overlap in the current pose. First decide whether it looks like intentional embedding or an unintended collision.",
"- If the cause is not obvious from the reported pair and pose, consider using `probe_model` with `pair_report(...)`, `overlap_report(...)`, or `mount_report(...)` before another geometry edit.",
PRESERVE_PROMPT_CRITICAL_GEOMETRY_RULE,
"- If the overlap could be intentional, inspect any existing `allow_overlap(...)` coverage and compare its part and element scope to the reported pair before changing geometry.",
EXACT_REPORTED_OVERLAP_RULE,
INTENTIONAL_QC_ALLOWANCE_RULE,
]
elif primary.kind == "missing_exact_geometry":
rules = [
"- This is usually a deleted or renamed visual-name contract, not a placement failure.",
"- Restore the named visual or update/remove the dependent exact check in the same edit.",
"- Do not rewrite the subassembly just because this repeated.",
]
elif primary.kind == "exact_contact_gap":
rules = [
"- This is a gap, not an overlap.",
"- First verify that the tested pair is the right pair. The support path may be through a different exact element than the one named here.",
"- If the pair or support relationship is unclear, consider using `probe_model` with `gap_report(...)`, `within_report(...)`, or `mount_report(...)` before patching.",
"- If the pair is correct, change geometry or mount placement. Do not relax `contact_tol` unless near-zero contact is actually the intended invariant.",
]
elif primary.kind == "real_overlap":
rules = [
NAMED_COMPILE_DEFECT_RULE,
"- Fix or explicitly justify the real 3D overlap in the tested pose before adding more exact checks.",
"- If the relationship is ambiguous, consider using `probe_model` with `pair_report(...)`, `overlap_report(...)`, or `mount_report(...)` before changing geometry.",
PRESERVE_PROMPT_CRITICAL_GEOMETRY_RULE,
EXACT_REPORTED_OVERLAP_RULE,
INTENTIONAL_QC_ALLOWANCE_RULE,
]
elif primary.kind == "isolated_part":
rules = [
NAMED_COMPILE_DEFECT_RULE,
"- Fix the floating/disconnected part failure before tuning secondary geometry.",
"- If the support path is unclear, consider using `probe_model` with `find_floating_parts(...)`, `nearest_neighbors(...)`, or `mount_report(...)` before changing geometry.",
INTENTIONAL_QC_ALLOWANCE_RULE,
]
else:
rules = [
"- Failures are blocking and should be investigated before adding more geometry or tests.",
"- Classify whether this is a local bug, a wrong representation, or a stale exact-check contract before patching.",
]
if include_warning_note:
rules.append(
"- Warnings are not blocking, but they are design evidence and should not be ignored."
)
if repeated and primary.kind in {"real_overlap", "isolated_part"}:
rules.append(
"- This failure class repeated. A short `probe_model` check is likely to be more informative than another small tweak; consider inspecting the underlying representation or support path before patching again, or add a precise allowance when the finding is intentional."
)
if failure_streak >= 3:
if primary.kind in {"missing_exact_geometry", "exact_contact_gap"}:
rules.append(
"- You are in a repair loop, but this failure family does not call for a geometry rewrite. Audit authored exact-name and exact-pair contracts first."
)
elif primary.kind in {"real_overlap", "isolated_part"}:
rules.append(
"- You are in a repair loop. A short `probe_model` snippet is likely to be more informative than another small placement, tolerance, or primitive tweak. Consider `pair_report(...)`, `mount_report(...)`, `find_floating_parts(...)`, or `nearest_neighbors(...)` before patching again."
)
if primary.kind == "real_overlap":
rules.append(SMALL_OVERLAP_GEOMETRY_REPAIR_RULE)
return rules