mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
fix(release): require visual selection evidence
This commit is contained in:
parent
1d15ab60a3
commit
a1ae0fa07f
8 changed files with 77 additions and 27 deletions
|
|
@ -131,11 +131,12 @@ def _state(value: Any, field: str) -> dict[str, Any]:
|
|||
def validate_plan(raw: Any) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict):
|
||||
raise PlanError("visual plan must be a JSON object")
|
||||
unknown = set(raw) - {"schema_version", "captures"}
|
||||
unknown = set(raw) - {"schema_version", "decision", "captures"}
|
||||
if unknown:
|
||||
raise PlanError(f"visual plan has unsupported fields: {', '.join(sorted(unknown))}")
|
||||
if raw.get("schema_version") != 1:
|
||||
raise PlanError("visual plan schema_version must be 1")
|
||||
decision = _text(raw.get("decision"), "visual plan decision", maximum=500)
|
||||
captures = raw.get("captures")
|
||||
if not isinstance(captures, list) or len(captures) > MAX_CAPTURES:
|
||||
raise PlanError(f"visual plan captures must be a list with at most {MAX_CAPTURES} entries")
|
||||
|
|
@ -191,7 +192,11 @@ def validate_plan(raw: Any) -> dict[str, Any]:
|
|||
"after": _state(capture.get("after"), f"{field}.after"),
|
||||
}
|
||||
)
|
||||
return {"schema_version": 1, "captures": normalized_captures}
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"decision": decision,
|
||||
"captures": normalized_captures,
|
||||
}
|
||||
|
||||
|
||||
def load_plan(path: str) -> dict[str, Any]:
|
||||
|
|
@ -273,9 +278,10 @@ def json_schema() -> dict[str, Any]:
|
|||
return {
|
||||
"type": "object",
|
||||
"additionalProperties": False,
|
||||
"required": ["schema_version", "captures"],
|
||||
"required": ["schema_version", "decision", "captures"],
|
||||
"properties": {
|
||||
"schema_version": {"const": 1, "type": "integer"},
|
||||
"decision": {"type": "string", "minLength": 1, "maxLength": 500},
|
||||
"captures": {
|
||||
"type": "array",
|
||||
"maxItems": MAX_CAPTURES,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ RENDERER_SPEC.loader.exec_module(renderer)
|
|||
def valid_plan():
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"decision": "This settings comparison makes the responsive redesign immediately visible.",
|
||||
"captures": [
|
||||
{
|
||||
"id": "responsive-settings",
|
||||
|
|
@ -79,6 +80,7 @@ class ReleaseNoteVisualPlanTest(unittest.TestCase):
|
|||
def test_structured_output_schema_carries_public_and_capture_bounds(self):
|
||||
schema = visuals.json_schema()
|
||||
self.assertEqual(schema["properties"]["schema_version"]["type"], "integer")
|
||||
self.assertIn("decision", schema["required"])
|
||||
captures = schema["properties"]["captures"]
|
||||
capture = captures["items"]["properties"]
|
||||
self.assertEqual(captures["maxItems"], visuals.MAX_CAPTURES)
|
||||
|
|
@ -88,6 +90,18 @@ class ReleaseNoteVisualPlanTest(unittest.TestCase):
|
|||
visuals.MAX_STEPS,
|
||||
)
|
||||
|
||||
def test_empty_capture_plan_requires_an_explicit_model_decision(self):
|
||||
with self.assertRaisesRegex(visuals.PlanError, "decision"):
|
||||
visuals.validate_plan({"schema_version": 1, "captures": []})
|
||||
plan = visuals.validate_plan(
|
||||
{
|
||||
"schema_version": 1,
|
||||
"decision": "The investigated changes have no meaningful static visual state.",
|
||||
"captures": [],
|
||||
}
|
||||
)
|
||||
self.assertEqual(plan["captures"], [])
|
||||
|
||||
def test_current_only_capture_has_one_asset(self):
|
||||
raw = valid_plan()
|
||||
raw["captures"][0]["before"] = None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue