Coverage for little_loops / cli / issues / skip.py: 69%
36 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-05-22 16:19 -0500
« prev ^ index » next coverage.py v7.12.0, created at 2026-05-22 16:19 -0500
1"""ll-issues skip: Deprioritize an issue by bumping its priority prefix."""
3from __future__ import annotations
5import re
6import sys
7from typing import TYPE_CHECKING
9if TYPE_CHECKING:
10 import argparse
12 from little_loops.config import BRConfig
15def cmd_skip(config: BRConfig, args: argparse.Namespace) -> int:
16 """Deprioritize an issue by renaming its priority prefix.
18 Renames the issue file to the given priority (default P5), appends a
19 ``## Skip Log`` entry with timestamp and optional reason, and prints the
20 new file path to stdout so callers can confirm the rename.
22 Args:
23 config: Project configuration
24 args: Parsed arguments with .issue_id, .priority, and .reason
26 Returns:
27 Exit code (0 = success, 1 = error)
28 """
29 from little_loops.cli.issues.show import _resolve_issue_id
30 from little_loops.issue_lifecycle import skip_issue
31 from little_loops.issue_parser import IssueParser
33 path = _resolve_issue_id(config, args.issue_id)
34 if path is None:
35 print(f"Error: Issue '{args.issue_id}' not found.", file=sys.stderr)
36 return 1
38 # Only skip non-terminal issues (check frontmatter status, not directory)
39 issue_info = IssueParser(config).parse_file(path)
40 if issue_info.status in ("done", "cancelled", "deferred"):
41 print(
42 f"Error: Issue '{args.issue_id}' has status '{issue_info.status}', not an active issue.",
43 file=sys.stderr,
44 )
45 return 1
47 new_name = re.sub(r"^P\d-", f"{args.priority}-", path.name)
48 new_path = path.parent / new_name
50 if path == new_path:
51 # Already at target priority — nothing to rename, still print path
52 try:
53 rel = str(new_path.relative_to(config.project_root))
54 except ValueError:
55 rel = str(new_path)
56 print(f"Deprioritized {args.issue_id} to {args.priority}: {rel}")
57 return 0
59 try:
60 skip_issue(path, new_path, args.reason)
61 except FileExistsError as exc:
62 print(f"Error: {exc}", file=sys.stderr)
63 return 1
65 try:
66 rel = str(new_path.relative_to(config.project_root))
67 except ValueError:
68 rel = str(new_path)
70 print(f"Deprioritized {args.issue_id} to {args.priority}: {rel}")
71 return 0