Coverage for little_loops / cli / issues / next_action.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2026-05-22 16:19 -0500

1"""ll-issues next-action: Print the next refinement action needed across all active issues.""" 

2 

3from __future__ import annotations 

4 

5import argparse 

6from typing import TYPE_CHECKING 

7 

8if TYPE_CHECKING: 

9 from little_loops.config import BRConfig 

10 

11 

12def cmd_next_action(config: BRConfig, args: argparse.Namespace) -> int: 

13 """Print the next refinement action needed across all active issues. 

14 

15 Output: NEEDS_FORMAT|NEEDS_VERIFY|NEEDS_SCORE|NEEDS_REFINE <id> (exit 1) 

16 ALL_DONE (exit 0) 

17 

18 Args: 

19 config: Project configuration 

20 args: Parsed arguments with optional .refine_cap, .ready_threshold, .outcome_threshold 

21 

22 Returns: 

23 Exit code (1 = work remains, 0 = all done) 

24 """ 

25 from little_loops.cli_args import parse_issue_ids 

26 from little_loops.issue_parser import find_issues, is_formatted 

27 

28 skip_ids = parse_issue_ids(getattr(args, "skip", None)) 

29 issues = find_issues(config, skip_ids=skip_ids or None) 

30 issues.sort(key=lambda i: (i.priority_int, -int(i.issue_id.split("-")[1]))) 

31 

32 refine_cap: int = getattr(args, "refine_cap", 5) 

33 ready_threshold: int = getattr(args, "ready_threshold", 85) 

34 outcome_threshold: int = getattr(args, "outcome_threshold", 70) 

35 

36 for issue in issues: 

37 if not is_formatted(issue.path): 

38 print(f"NEEDS_FORMAT {issue.issue_id}") 

39 return 1 

40 if "/ll:verify-issues" not in issue.session_commands: 

41 print(f"NEEDS_VERIFY {issue.issue_id}") 

42 return 1 

43 cs = issue.confidence_score 

44 oc = issue.outcome_confidence 

45 if cs is None or oc is None: 

46 print(f"NEEDS_SCORE {issue.issue_id}") 

47 return 1 

48 if issue.session_command_counts.get("/ll:refine-issue", 0) < refine_cap: 

49 if cs < ready_threshold or oc < outcome_threshold: 

50 print(f"NEEDS_REFINE {issue.issue_id}") 

51 return 1 

52 

53 print("ALL_DONE") 

54 return 0