fix(t021): prevent false positive task marking in auto-complete#216
fix(t021): prevent false positive task marking in auto-complete#216marcusquinn merged 1 commit intomainfrom
Conversation
Refine task ID extraction to only match explicit completion patterns: - Conventional commits with task scope: feat(t001):, fix(t002): - Mark...done pattern: 'mark t001, t002 done' - Complete/closes keyword: 'complete t003', 'closes t004' - Task before completion word: 't005 done' Previously extracted ALL task IDs from any commit containing 'done', causing false positives when tasks were merely mentioned.
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 addresses a critical bug in the auto-complete feature where tasks were incorrectly marked as complete due to overly broad commit message parsing. The changes introduce a more precise method for extracting task IDs, ensuring that only explicitly completed tasks are identified, thereby improving the accuracy and reliability of task status tracking. 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 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 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 17:27:39 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Code Review
This pull request effectively addresses the issue of false positive task marking by replacing a broad regex with a more nuanced, pattern-based approach to extracting task IDs from commit messages. The new implementation iterates through commits and applies specific rules for conventional commits, "mark...done" phrases, and other completion keywords. This is a great improvement in correctness. I've added a suggestion to refactor the loop for better efficiency and readability by using more of bash's built-in features and optimizing command chains.
| while IFS= read -r commit; do | ||
| [[ -z "$commit" ]] && continue | ||
|
|
||
| # Pattern 1: Conventional commits with task ID in scope | ||
| # e.g., feat(t001):, fix(t002):, docs(t003.1):, refactor(t004): | ||
| if [[ "$commit" =~ ^(feat|fix|docs|refactor|perf|test|chore|style|build|ci)\(t[0-9]{3}(\.[0-9]+)*\): ]]; then | ||
| local id | ||
| id=$(echo "$commit" | grep -oE '\(t[0-9]{3}(\.[0-9]+)*\)' | tr -d '()') | ||
| task_ids="$task_ids $id" | ||
| fi | ||
|
|
||
| # Pattern 2: "mark tXXX done/complete" - extract task IDs between "mark" and "done/complete" | ||
| # e.g., "mark t004, t048, t069 done" -> t004, t048, t069 | ||
| if [[ "$commit" =~ mark[[:space:]]+(.*)[[:space:]]+(done|complete) ]]; then | ||
| local segment="${BASH_REMATCH[1]}" | ||
| local ids | ||
| ids=$(echo "$segment" | grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b') | ||
| task_ids="$task_ids $ids" | ||
| fi | ||
|
|
||
| # Pattern 3: "complete/completes/closes tXXX" - task ID immediately after keyword | ||
| # e.g., "complete t037", "closes t001" | ||
| local ids | ||
| ids=$(echo "$commit" | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then | ||
| task_ids="$task_ids $ids" | ||
| fi | ||
|
|
||
| # Pattern 4: "tXXX complete/done/finished" - task ID before completion word | ||
| # e.g., "t001 complete", "t002 done" | ||
| ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then | ||
| task_ids="$task_ids $ids" | ||
| fi | ||
|
|
||
| done <<< "$commits" |
There was a problem hiding this comment.
This while loop is a great improvement for correctness. It can be further optimized for efficiency and readability.
- Efficiency: The loop currently spawns multiple processes (
echo,grep,tr) for each commit, which can be slow if there are many commits. You can make this more efficient by using bash's built-in regex matching (BASH_REMATCH) for pattern 1, and combininggreppipes withsedfor patterns 3 and 4. - Readability: The
localdeclarations foridandidsare scattered and re-declared, which can be confusing. It's better practice to declare all loop-specific variables once at the top of the loop.
Here's a suggested refactoring of the loop that addresses these points:
while IFS= read -r commit; do
local id segment ids
[[ -z "$commit" ]] && continue
# Pattern 1: Conventional commits with task ID in scope (more efficient)
if [[ "$commit" =~ ^(feat|fix|docs|refactor|perf|test|chore|style|build|ci)\((t[0-9]{3}(\.[0-9]+)*)\): ]]; then
id="${BASH_REMATCH[2]}"
task_ids="$task_ids $id"
fi
# Pattern 2: "mark tXXX done/complete" - extract task IDs between "mark" and "done/complete"
# e.g., "mark t004, t048, t069 done" -> t004, t048, t069
if [[ "$commit" =~ mark[[:space:]]+(.*)[[:space:]]+(done|complete) ]]; then
segment="${BASH_REMATCH[1]}"
ids=$(echo "$segment" | grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b')
task_ids="$task_ids $ids"
fi
# Pattern 3: "complete/completes/closes tXXX" - task ID immediately after keyword (more efficient)
# e.g., "complete t037", "closes t001"
ids=$(echo "$commit" | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | sed -E 's/.*[[:space:]]+//')
if [[ -n "$ids" ]]; then
task_ids="$task_ids $ids"
fi
# Pattern 4: "tXXX complete/done/finished" - task ID before completion word (more efficient)
# e.g., "t001 complete", "t002 done"
ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' | sed -E 's/[[:space:]]+(complete|done|finished)$//')
if [[ -n "$ids" ]]; then
task_ids="$task_ids $ids"
fi
done <<< "$commits"
🤖 Augment PR SummarySummary: Refines task auto-completion so tasks are only marked complete when the commit subject explicitly indicates completion. Changes:
Technical Notes: Output remains a de-duplicated, sorted list of task IDs for consumption by 🤖 Was this summary useful? React with 👍 or 👎 |
| fi | ||
|
|
||
| # Pattern 3: "complete/completes/closes tXXX" - task ID immediately after keyword | ||
| # e.g., "complete t037", "closes t001" |
There was a problem hiding this comment.
The regex mark[[:space:]]+(.*)[[:space:]]+(done|complete) can match inside other words (e.g. remark) and the greedy (.*) can extend to the last done/complete, potentially pulling in task IDs from unrelated trailing text. That could reintroduce false-positive task completions in some commit subjects that contain multiple done/complete words.
🤖 Was this useful? React with 👍 or 👎
| # Pattern 4: "tXXX complete/done/finished" - task ID before completion word | ||
| # e.g., "t001 complete", "t002 done" | ||
| ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then |
There was a problem hiding this comment.
Pattern 3 doesn’t require a word boundary around (completes?|closes?), so subjects like incomplete t021 or encloses t021 could still match and incorrectly mark a task as completed. Consider requiring a clear token boundary/separator around the completion keyword to avoid substring matches.
🤖 Was this useful? React with 👍 or 👎
| # e.g., "complete t037", "closes t001" | ||
| local ids | ||
| ids=$(echo "$commit" | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then |
There was a problem hiding this comment.
grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b' relies on \b acting like a word boundary, but in many grep -E implementations it’s treated as a backspace escape, which can make extraction inconsistent across environments. If this script runs on BSD/macOS grep, task ID detection here may silently fail or behave unexpectedly.
🤖 Was this useful? React with 👍 or 👎
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.agent/scripts/version-manager.sh:
- Around line 588-589: The current pipeline that deduplicates task IDs (echo
"$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}' | sort -u) allows partial
matches like t0012 or t001foo; update the grep pattern to strictly match the
task-id format used by the script by anchoring the end and allowing optional
sub-tasks, e.g. replace the grep -E pattern with one that enforces start and end
anchors and optional dot-separated numeric subparts (use
'^t[0-9]{3}(\\.[0-9]+)*$') so only valid IDs from the task_ids variable pass to
sort -u.
- Around line 562-584: Pattern 3 and Pattern 4 regexes can match substrings
inside larger words; update the grep -oE invocations that populate the local
variable ids so they require word boundaries: for the completes?/closes? pattern
used to set ids (the line assigning ids from echo "$commit" | grep -oE
'(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' ...) add a left-side word
boundary (e.g., '\b(completes?|closes?)[[:space:]]+t...') and for the tXXX
before completion pattern (the line assigning ids from echo "$commit" | grep -oE
't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' ...) add a right-side
word boundary on the completion words (e.g.,
'...([[:space:]]+(complete|done|finished)\b)') so that the populated ids and
appended task_ids only match whole words.
| # Pattern 2: "mark tXXX done/complete" - extract task IDs between "mark" and "done/complete" | ||
| # e.g., "mark t004, t048, t069 done" -> t004, t048, t069 | ||
| if [[ "$commit" =~ mark[[:space:]]+(.*)[[:space:]]+(done|complete) ]]; then | ||
| local segment="${BASH_REMATCH[1]}" | ||
| local ids | ||
| ids=$(echo "$segment" | grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b') | ||
| task_ids="$task_ids $ids" | ||
| fi | ||
|
|
||
| # Pattern 3: "complete/completes/closes tXXX" - task ID immediately after keyword | ||
| # e.g., "complete t037", "closes t001" | ||
| local ids | ||
| ids=$(echo "$commit" | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then | ||
| task_ids="$task_ids $ids" | ||
| fi | ||
|
|
||
| # Pattern 4: "tXXX complete/done/finished" - task ID before completion word | ||
| # e.g., "t001 complete", "t002 done" | ||
| ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' | grep -oE 't[0-9]{3}(\.[0-9]+)*') | ||
| if [[ -n "$ids" ]]; then | ||
| task_ids="$task_ids $ids" | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the file and the specific function
cat -n .agent/scripts/version-manager.sh | head -100Repository: marcusquinn/aidevops
Length of output: 3633
🏁 Script executed:
# Look at the extract_task_ids_from_commits function around lines 532-590
sed -n '530,595p' .agent/scripts/version-manager.shRepository: marcusquinn/aidevops
Length of output: 2854
🏁 Script executed:
# Test grep \b behavior in ERE mode to verify the claim
echo "Test 1: Does \\b work as word boundary in grep -E?"
printf 't001 test\n' | grep -oE '\bt[0-9]{3}\b' && echo "Match found" || echo "No match"
echo -e "\nTest 2: Does \\b work without explicit escape?"
printf 't001 test\n' | grep -oE '\\bt[0-9]{3}\\b' && echo "Match found" || echo "No match"
echo -e "\nTest 3: Test false positive - does 'remark' match?"
printf 'remark t001\n' | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' && echo "False positive: matched 'remark'" || echo "Correctly rejected"
echo -e "\nTest 4: Test false positive - does 'incomplete' match?"
printf 'incomplete t021\n' | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' && echo "False positive: matched 'incomplete'" || echo "Correctly rejected"
echo -e "\nTest 5: Test mark pattern with \\b"
printf 'mark t004 done\n' | grep -oE '\bt[0-9]{3}(\.[0-9]+)*\b' && echo "Mark pattern match found" || echo "Mark pattern: No match"Repository: marcusquinn/aidevops
Length of output: 427
🏁 Script executed:
# Test if the patterns within complete/closes word actually match
echo -e "\nTest 6: Does 'completest004' match (boundary issue)?"
printf 'completest004 something\n' | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' && echo "Matched inside word" || echo "Correctly rejected with space requirement"
echo -e "\nTest 7: What about 'complete t004' (should match)"
printf 'complete t004\n' | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' && echo "Matched correctly" || echo "No match"Repository: marcusquinn/aidevops
Length of output: 242
🏁 Script executed:
# Let's also check what the actual final filter looks like by searching for it
grep -n "final filter\|^t\[0-9\]\{3\}" .agent/scripts/version-manager.sh | head -20Repository: marcusquinn/aidevops
Length of output: 46
🏁 Script executed:
# Look at the complete extract_task_ids_from_commits function
sed -n '532,610p' .agent/scripts/version-manager.shRepository: marcusquinn/aidevops
Length of output: 3288
🏁 Script executed:
# Test Pattern 4 boundary issue
echo "Test Pattern 4 boundary: does 't001 completely' match?"
printf 't001 completely\n' | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' && echo "Matched (false positive)" || echo "Correctly rejected"
echo -e "\nTest additional: 'refactor t005 incomplete' - should NOT match"
printf 'refactor t005 incomplete\n' | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' && echo "Matched (false positive)" || echo "Correctly rejected"
echo -e "\nTest word boundary with alternation: Does '(completes?|closes?) \b' format help?"
printf 'incomplete t021\n' | grep -oE '(^|[^[:alnum:]_])(completes?|closes?)[[:space:]]+t[0-9]{3}' && echo "With boundary: Matched" || echo "With boundary: Correctly rejected"Repository: marcusquinn/aidevops
Length of output: 355
🏁 Script executed:
# Verify final output format to ensure deduplication works correctly
echo -e "\nTest final filter output quality:"
printf 't001\nt001\nt002\nincomplet\nfragment\nt003' | grep -E '^t[0-9]{3}' | sort -uRepository: marcusquinn/aidevops
Length of output: 113
Review contains incorrect technical analysis—\b word boundaries work correctly, but real boundary issues exist in Patterns 3 and 4.
The \b assertion is incorrect: testing confirms \b in grep -E functions properly as a word boundary. Pattern 2 (mark…done) works as designed.
However, two genuine reliability issues remain:
- Pattern 3 (
(completes?|closes?)[[:space:]]+t[0-9]{3}…): Lacks left word boundary. "incomplete t021" incorrectly matches "complete" within the word. - Pattern 4 (
t[0-9]{3}…[[:space:]]+(complete|done|finished)): Lacks right word boundary. "t001 completely" incorrectly matches "complete" within the word.
For automation script reliability (per coding guidelines), add word boundaries:
🔧 Suggested fix (correct boundaries)
# Pattern 3: "complete/completes/closes tXXX" - task ID immediately after keyword
# e.g., "complete t037", "closes t001"
local ids
- ids=$(echo "$commit" | grep -oE '(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | grep -oE 't[0-9]{3}(\.[0-9]+)*')
+ ids=$(echo "$commit" | grep -oE '(^|[^[:alnum:]_])(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' | grep -oE 't[0-9]{3}(\.[0-9]+)*')
if [[ -n "$ids" ]]; then
task_ids="$task_ids $ids"
fi
# Pattern 4: "tXXX complete/done/finished" - task ID before completion word
# e.g., "t001 complete", "t002 done"
ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' | grep -oE 't[0-9]{3}(\.[0-9]+)*')
+ ids=$(echo "$commit" | grep -oE 't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)($|[^[:alnum:]_])' | grep -oE 't[0-9]{3}(\.[0-9]+)*')🤖 Prompt for AI Agents
In @.agent/scripts/version-manager.sh around lines 562 - 584, Pattern 3 and
Pattern 4 regexes can match substrings inside larger words; update the grep -oE
invocations that populate the local variable ids so they require word
boundaries: for the completes?/closes? pattern used to set ids (the line
assigning ids from echo "$commit" | grep -oE
'(completes?|closes?)[[:space:]]+t[0-9]{3}(\.[0-9]+)*' ...) add a left-side word
boundary (e.g., '\b(completes?|closes?)[[:space:]]+t...') and for the tXXX
before completion pattern (the line assigning ids from echo "$commit" | grep -oE
't[0-9]{3}(\.[0-9]+)*[[:space:]]+(complete|done|finished)' ...) add a right-side
word boundary on the completion words (e.g.,
'...([[:space:]]+(complete|done|finished)\b)') so that the populated ids and
appended task_ids only match whole words.
| # Deduplicate and sort | ||
| echo "$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}' | sort -u |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Test 1: Verify regex behavior with the original pattern
echo "=== Testing original pattern: ^t[0-9]{3} ==="
printf '%s\n' "t001" "t0012" "t001foo" "t001.1" | grep -E '^t[0-9]{3}' && echo "---" && echo "Pattern matched above"
echo ""
echo "=== Testing suggested pattern: ^t[0-9]{3}(\.[0-9]+)*$ ==="
printf '%s\n' "t001" "t0012" "t001foo" "t001.1" | grep -E '^t[0-9]{3}(\.[0-9]+)*$' && echo "---" && echo "Pattern matched above"Repository: marcusquinn/aidevops
Length of output: 257
🏁 Script executed:
# Examine the actual file at lines 588-589
sed -n '580,600p' .agent/scripts/version-manager.sh | cat -nRepository: marcusquinn/aidevops
Length of output: 944
🏁 Script executed:
# Search for task ID patterns and usage in the script
rg 't[0-9]{3}' .agent/scripts/version-manager.sh -A 2 -B 2 | head -50Repository: marcusquinn/aidevops
Length of output: 1935
🏁 Script executed:
# Check what task IDs actually look like in the codebase
rg '\bt[0-9]{3}' --type sh -A 1 -B 1 | head -40Repository: marcusquinn/aidevops
Length of output: 3106
Anchor the final task-id filter to prevent partial-ID matches.
The pattern ^t[0-9]{3} accepts unwanted matches: t0012 (4 digits instead of 3) and t001foo (text after ID). Since task IDs follow the strict format t[0-9]{3}(\.[0-9]+)*, add end-of-line anchor and optional sub-task support to enforce correctness at the deduplication stage.
Suggested fix
- echo "$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}' | sort -u
+ echo "$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}(\.[0-9]+)*$' | sort -u📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Deduplicate and sort | |
| echo "$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}' | sort -u | |
| # Deduplicate and sort | |
| echo "$task_ids" | tr ' ' '\n' | grep -E '^t[0-9]{3}(\.[0-9]+)*$' | sort -u |
🤖 Prompt for AI Agents
In @.agent/scripts/version-manager.sh around lines 588 - 589, The current
pipeline that deduplicates task IDs (echo "$task_ids" | tr ' ' '\n' | grep -E
'^t[0-9]{3}' | sort -u) allows partial matches like t0012 or t001foo; update the
grep pattern to strictly match the task-id format used by the script by
anchoring the end and allowing optional sub-tasks, e.g. replace the grep -E
pattern with one that enforces start and end anchors and optional dot-separated
numeric subparts (use '^t[0-9]{3}(\\.[0-9]+)*$') so only valid IDs from the
task_ids variable pass to sort -u.



Summary
Fixes false positive task marking in the auto-complete feature from PR #208.
Problem
The original implementation extracted ALL task IDs from any commit containing completion keywords like "done". This caused false positives when tasks were merely mentioned in the same commit but not actually completed.
Example problematic commit:
This would incorrectly mark t007 as complete (it was being added to the plan, not completed).
Solution
Refined task ID extraction to only match explicit completion patterns:
feat(t001):,fix(t002):mark t001, t002 done(extracts only tasks between "mark" and "done")complete t003,closes t004t005 done,t006 finishedTesting
Follow-up to #208
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.