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

39 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2026-06-29 00:54 -0500

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

2 

3from __future__ import annotations 

4 

5import argparse 

6import json 

7from typing import TYPE_CHECKING 

8 

9if TYPE_CHECKING: 

10 from little_loops.config import BRConfig 

11 

12 

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

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

15 

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

17 ALL_DONE (exit 0) 

18 

19 Args: 

20 config: Project configuration 

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

22 

23 Returns: 

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

25 """ 

26 from little_loops.cli_args import parse_issue_ids 

27 from little_loops.issue_parser import find_issues, is_formatted 

28 

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

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

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

32 

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

34 default_ready: int = getattr(args, "ready_threshold", 85) 

35 default_outcome: int = getattr(args, "outcome_threshold", 70) 

36 

37 config_path = config.project_root / ".ll" / "ll-config.json" 

38 try: 

39 cg = json.loads(config_path.read_text()).get("commands", {}).get("confidence_gate", {}) 

40 ready_threshold: int = cg.get("readiness_threshold", default_ready) 

41 outcome_threshold: int = cg.get("outcome_threshold", default_outcome) 

42 except Exception: 

43 ready_threshold = default_ready 

44 outcome_threshold = default_outcome 

45 

46 for issue in issues: 

47 if not is_formatted(issue.path): 

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

49 return 1 

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

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

52 return 1 

53 cs = issue.confidence_score 

54 oc = issue.outcome_confidence 

55 if cs is None or oc is None: 

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

57 return 1 

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

59 if cs < ready_threshold or oc < outcome_threshold: 

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

61 return 1 

62 

63 print("ALL_DONE") 

64 return 0