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
2 changes: 1 addition & 1 deletion desloppify/engine/_plan/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,10 @@ def ensure_plan_defaults(plan: dict[str, Any]) -> None:

Runtime contract is v8-only. Legacy payloads are upgraded in-place once.
"""
_upgrade_plan_to_v8(plan)
defaults = empty_plan()
for key, value in defaults.items():
plan.setdefault(key, value)
_upgrade_plan_to_v8(plan)
subjective_defer_meta = plan.get("subjective_defer_meta")
if isinstance(subjective_defer_meta, dict):
subjective_defer_meta.pop("force_visible_ids", None)
Expand Down
2 changes: 1 addition & 1 deletion desloppify/engine/_plan/schema/normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
def _rename_key(d: dict, old: str, new: str) -> bool:
if old not in d:
return False
d.setdefault(new, d.pop(old))
d[new] = d.pop(old)
return True


Expand Down
14 changes: 14 additions & 0 deletions desloppify/tests/plan/test_persistence_runtime_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,17 @@ def test_resolve_plan_load_status_migrates_legacy_lifecycle_in_memory_only(tmp_p
assert json.loads(plan_file.read_text(encoding="utf-8"))["refresh_state"][
"lifecycle_phase"
] == "workflow"


def test_resolve_plan_load_status_preserves_legacy_uncommitted_findings(tmp_path):
plan_file = tmp_path / "plan.json"
plan_file.write_text(
'{"version": 7, "created": "2026-01-01T00:00:00+00:00", "updated": "2026-01-01T00:00:00+00:00", "queue_order": [], "deferred": [], "skipped": {}, "active_cluster": null, "overrides": {}, "clusters": {}, "superseded": {}, "promoted_ids": [], "plan_start_scores": {}, "refresh_state": {}, "execution_log": [], "epic_triage_meta": {}, "commit_log": [], "uncommitted_findings": ["review::a.py::issue-1"], "uncommitted_issues": [], "commit_tracking_branch": null}\n',
encoding="utf-8",
)

status = persistence_mod.resolve_plan_load_status(plan_file)

assert status.plan is not None
assert status.plan["uncommitted_issues"] == ["review::a.py::issue-1"]
assert "uncommitted_findings" not in status.plan
15 changes: 15 additions & 0 deletions desloppify/tests/plan/test_schema_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ def test_ensure_container_types_sets_defaults_and_renames_keys() -> None:
assert plan["commit_tracking_branch"] is None


def test_ensure_container_types_rename_overwrites_existing_target_key() -> None:
plan = {
"epic_triage_meta": {"finding_snapshot_hash": "abc", "issue_snapshot_hash": ""},
"uncommitted_findings": ["x"],
"uncommitted_issues": [],
}

migrations.ensure_container_types(plan)

assert plan["epic_triage_meta"]["issue_snapshot_hash"] == "abc"
assert "finding_snapshot_hash" not in plan["epic_triage_meta"]
assert plan["uncommitted_issues"] == ["x"]
assert "uncommitted_findings" not in plan


def test_migrate_synthesis_to_triage_renames_ids_meta_and_cluster_fields() -> None:
plan = {
"queue_order": ["synthesis::a", "other"],
Expand Down