@xenonbyte/req-2-plan 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/README.zh-CN.md +158 -0
  4. package/bin/r2p.js +38 -0
  5. package/docs/req-to-plan-design.md +277 -0
  6. package/package.json +47 -0
  7. package/requirements.txt +1 -0
  8. package/tools/r2p +10 -0
  9. package/tools/r2p-continue +10 -0
  10. package/tools/r2p-gap-open +10 -0
  11. package/tools/r2p-gap-resolve +10 -0
  12. package/tools/r2p-reopen +10 -0
  13. package/tools/r2p-start +10 -0
  14. package/tools/r2p-status +10 -0
  15. package/tools/r2p-switch +10 -0
  16. package/tools/r2p-tier-lock +10 -0
  17. package/tools/workflow_cli/__init__.py +0 -0
  18. package/tools/workflow_cli/__main__.py +5 -0
  19. package/tools/workflow_cli/agent_shortcuts.py +778 -0
  20. package/tools/workflow_cli/agent_templates/claude/SKILL.md +34 -0
  21. package/tools/workflow_cli/agent_templates/claude/commands/r2p-continue.md +16 -0
  22. package/tools/workflow_cli/agent_templates/claude/commands/r2p-gap-open.md +8 -0
  23. package/tools/workflow_cli/agent_templates/claude/commands/r2p-gap-resolve.md +8 -0
  24. package/tools/workflow_cli/agent_templates/claude/commands/r2p-reopen.md +8 -0
  25. package/tools/workflow_cli/agent_templates/claude/commands/r2p-start.md +10 -0
  26. package/tools/workflow_cli/agent_templates/claude/commands/r2p-status.md +8 -0
  27. package/tools/workflow_cli/agent_templates/claude/commands/r2p-switch.md +8 -0
  28. package/tools/workflow_cli/agent_templates/claude/commands/r2p-tier-lock.md +8 -0
  29. package/tools/workflow_cli/agent_templates/codex/skills/r2p-continue/SKILL.md +12 -0
  30. package/tools/workflow_cli/agent_templates/codex/skills/r2p-gap-open/SKILL.md +12 -0
  31. package/tools/workflow_cli/agent_templates/codex/skills/r2p-gap-resolve/SKILL.md +12 -0
  32. package/tools/workflow_cli/agent_templates/codex/skills/r2p-reopen/SKILL.md +12 -0
  33. package/tools/workflow_cli/agent_templates/codex/skills/r2p-start/SKILL.md +14 -0
  34. package/tools/workflow_cli/agent_templates/codex/skills/r2p-status/SKILL.md +12 -0
  35. package/tools/workflow_cli/agent_templates/codex/skills/r2p-switch/SKILL.md +12 -0
  36. package/tools/workflow_cli/agent_templates/codex/skills/r2p-tier-lock/SKILL.md +12 -0
  37. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-continue.toml +4 -0
  38. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-gap-open.toml +4 -0
  39. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-gap-resolve.toml +4 -0
  40. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-reopen.toml +4 -0
  41. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-start.toml +4 -0
  42. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-status.toml +4 -0
  43. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-switch.toml +4 -0
  44. package/tools/workflow_cli/agent_templates/gemini/commands/r2p-tier-lock.toml +4 -0
  45. package/tools/workflow_cli/artifact.py +228 -0
  46. package/tools/workflow_cli/cli.py +1779 -0
  47. package/tools/workflow_cli/gates.py +471 -0
  48. package/tools/workflow_cli/install.py +900 -0
  49. package/tools/workflow_cli/install_cli.py +158 -0
  50. package/tools/workflow_cli/link_expander.py +102 -0
  51. package/tools/workflow_cli/models.py +504 -0
  52. package/tools/workflow_cli/output.py +91 -0
  53. package/tools/workflow_cli/repo_baseline.py +137 -0
  54. package/tools/workflow_cli/state.py +621 -0
  55. package/tools/workflow_cli/tier.py +201 -0
  56. package/tools/workflow_cli/tier_keywords.yaml +45 -0
  57. package/tools/workflow_cli/version.py +1 -0
@@ -0,0 +1,137 @@
1
+ """Scan repo baseline metrics: LOC, language breakdown, monorepo detection, submodules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+
9
+
10
+ @dataclass
11
+ class RepoBaseline:
12
+ """Repository baseline metrics."""
13
+ loc: int = 0
14
+ module_count: int = 0
15
+ is_monorepo: bool = False
16
+ language_breakdown: dict[str, int] = field(default_factory=dict)
17
+ submodule_count: int = 0
18
+ cross_language_refs: list[str] = field(default_factory=list)
19
+
20
+
21
+ EXTENSION_TO_LANGUAGE = {
22
+ ".py": "Python",
23
+ ".ts": "TypeScript",
24
+ ".tsx": "TypeScript",
25
+ ".js": "JavaScript",
26
+ ".jsx": "JavaScript",
27
+ ".go": "Go",
28
+ ".rs": "Rust",
29
+ ".java": "Java",
30
+ ".kt": "Kotlin",
31
+ ".swift": "Swift",
32
+ ".rb": "Ruby",
33
+ ".php": "PHP",
34
+ ".cs": "C#",
35
+ ".cpp": "C++",
36
+ ".cc": "C++",
37
+ ".c": "C",
38
+ ".h": "C",
39
+ ".scala": "Scala",
40
+ ".ex": "Elixir",
41
+ ".exs": "Elixir",
42
+ ".zig": "Zig",
43
+ ".dart": "Dart",
44
+ }
45
+
46
+ MONOREPO_SIGNALS = {
47
+ "package.json",
48
+ "setup.py",
49
+ "Cargo.toml",
50
+ "go.mod",
51
+ "build.gradle",
52
+ "pom.xml",
53
+ }
54
+
55
+ SKIP_DIRS = {
56
+ ".git",
57
+ ".worktrees",
58
+ "node_modules",
59
+ "__pycache__",
60
+ ".venv",
61
+ "venv",
62
+ "dist",
63
+ "build",
64
+ "target",
65
+ ".pytest_cache",
66
+ ".mypy_cache",
67
+ }
68
+
69
+
70
+ def _count_loc(path: Path) -> int:
71
+ """Count non-blank lines of code in a file."""
72
+ try:
73
+ text = path.read_text(encoding="utf-8", errors="ignore")
74
+ return sum(1 for line in text.splitlines() if line.strip())
75
+ except (PermissionError, OSError):
76
+ return 0
77
+
78
+
79
+ def scan_repo_baseline(repo_path: Path) -> RepoBaseline:
80
+ """Scan repo directory and return baseline metrics.
81
+
82
+ Args:
83
+ repo_path: Path to the repository root.
84
+
85
+ Returns:
86
+ RepoBaseline with collected metrics.
87
+ """
88
+ total_loc = 0
89
+ language_breakdown: dict[str, int] = {}
90
+ monorepo_signal_files: dict[str, list[Path]] = {}
91
+ module_dirs: set[Path] = set()
92
+ submodule_count = 0
93
+
94
+ for root, dirs, files in os.walk(repo_path):
95
+ root_path = Path(root)
96
+ # Skip excluded directories
97
+ dirs[:] = [d for d in dirs if d not in SKIP_DIRS and not d.startswith(".")]
98
+
99
+ for fname in files:
100
+ fpath = root_path / fname
101
+ ext = fpath.suffix.lower()
102
+
103
+ # Count lines of code for recognized languages
104
+ if ext in EXTENSION_TO_LANGUAGE:
105
+ lang = EXTENSION_TO_LANGUAGE[ext]
106
+ loc = _count_loc(fpath)
107
+ total_loc += loc
108
+ language_breakdown[lang] = language_breakdown.get(lang, 0) + loc
109
+ module_dirs.add(root_path)
110
+
111
+ # Track monorepo signal files
112
+ if fname in MONOREPO_SIGNALS:
113
+ monorepo_signal_files.setdefault(fname, []).append(fpath)
114
+
115
+ # Count git submodules
116
+ if fname == ".gitmodules":
117
+ try:
118
+ content = fpath.read_text(encoding="utf-8", errors="ignore")
119
+ submodule_count = content.count("[submodule ")
120
+ except (PermissionError, OSError):
121
+ pass
122
+
123
+ # Detect monorepo: 2+ of same signal file type (e.g., 2+ package.json)
124
+ is_monorepo = any(len(paths) >= 2 for paths in monorepo_signal_files.values())
125
+
126
+ # Cross-language refs: list of languages if 2+
127
+ languages = sorted(language_breakdown.keys())
128
+ cross_language_refs = languages if len(languages) >= 2 else []
129
+
130
+ return RepoBaseline(
131
+ loc=total_loc,
132
+ module_count=len(module_dirs),
133
+ is_monorepo=is_monorepo,
134
+ language_breakdown=language_breakdown,
135
+ submodule_count=submodule_count,
136
+ cross_language_refs=cross_language_refs,
137
+ )