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
17 changes: 14 additions & 3 deletions desloppify/app/commands/plan/override/resolve_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from desloppify.app.commands.plan.shared.cluster_membership import cluster_issue_ids
from desloppify.base.output.terminal import colorize
from desloppify.engine._plan.constants import (
STRATEGY_PREFIX,
confirmed_triage_stage_names,
is_synthetic_id,
recorded_unconfirmed_triage_stage_names,
Expand All @@ -15,6 +16,7 @@
TRIAGE_STAGE_PREREQUISITES,
)


def check_cluster_guard(patterns: list[str], plan: dict, state: dict) -> bool:
"""Return True when a cluster-name resolve should be blocked."""
clusters = plan.get("clusters", {})
Expand Down Expand Up @@ -64,10 +66,19 @@ def print_cluster_guard(cluster_name: str, issue_ids: list[str], state: dict) ->
"dim",
)
)


def _is_plan_only_synthetic_id(pattern: str) -> bool:
"""Return whether a synthetic ID has no state-backed work item."""
return is_synthetic_id(pattern) and not pattern.startswith(STRATEGY_PREFIX)


def split_synthetic_patterns(patterns: list[str]) -> tuple[list[str], list[str]]:
"""Partition synthetic workflow/triage patterns from real issue patterns."""
synthetic = [pattern for pattern in patterns if is_synthetic_id(pattern)]
remaining = [pattern for pattern in patterns if not is_synthetic_id(pattern)]
"""Partition plan-only synthetic IDs from state-backed work-item patterns."""
synthetic = [pattern for pattern in patterns if _is_plan_only_synthetic_id(pattern)]
remaining = [
pattern for pattern in patterns if not _is_plan_only_synthetic_id(pattern)
]
return synthetic, remaining


Expand Down
75 changes: 73 additions & 2 deletions desloppify/tests/commands/plan/test_plan_overrides_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import desloppify.app.commands.plan.override.resolve_workflow as resolve_workflow_mod
import desloppify.app.commands.plan.override.skip as override_skip_mod
import desloppify.app.commands.plan.reorder_handlers as reorder_handlers_mod
import desloppify.state as state_mod
from desloppify.base.exception_sets import CommandError


Expand Down Expand Up @@ -48,10 +49,15 @@ def test_override_resolve_helpers_cover_synthetic_split_and_blocked_stages(
capsys,
) -> None:
synthetic, remaining = resolve_helpers_mod.split_synthetic_patterns(
["triage::reflect", "workflow::create-plan", "unused::src/a.py::X"]
[
"triage::reflect",
"workflow::create-plan",
"strategy::owner-boundary-type-safety",
"unused::src/a.py::X",
]
)
assert synthetic == ["triage::reflect", "workflow::create-plan"]
assert remaining == ["unused::src/a.py::X"]
assert remaining == ["strategy::owner-boundary-type-safety", "unused::src/a.py::X"]
assert resolve_helpers_mod.resolve_synthetic_ids(
["triage::reflect", "unused::src/a.py::X"]
) == (["triage::reflect"], ["unused::src/a.py::X"])
Expand Down Expand Up @@ -155,6 +161,71 @@ def test_override_resolve_cmd_confirm_requires_note(capsys) -> None:
assert "--confirm requires --note" in out


def test_override_resolve_cmd_resolves_state_backed_strategy_item(monkeypatch) -> None:
strategy_id = "strategy::owner-boundary-type-safety"
state = state_mod.empty_state()
state["work_items"][strategy_id] = {
"id": strategy_id,
"status": "open",
"detector": "strategy",
"file": ".",
"tier": 2,
"confidence": "high",
"summary": "Migrate the remaining owner-boundary compatibility seams.",
}
plan = {"queue_order": [strategy_id], "clusters": {}}
delegated: list[argparse.Namespace] = []

monkeypatch.setattr(
override_resolve_cmd_mod,
"command_runtime",
lambda _args: SimpleNamespace(state=state),
)
monkeypatch.setattr(override_resolve_cmd_mod, "load_plan", lambda: plan)
monkeypatch.setattr(
override_resolve_cmd_mod, "append_log_entry", lambda *_args, **_kwargs: None
)
monkeypatch.setattr(override_resolve_cmd_mod, "save_plan", lambda _plan: None)
monkeypatch.setattr(
override_resolve_cmd_mod,
"resolve_workflow_patterns",
lambda *_args, **_kwargs: pytest.fail(
"strategy work must use state resolution"
),
)

def resolve_state_backed_item(resolve_args: argparse.Namespace) -> None:
delegated.append(resolve_args)
state_mod.resolve_issues(
state,
strategy_id,
resolve_args.status,
resolve_args.note,
attestation=resolve_args.attest,
)

monkeypatch.setattr(
override_resolve_cmd_mod, "cmd_resolve", resolve_state_backed_item
)

override_resolve_cmd_mod.cmd_plan_resolve(
argparse.Namespace(
patterns=[strategy_id],
attest="I have actually completed the owner-boundary migration and am not gaming the score.",
note="Completed the owner-boundary migration and verified its affected callers.",
confirm=False,
force_resolve=False,
state=None,
lang=None,
path=".",
exclude=None,
)
)

assert delegated[0].patterns == [strategy_id]
assert state["work_items"][strategy_id]["status"] == "fixed"


def test_override_resolve_cmd_handles_synthetic_only_resolution(
monkeypatch, capsys
) -> None:
Expand Down