feat(t021): auto-mark tasks complete from commit messages in release#208
feat(t021): auto-mark tasks complete from commit messages in release#208marcusquinn merged 1 commit intomainfrom
Conversation
- Add extract_task_ids_from_commits() to parse task IDs (t001, t001.1, etc.) - Add auto_mark_tasks_complete() to update TODO.md checkboxes - Integrate into release workflow after changelog generation - Add standalone commands: auto-mark-tasks, list-task-ids - Update release.md documentation with new automatic behavior Supports patterns: t001, feat(t001):, fix(t002):, closes t003, mark t004
Summary of ChangesHello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant enhancement to the release workflow by automating the process of marking tasks as complete in the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
WalkthroughThe pull request introduces automated task completion tracking for a version management system. The script now extracts task IDs from commit messages, automatically marks matching tasks as complete in TODO.md with timestamps, and integrates this automation into the release workflow. Changes
Sequence Diagram(s)sequenceDiagram
participant Release as Release Process
participant Script as version-manager.sh
participant Git as Git Repository
participant TODO as TODO.md
participant Commit as Commit History
Release->>Script: Initiate release
Script->>Git: Query commits since last tag
Git->>Commit: Fetch commit messages
Commit-->>Script: Return commits
Script->>Script: extract_task_ids_from_commits()
Script->>TODO: Read current tasks
TODO-->>Script: Return task entries
Script->>Script: Parse and match task IDs
Script->>TODO: Update checkboxes & add timestamps
Script->>Git: Stage TODO.md
Script->>Git: Commit version changes
Git-->>Release: Release continues
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sun Jan 25 15:04:16 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Code Review
This pull request introduces a great new feature to automatically mark tasks in TODO.md as complete based on commit messages. The implementation is well-structured, adding new functions and CLI commands cleanly. My review focuses on a significant performance and portability improvement in the auto_mark_tasks_complete function. The current implementation reads and writes the TODO.md file for every task, which can be very slow with a large task file. I've suggested a refactoring that processes the file only once, making it much more efficient and robust.
| auto_mark_tasks_complete() { | ||
| local todo_file="$REPO_ROOT/TODO.md" | ||
| local today | ||
| today=$(date +%Y-%m-%dT%H:%M:%SZ) | ||
| local today_short | ||
| today_short=$(date +%Y-%m-%d) | ||
|
|
||
| if [[ ! -f "$todo_file" ]]; then | ||
| print_warning "TODO.md not found, skipping task auto-completion" | ||
| return 0 | ||
| fi | ||
|
|
||
| print_info "Scanning commits for task IDs to auto-mark complete..." | ||
|
|
||
| local task_ids | ||
| task_ids=$(extract_task_ids_from_commits) | ||
|
|
||
| if [[ -z "$task_ids" ]]; then | ||
| print_info "No task IDs found in commits since last release" | ||
| return 0 | ||
| fi | ||
|
|
||
| local count=0 | ||
| local marked_tasks="" | ||
|
|
||
| # Process each task ID | ||
| while IFS= read -r task_id; do | ||
| [[ -z "$task_id" ]] && continue | ||
|
|
||
| # Build regex patterns (avoids shellcheck SC1087 false positive with [[:space:]]) | ||
| local unchecked_pattern="^[[:space:]]*- \\[ \\] ${task_id}[[:space:]]" | ||
| local checked_pattern="^[[:space:]]*- \\[x\\] ${task_id}[[:space:]]" | ||
|
|
||
| # Check if task exists and is not already complete | ||
| # Pattern: - [ ] t001 ... (not already checked) | ||
| if grep -qE "$unchecked_pattern" "$todo_file"; then | ||
| # Mark task complete: change [ ] to [x] and add completed: timestamp | ||
| # Use sed to update the line | ||
| local escaped_id | ||
| escaped_id=$(echo "$task_id" | sed 's/\./\\./g') | ||
|
|
||
| # Build sed patterns | ||
| local sed_unchecked_pattern="^[[:space:]]*- \\[ \\] ${escaped_id}[[:space:]]" | ||
|
|
||
| # Check if line already has completed: field | ||
| if grep -E "$sed_unchecked_pattern" "$todo_file" | grep -q "completed:"; then | ||
| # Just change checkbox | ||
| sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]]\\)/\\1- [x] \\2/" "$todo_file" | ||
| else | ||
| # Change checkbox and add completed: timestamp | ||
| sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]].*\\)\$/\\1- [x] \\2 completed:$today_short/" "$todo_file" | ||
| fi | ||
|
|
||
| count=$((count + 1)) | ||
| marked_tasks="$marked_tasks $task_id" | ||
| print_success "Marked $task_id as complete" | ||
| elif grep -qE "$checked_pattern" "$todo_file"; then | ||
| print_info "Task $task_id already marked complete" | ||
| else | ||
| print_warning "Task $task_id not found in TODO.md (may be subtask or already moved)" | ||
| fi | ||
| done <<< "$task_ids" | ||
|
|
||
| if [[ $count -gt 0 ]]; then | ||
| print_success "Auto-marked $count task(s) complete:$marked_tasks" | ||
| fi | ||
|
|
||
| return 0 | ||
| } |
There was a problem hiding this comment.
This function has performance and portability issues that could become problematic as TODO.md grows.
1. Performance: The function iterates through each task_id and runs grep and sed -i inside the loop. This means TODO.md is read and re-written for every single task found in the commits. For 10 tasks, the file is processed 10 times, which is inefficient.
2. Portability: The sed -i '' command is specific to BSD sed (like on macOS) and will fail on systems with GNU sed (common on Linux).
I've suggested a refactoring that addresses both issues by:
- Processing
TODO.mdonly once using awhile readloop in bash. - Using an associative array for efficient task lookups.
- Avoiding
sed -iin favor of writing to a temporary file, which is both more efficient and portable.
This new implementation is much more scalable and robust.
auto_mark_tasks_complete() {
local todo_file="$REPO_ROOT/TODO.md"
local today_short
today_short=$(date +%Y-%m-%d)
if [[ ! -f "$todo_file" ]]; then
print_warning "TODO.md not found, skipping task auto-completion"
return 0
fi
print_info "Scanning commits for task IDs to auto-mark complete..."
local task_ids
task_ids=$(extract_task_ids_from_commits)
if [[ -z "$task_ids" ]]; then
print_info "No task IDs found in commits since last release"
return 0
fi
# Use an associative array for efficient lookups.
declare -A tasks_to_process
while IFS= read -r task_id; do
[[ -z "$task_id" ]] && continue
tasks_to_process["$task_id"]="unprocessed"
done <<< "$task_ids"
local temp_file
temp_file=$(mktemp)
# Process TODO.md once, writing to a temporary file. This is much more
# efficient than reading and writing the file for each task.
while IFS= read -r line; do
local task_id
# Match unchecked tasks: - [ ] t...
if [[ "$line" =~ ^[[:space:]]*-' '['' '']'[[:space:]]+(t[0-9]{3}(\.[0-9]+)*) ]]; then
task_id="${BASH_REMATCH[1]}"
if [[ "${tasks_to_process[$task_id]:-}" == "unprocessed" ]]; then
line="${line/\\[ \\]/\\[x\\]}"
if [[ ! "$line" =~ completed: ]]; then
# Append to end of line, stripping trailing whitespace first
line="${line%%[[:space:]]}"
line="$line completed:$today_short"
fi
tasks_to_process["$task_id"]="marked"
fi
# Match already checked tasks: - [x] t...
elif [[ "$line" =~ ^[[:space:]]*-' '['x']'[[:space:]]+(t[0-9]{3}(\.[0-9]+)*) ]]; then
task_id="${BASH_REMATCH[1]}"
if [[ "${tasks_to_process[$task_id]:-}" == "unprocessed" ]]; then
tasks_to_process["$task_id"]="already_marked"
fi
fi
echo "$line" >> "$temp_file"
done < "$todo_file"
mv "$temp_file" "$todo_file"
local count=0
local marked_tasks=""
# Report results in the same order as found in commits
while IFS= read -r task_id; do
[[ -z "$task_id" ]] && continue
case "${tasks_to_process[$task_id]:-unprocessed}" in
marked)
count=$((count + 1))
marked_tasks="$marked_tasks $task_id"
print_success "Marked $task_id as complete"
;;
already_marked)
print_info "Task $task_id already marked complete"
;;
unprocessed)
print_warning "Task $task_id not found in TODO.md (may be subtask or already moved)"
;;
esac
done <<< "$task_ids"
if [[ $count -gt 0 ]]; then
print_success "Auto-marked $count task(s) complete:$marked_tasks"
fi
return 0
}There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.agent/scripts/version-manager.sh:
- Around line 551-604: In auto_mark_tasks_complete(), the grep/sed patterns
require a trailing space after the task ID and use today_short; update the
regexes to allow the task ID to be followed by either whitespace or end-of-line
(e.g., use "(?:$|[[:space:]])" or a word-boundary-style pattern) for
unchecked_pattern, checked_pattern and sed_unchecked_pattern (and the sed match
groups that reference ${escaped_id}), and replace uses of today_short with the
full ISO timestamp variable today when appending the completed: timestamp so
completed entries use the full timestamp.
| # Function to auto-mark tasks complete in TODO.md based on commit messages | ||
| # Parses commits since last tag for task IDs and marks them complete | ||
| auto_mark_tasks_complete() { | ||
| local todo_file="$REPO_ROOT/TODO.md" | ||
| local today | ||
| today=$(date +%Y-%m-%dT%H:%M:%SZ) | ||
| local today_short | ||
| today_short=$(date +%Y-%m-%d) | ||
|
|
||
| if [[ ! -f "$todo_file" ]]; then | ||
| print_warning "TODO.md not found, skipping task auto-completion" | ||
| return 0 | ||
| fi | ||
|
|
||
| print_info "Scanning commits for task IDs to auto-mark complete..." | ||
|
|
||
| local task_ids | ||
| task_ids=$(extract_task_ids_from_commits) | ||
|
|
||
| if [[ -z "$task_ids" ]]; then | ||
| print_info "No task IDs found in commits since last release" | ||
| return 0 | ||
| fi | ||
|
|
||
| local count=0 | ||
| local marked_tasks="" | ||
|
|
||
| # Process each task ID | ||
| while IFS= read -r task_id; do | ||
| [[ -z "$task_id" ]] && continue | ||
|
|
||
| # Build regex patterns (avoids shellcheck SC1087 false positive with [[:space:]]) | ||
| local unchecked_pattern="^[[:space:]]*- \\[ \\] ${task_id}[[:space:]]" | ||
| local checked_pattern="^[[:space:]]*- \\[x\\] ${task_id}[[:space:]]" | ||
|
|
||
| # Check if task exists and is not already complete | ||
| # Pattern: - [ ] t001 ... (not already checked) | ||
| if grep -qE "$unchecked_pattern" "$todo_file"; then | ||
| # Mark task complete: change [ ] to [x] and add completed: timestamp | ||
| # Use sed to update the line | ||
| local escaped_id | ||
| escaped_id=$(echo "$task_id" | sed 's/\./\\./g') | ||
|
|
||
| # Build sed patterns | ||
| local sed_unchecked_pattern="^[[:space:]]*- \\[ \\] ${escaped_id}[[:space:]]" | ||
|
|
||
| # Check if line already has completed: field | ||
| if grep -E "$sed_unchecked_pattern" "$todo_file" | grep -q "completed:"; then | ||
| # Just change checkbox | ||
| sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]]\\)/\\1- [x] \\2/" "$todo_file" | ||
| else | ||
| # Change checkbox and add completed: timestamp | ||
| sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]].*\\)\$/\\1- [x] \\2 completed:$today_short/" "$todo_file" | ||
| fi |
There was a problem hiding this comment.
Make TODO matching tolerate end‑of‑line task IDs and use full timestamps.
Current patterns require a trailing space after the task ID, so lines like - [ ] t001 won’t match. Also, today (full ISO) is computed but the shorter date is used, which diverges from the workflow examples.
🔧 Proposed fix
- local today
- today=$(date +%Y-%m-%dT%H:%M:%SZ)
- local today_short
- today_short=$(date +%Y-%m-%d)
+ local today
+ today=$(date +%Y-%m-%dT%H:%M:%SZ)
@@
- local unchecked_pattern="^[[:space:]]*- \\[ \\] ${task_id}[[:space:]]"
- local checked_pattern="^[[:space:]]*- \\[x\\] ${task_id}[[:space:]]"
+ local unchecked_pattern="^[[:space:]]*- \\[ \\] ${task_id}([[:space:]]|$)"
+ local checked_pattern="^[[:space:]]*- \\[x\\] ${task_id}([[:space:]]|$)"
@@
- local sed_unchecked_pattern="^[[:space:]]*- \\[ \\] ${escaped_id}[[:space:]]"
+ local sed_unchecked_pattern="^[[:space:]]*- \\[ \\] ${escaped_id}([[:space:]]|$)"
@@
- sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]]\\)/\\1- [x] \\2/" "$todo_file"
+ sed -i '' -E "s/^([[:space:]]*)- \\[ \\] (${escaped_id})([[:space:]].*)?$/\\1- [x] \\2\\3/" "$todo_file"
else
- sed -i '' "s/^\\([[:space:]]*\\)- \\[ \\] \\(${escaped_id}[[:space:]].*\\)\$/\\1- [x] \\2 completed:$today_short/" "$todo_file"
+ sed -i '' -E "s/^([[:space:]]*)- \\[ \\] (${escaped_id})([[:space:]].*)?$/\\1- [x] \\2\\3 completed:$today/" "$todo_file"
fi🤖 Prompt for AI Agents
In @.agent/scripts/version-manager.sh around lines 551 - 604, In
auto_mark_tasks_complete(), the grep/sed patterns require a trailing space after
the task ID and use today_short; update the regexes to allow the task ID to be
followed by either whitespace or end-of-line (e.g., use "(?:$|[[:space:]])" or a
word-boundary-style pattern) for unchecked_pattern, checked_pattern and
sed_unchecked_pattern (and the sed match groups that reference ${escaped_id}),
and replace uses of today_short with the full ISO timestamp variable today when
appending the completed: timestamp so completed entries use the full timestamp.
New features documented: - /performance command for web performance audits (PR #209) - /email-health-check command for deliverability checks (PR #213) - @debug-opengraph and @debug-favicon SEO subagents (PR #206) - Auto-task completion from commit messages (PR #208) Updated Core Capabilities section with new monitoring features.
🤖 Augment PR SummarySummary: The release workflow now auto-completes TODO tasks referenced by recent commits. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
|
|
||
| # Extract task IDs (t001, t001.1, etc.) from commit messages | ||
| # Patterns: t001, feat(t001):, fix(t002):, closes t003, completes t004, mark t005 | ||
| echo "$commits" | grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b' | sort -u |
| [[ -z "$task_id" ]] && continue | ||
|
|
||
| # Build regex patterns (avoids shellcheck SC1087 false positive with [[:space:]]) | ||
| local unchecked_pattern="^[[:space:]]*- \\[ \\] ${task_id}[[:space:]]" |
New features documented: - /performance command for web performance audits (PR #209) - /email-health-check command for deliverability checks (PR #213) - @debug-opengraph and @debug-favicon SEO subagents (PR #206) - Auto-task completion from commit messages (PR #208) Updated Core Capabilities section with new monitoring features.



Summary
Implements automatic task completion marking during the release workflow. When running
version-manager.sh release, the script now:- [ ]→- [x])completed:timestamp to each marked taskChanges
extract_task_ids_from_commits()andauto_mark_tasks_complete()functionsNew Commands
Supported Patterns
Task IDs are extracted from commit messages matching:
chore: mark t001 as completefeat(t001): add user dashboardfix: resolve t002.1 validation issuedocs: update t003 documentationTesting
list-task-idscorrectly extracts task IDs from commitsauto-mark-taskscorrectly identifies already-complete tasksCloses #t021
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.