1"""ll-issues anchor-sweep: rewrite file:line refs in active issue files."""

2

3 from __future__ import annotations

4

5 import argparse

6 import sys

7 from pathlib import Path

8 from typing import TYPE_CHECKING

9

10 if TYPE_CHECKING:

11 from little_loops.config import BRConfig

12

13

14 def cmd_anchor_sweep(config: BRConfig, args: argparse.Namespace) -> int:

15 """Rewrite file:line references in active issue files to anchor form.

16

17 Scans bugs/, features/, and enhancements/ under the issues directory for

18 references like ``file.py:42`` outside code fences, resolves each to its

19 enclosing function/class/section, and rewrites in-place.

20

21 Args:

22 config: Project configuration.

23 args: Parsed arguments with .dry_run and .issues_dir.

24

25 Returns:

26 0 on success, 1 on error.

27 """

28 from little_loops.issues.anchor_sweep import sweep_issues

29

30 issues_dir = Path(args.issues_dir)

31 if not issues_dir.is_absolute():

32 issues_dir = config.project_root / issues_dir

33

34 if not issues_dir.is_dir():

35 print(f"Error: issues directory not found: {issues_dir}", file=sys.stderr)

36 return 1

37

38 dry_run: bool = args.dry_run

39 result = sweep_issues(issues_dir, dry_run=dry_run)

40

41 mode = "[dry-run] " if dry_run else ""

42 if result.changes:

43 for change in result.changes:

44 print(f"{mode}{change}")

45 if dry_run:

46 print(

47 f"\n{mode}Would modify {len(result.changes)} file(s). Re-run without --dry-run to apply."

48 )

49 else:

50 print(f"\nModified {len(result.modified_files)} file(s).")

51 else:

52 print(f"{mode}No file:line references found in active issue files.")

53

54 if result.skipped_refs:

55 print(

56 f"Warning: {result.skipped_refs} reference(s) could not be resolved and were left unchanged.",

57 file=sys.stderr,

58 )

59

60 return 0