feat(#90): IMP-56 u1-u19 catch-up before final close (post-u20 push fix)
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 20s
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 20s
u1: text_overrides axis in user_overrides_io u2: structure_overrides axis in user_overrides_io u3: vite allowlist for new endpoints u4: text_override_resolver u5: Step 12 text_overrides apply in phase_z2_pipeline u6: structure_override_resolver u7: text_path_stamper u8: SlideCanvas text-edit capture u9: SlideCanvas structure-edit overlay u10: userOverridesApi service extension u11: designAgent types extension u12: slidePlanUtils restore u13: user_overrides endpoint tests u14: user_overrides restore tests u15: pipeline fallback tests u16: edit-mode state + gating tests u17: slide_base print mode CSS u18: /api/connect endpoint (vite) u19: /api/export endpoint (vite) Recovery scope: 29 files (12 modified + 17 new). u20 already pushed in 9439575; this commit lands u1-u19 that were authored but not committed before #90 was externally closed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,13 @@
|
||||
Covers the persisted axes called out in the Stage 2 plan
|
||||
(IMP-51 #79 u1 extended this to 5 axes by adding ``image_overrides``;
|
||||
IMP-45 #74 u1 extended to 6 axes by adding ``slide_css``;
|
||||
IMP-55 #93 u1 extended to 7 axes by adding ``manual_section_assignment``):
|
||||
IMP-55 #93 u1 extended to 7 axes by adding ``manual_section_assignment``;
|
||||
IMP-56 #90 u1 extended to 8 axes by adding ``text_overrides``;
|
||||
IMP-56 #90 u2 extended to 9 axes by adding ``structure_overrides`` —
|
||||
scope LOCKED to ``{slot_order, hidden_slots}``; frame swap stays on the
|
||||
existing ``frames`` axis):
|
||||
|
||||
1. Round-trip ``save`` → ``load`` (7 KNOWN_AXES + foreign top-level keys).
|
||||
1. Round-trip ``save`` → ``load`` (9 KNOWN_AXES + foreign top-level keys).
|
||||
2. Unknown-key passthrough (foreign axes preserved across partial merges).
|
||||
3. Missing / corrupt / non-object behavior (graceful ``{}`` + stderr warning).
|
||||
4. Invalid keys (``InvalidOverrideKey`` raised on traversal / separators /
|
||||
@@ -123,25 +127,50 @@ def _full_payload() -> dict:
|
||||
},
|
||||
"slide_css": "<style>.slide .frame-process-product .label { font-size: 14px; }</style>",
|
||||
"manual_section_assignment": True,
|
||||
"text_overrides": {"zone-top": {"slot_title.0": "edited headline"}},
|
||||
"structure_overrides": {
|
||||
"zone-top": {
|
||||
"slot_order": ["slot_title", "slot_body"],
|
||||
"hidden_slots": ["slot_caption"],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_known_axes_includes_image_overrides():
|
||||
"""IMP-51 #79 u1 — ``image_overrides`` is a known axis (now 7 total)."""
|
||||
"""IMP-51 #79 u1 — ``image_overrides`` is a known axis (now 9 total)."""
|
||||
assert "image_overrides" in KNOWN_AXES
|
||||
assert len(KNOWN_AXES) == 7
|
||||
assert len(KNOWN_AXES) == 9
|
||||
|
||||
|
||||
def test_known_axes_includes_slide_css():
|
||||
"""IMP-45 #74 u1 — ``slide_css`` is a known axis (7 total)."""
|
||||
"""IMP-45 #74 u1 — ``slide_css`` is a known axis (9 total)."""
|
||||
assert "slide_css" in KNOWN_AXES
|
||||
assert len(KNOWN_AXES) == 7
|
||||
assert len(KNOWN_AXES) == 9
|
||||
|
||||
|
||||
def test_known_axes_includes_manual_section_assignment():
|
||||
"""IMP-55 #93 u1 — bool intent marker is a known axis (7 total)."""
|
||||
"""IMP-55 #93 u1 — bool intent marker is a known axis (9 total)."""
|
||||
assert "manual_section_assignment" in KNOWN_AXES
|
||||
assert len(KNOWN_AXES) == 7
|
||||
assert len(KNOWN_AXES) == 9
|
||||
|
||||
|
||||
def test_known_axes_includes_text_overrides():
|
||||
"""IMP-56 #90 u1 — ``text_overrides`` is a known axis (9 total)."""
|
||||
assert "text_overrides" in KNOWN_AXES
|
||||
assert len(KNOWN_AXES) == 9
|
||||
|
||||
|
||||
def test_known_axes_includes_structure_overrides():
|
||||
"""IMP-56 #90 u2 — ``structure_overrides`` is a known axis (9 total).
|
||||
|
||||
Scope is locked to ``{slot_order, hidden_slots}`` only; frame swap
|
||||
stays on the existing ``frames`` axis (verified at resolver u6 + Step
|
||||
12 apply u7). The IO layer itself only enforces the axis name + the
|
||||
foreign-key preservation invariant.
|
||||
"""
|
||||
assert "structure_overrides" in KNOWN_AXES
|
||||
assert len(KNOWN_AXES) == 9
|
||||
|
||||
|
||||
def test_save_then_load_round_trip(tmp_path):
|
||||
@@ -170,6 +199,8 @@ def test_save_partial_payload_preserves_other_axes(tmp_path):
|
||||
assert loaded["image_overrides"] == _full_payload()["image_overrides"]
|
||||
assert loaded["slide_css"] == _full_payload()["slide_css"]
|
||||
assert loaded["manual_section_assignment"] is True
|
||||
assert loaded["text_overrides"] == _full_payload()["text_overrides"]
|
||||
assert loaded["structure_overrides"] == _full_payload()["structure_overrides"]
|
||||
|
||||
|
||||
def test_save_partial_image_overrides_preserves_other_axes(tmp_path):
|
||||
@@ -193,6 +224,8 @@ def test_save_partial_image_overrides_preserves_other_axes(tmp_path):
|
||||
assert loaded["frames"] == _full_payload()["frames"]
|
||||
assert loaded["slide_css"] == _full_payload()["slide_css"]
|
||||
assert loaded["manual_section_assignment"] is True
|
||||
assert loaded["text_overrides"] == _full_payload()["text_overrides"]
|
||||
assert loaded["structure_overrides"] == _full_payload()["structure_overrides"]
|
||||
|
||||
|
||||
def test_save_axis_replaces_not_deep_merges(tmp_path):
|
||||
@@ -265,12 +298,15 @@ def test_save_writes_pretty_sorted_json_for_diffability(tmp_path):
|
||||
key = "03"
|
||||
save(key, _full_payload(), root=tmp_path)
|
||||
raw = (tmp_path / "03.json").read_text(encoding="utf-8")
|
||||
# sort_keys=True → KNOWN_AXES come out alphabetically
|
||||
# sort_keys=True → KNOWN_AXES come out alphabetically. ``structure_overrides``
|
||||
# (IMP-56 #90 u2) sorts between ``slide_css`` and ``text_overrides``.
|
||||
pos_frames = raw.index('"frames"')
|
||||
pos_image_overrides = raw.index('"image_overrides"')
|
||||
pos_layout = raw.index('"layout"')
|
||||
pos_manual = raw.index('"manual_section_assignment"')
|
||||
pos_slide_css = raw.index('"slide_css"')
|
||||
pos_structure_overrides = raw.index('"structure_overrides"')
|
||||
pos_text_overrides = raw.index('"text_overrides"')
|
||||
pos_zg = raw.index('"zone_geometries"')
|
||||
pos_zs = raw.index('"zone_sections"')
|
||||
assert (
|
||||
@@ -279,6 +315,8 @@ def test_save_writes_pretty_sorted_json_for_diffability(tmp_path):
|
||||
< pos_layout
|
||||
< pos_manual
|
||||
< pos_slide_css
|
||||
< pos_structure_overrides
|
||||
< pos_text_overrides
|
||||
< pos_zg
|
||||
< pos_zs
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user