Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 17:55:16 +08:00
commit a81fb4a29a
15 changed files with 824 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""
Work Items Scanner
Scans code for TODOs, FIXMEs, and loads session objectives.
"""
import re
import json
from pathlib import Path
from typing import Dict, List
class WorkItemsScanner:
"""Scan project for work items"""
def __init__(self, project_path: str = "."):
"""Initialize scanner with project path"""
self.project_path = Path(project_path)
def scan_code_markers(self, patterns: List[str] = None) -> Dict[str, List[Dict]]:
"""Scan code files for TODO/FIXME markers"""
if patterns is None:
patterns = ["*.py", "*.js", "*.ts", "*.tsx", "*.java", "*.go", "*.rs"]
todos = []
fixmes = []
for pattern in patterns:
for file_path in self.project_path.rglob(pattern):
# Skip test files and node_modules
if "test" in str(file_path) or "node_modules" in str(file_path):
continue
try:
with open(file_path, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
# Match TODO: or TODO -
if re.search(r'TODO[:\-]', line, re.IGNORECASE):
comment = line.strip()
todos.append({
"file": str(file_path.relative_to(self.project_path)),
"line": line_num,
"text": comment
})
# Match FIXME: or FIXME -
if re.search(r'FIXME[:\-]', line, re.IGNORECASE):
comment = line.strip()
fixmes.append({
"file": str(file_path.relative_to(self.project_path)),
"line": line_num,
"text": comment
})
except (IOError, UnicodeDecodeError):
# Skip files we can't read
continue
return {
"todos": todos[:20], # Limit to first 20
"fixmes": fixmes[:20]
}
def load_session_objectives(self) -> List[Dict]:
"""Load objectives from .sessions/state.json"""
state_file = self.project_path / ".sessions" / "state.json"
if not state_file.exists():
return []
try:
with open(state_file) as f:
state = json.load(f)
objectives = state.get("objectives", [])
# Convert to list of dicts if it's a simple list
if objectives and isinstance(objectives[0], str):
return [{"text": obj, "completed": False} for obj in objectives]
return objectives
except (json.JSONDecodeError, IOError, KeyError):
return []
def generate_report(self) -> str:
"""Generate work items section"""
lines = []
lines.append("## 📋 Open Work Items")
lines.append("")
# Session objectives
objectives = self.load_session_objectives()
if objectives:
lines.append("**Session Objectives**:")
for obj in objectives:
status = "[x]" if obj.get("completed") else "[ ]"
text = obj.get("text", "Unknown objective")
lines.append(f"- {status} {text}")
lines.append("")
# Code markers
markers = self.scan_code_markers()
todos = markers["todos"]
fixmes = markers["fixmes"]
if todos:
lines.append("**TODOs in Code**:")
for todo in todos[:5]: # Show first 5
lines.append(f"- {todo['file']}:{todo['line']} - {todo['text'][:80]}")
if len(todos) > 5:
lines.append(f"- ... and {len(todos) - 5} more")
lines.append("")
if fixmes:
lines.append("**FIXMEs in Code**:")
for fixme in fixmes[:5]:
lines.append(f"- {fixme['file']}:{fixme['line']} - {fixme['text'][:80]}")
if len(fixmes) > 5:
lines.append(f"- ... and {len(fixmes) - 5} more")
lines.append("")
lines.append(f"**Summary**: {len(todos)} TODOs, {len(fixmes)} FIXMEs")
return "\n".join(lines)