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
« 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."""
3from __future__ import annotations
5import argparse
6import json
7from typing import TYPE_CHECKING
9if TYPE_CHECKING:
10 from little_loops.config import BRConfig
13def cmd_next_action(config: BRConfig, args: argparse.Namespace) -> int:
14 """Print the next refinement action needed across all active issues.
16 Output: NEEDS_FORMAT|NEEDS_VERIFY|NEEDS_SCORE|NEEDS_REFINE <id> (exit 1)
17 ALL_DONE (exit 0)
19 Args:
20 config: Project configuration
21 args: Parsed arguments with optional .refine_cap, .ready_threshold, .outcome_threshold
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
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])))
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)
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
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
63 print("ALL_DONE")
64 return 0