|
5 | 5 | from datetime import UTC, datetime |
6 | 6 | from unittest.mock import MagicMock |
7 | 7 |
|
| 8 | +import pytest |
| 9 | + |
8 | 10 | from ddev.ai.phases.base import Phase, PhaseOutcome, _make_memory_resolver |
9 | 11 | from ddev.ai.phases.checkpoint import CheckpointManager |
10 | 12 | from ddev.ai.phases.config import PhaseConfig |
@@ -226,6 +228,20 @@ async def test_process_message_writes_memory_and_checkpoint(flow_dir, message_qu |
226 | 228 | assert checkpoint["finished_at"] |
227 | 229 |
|
228 | 230 |
|
| 231 | +@pytest.mark.parametrize( |
| 232 | + "reserved_key", |
| 233 | + ["status", "started_at", "finished_at", "tokens", "memory_path"], |
| 234 | +) |
| 235 | +async def test_extra_checkpoint_cannot_override_reserved_keys(flow_dir, message_queue, reserved_key): |
| 236 | + outcome = PhaseOutcome(memory_text="m", extra_checkpoint={reserved_key: "evil"}) |
| 237 | + phase, mgr = _make_stub_phase(flow_dir, message_queue, outcome=outcome) |
| 238 | + |
| 239 | + with pytest.raises(ValueError, match=f"reserved keys.*{reserved_key}"): |
| 240 | + await phase.process_message(PhaseTrigger(id="start", phase_id=None)) |
| 241 | + |
| 242 | + assert mgr.read() == {} |
| 243 | + |
| 244 | + |
229 | 245 | async def test_failed_phase_omits_memory_path(flow_dir, message_queue): |
230 | 246 | phase, mgr = _make_stub_phase(flow_dir, message_queue) |
231 | 247 |
|
|
0 commit comments