development-hub/src/development_hub/services/progress_writer.py

178 lines
5.1 KiB
Python

"""Service for writing progress log entries."""
from datetime import date
from pathlib import Path
from development_hub.paths import paths
class ProgressWriter:
"""Writes daily progress log entries to markdown files."""
def __init__(self, progress_dir: Path | None = None):
"""Initialize progress writer.
Args:
progress_dir: Directory for progress files. Defaults to settings value.
"""
self._progress_dir = progress_dir or paths.progress_dir
def get_today_path(self) -> Path:
"""Get path to today's progress file."""
today = date.today()
filename = today.strftime("%Y-%m-%d.md")
return self._progress_dir / filename
def file_exists(self) -> bool:
"""Check if today's progress file already exists."""
return self.get_today_path().exists()
def create_progress_entry(
self,
projects: list[str],
focus: list[str],
completed: list[str],
in_progress: list[str],
blocked: list[str] | None = None,
next_tasks: list[str] | None = None,
notes: str | None = None,
) -> Path:
"""Create or update today's progress log entry.
Args:
projects: List of project keys worked on
focus: Primary focus items
completed: Completed tasks
in_progress: Tasks in progress
blocked: Blocked items (optional)
next_tasks: Next up items (optional)
notes: Additional notes (optional)
Returns:
Path to the created/updated file
"""
today = date.today()
path = self.get_today_path()
# Build content
lines = [
"---",
f"date: {today.isoformat()}",
f"projects: [{', '.join(projects)}]",
"---",
"",
]
# Focus section
if focus:
lines.append("## Focus")
for item in focus:
lines.append(f"- {item}")
lines.append("")
# Completed section
lines.append("## Completed")
if completed:
for item in completed:
lines.append(f"- [x] {item}")
else:
lines.append("(none yet)")
lines.append("")
# In Progress section
lines.append("## In Progress")
if in_progress:
for item in in_progress:
lines.append(f"- [ ] {item}")
else:
lines.append("(none)")
lines.append("")
# Blocked section
lines.append("## Blocked")
if blocked:
for item in blocked:
lines.append(f"- {item}")
else:
lines.append("(none)")
lines.append("")
# Next section
if next_tasks:
lines.append("## Next")
for i, item in enumerate(next_tasks, 1):
lines.append(f"{i}. {item}")
lines.append("")
# Notes section
if notes:
lines.append("## Notes")
lines.append(notes)
lines.append("")
# Write file
self._progress_dir.mkdir(parents=True, exist_ok=True)
path.write_text("\n".join(lines))
return path
def append_completed(self, task: str) -> bool:
"""Append a completed task to today's progress.
Args:
task: The completed task description
Returns:
True if successful, False if no progress file exists
"""
path = self.get_today_path()
if not path.exists():
return False
content = path.read_text()
lines = content.split("\n")
# Find the Completed section
for i, line in enumerate(lines):
if line.strip() == "## Completed":
# Find where to insert (after the header)
insert_idx = i + 1
# Skip (none yet) if present
if insert_idx < len(lines) and lines[insert_idx].strip() == "(none yet)":
lines[insert_idx] = f"- [x] {task}"
else:
lines.insert(insert_idx, f"- [x] {task}")
path.write_text("\n".join(lines))
return True
return False
def append_in_progress(self, task: str) -> bool:
"""Append an in-progress task to today's progress.
Args:
task: The task description
Returns:
True if successful, False if no progress file exists
"""
path = self.get_today_path()
if not path.exists():
return False
content = path.read_text()
lines = content.split("\n")
# Find the In Progress section
for i, line in enumerate(lines):
if line.strip() == "## In Progress":
insert_idx = i + 1
if insert_idx < len(lines) and lines[insert_idx].strip() == "(none)":
lines[insert_idx] = f"- [ ] {task}"
else:
lines.insert(insert_idx, f"- [ ] {task}")
path.write_text("\n".join(lines))
return True
return False