-
Notifications
You must be signed in to change notification settings - Fork 5
feat: provider-agnostic task claiming via TODO.md (t165) #627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughReplaces GitHub-issue-based ownership with TODO.md as the authoritative source: adds identity derivation, TODO.md assignee parsing, claim/unclaim/check commands, pre-edit warning change, race-aware local locking, and optional bi-directional sync of assignees to/from Git platform. Changes
Sequence DiagramsequenceDiagram
participant User
participant PreEdit as "pre-edit-check.sh (hook)"
participant Supervisor as "supervisor-helper.sh"
participant Todo as "TODO.md"
participant Lock as "todo_commit_push (lock)"
participant GH as "GitHub (gh) / issue sync"
User->>PreEdit: open worktree / run pre-edit
PreEdit->>Todo: read tNNN task line
PreEdit->>PreEdit: derive my_identity (AIDEVOPS_IDENTITY / whoami@host)
alt assignee exists && assignee != my_identity
PreEdit->>User: emit warning mentioning assignee
end
User->>Supervisor: cmd_dispatch / claim
Supervisor->>Supervisor: get_aidevops_identity()
Supervisor->>Todo: check_task_claimed(tNNN)
alt claimed by other
Supervisor->>User: abort dispatch (owned by other)
else free or self
Supervisor->>Lock: attempt todo_commit_push (acquire)
Supervisor->>Todo: cmd_claim -> set assignee:, started:
Supervisor->>Lock: push & release
Supervisor->>GH: optionally sync_claim_to_github()
Supervisor->>User: proceed with dispatch
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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 |
Summary of ChangesHello @alex-solovyev, 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 significantly refactors the task claiming mechanism, transitioning from a GitHub-dependent system to a robust, provider-agnostic solution centered around the TODO.md file. The new approach enhances portability and reduces reliance on external APIs by managing task ownership directly within the repository, allowing for distributed and offline task management with built-in race condition protection. Highlights
Changelog
Activity
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
|
🔍 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 Feb 8 15:25:22 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a robust, provider-agnostic task claiming system based on TODO.md, which is a great improvement over the previous GitHub-specific implementation. The changes are well-structured, with new helper functions for claiming, unclaiming, and checking tasks, and these are correctly integrated into the supervisor's dispatch logic and the pre-edit git hook. The use of git for optimistic locking is a clever solution for handling race conditions in a distributed environment. My review includes a critical fix for the dispatch logic to prevent workers from being assigned a task if the claim fails, and a suggestion for improved regex robustness in timestamp removal. Overall, this is a solid feature that enhances the autonomy and flexibility of the system.
.agents/scripts/supervisor-helper.sh
Outdated
| fi | ||
|
|
||
| # Claim the task before dispatching (t165) | ||
| cmd_claim "$task_id" 2>/dev/null || log_info "Could not claim $task_id (no TODO.md entry or push failed)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation ignores a failed task claim and proceeds with dispatching the task. If cmd_claim fails (e.g., due to a race condition), the || log_info construct simply logs a message and allows the cmd_dispatch function to continue. This can result in two different workers being assigned to the same task, defeating the purpose of the claiming mechanism. The dispatch should be aborted if the claim fails to prevent this.
| cmd_claim "$task_id" 2>/dev/null || log_info "Could not claim $task_id (no TODO.md entry or push failed)" | |
| if ! cmd_claim "$task_id"; then | |
| log_warn "Failed to claim task $task_id, skipping dispatch. It may have been claimed by another process." | |
| return 1 | |
| fi |
.agents/scripts/supervisor-helper.sh
Outdated
|
|
||
| # Remove @identity (with optional @host part) and started:ISO timestamp | ||
| local new_line | ||
| new_line=$(echo "$task_line" | sed -E "s/@${identity}[[:space:]]*//; s/started:[0-9T:Z-]+[[:space:]]*//") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The regex used to remove the started: timestamp is started:[0-9T:Z-]+. This is a bit too broad and could lead to unintended side effects if the task line format changes or contains other numbers. For better robustness, it's preferable to use a more specific regex that precisely matches the ISO 8601 format being generated in the cmd_claim function.
| new_line=$(echo "$task_line" | sed -E "s/@${identity}[[:space:]]*//; s/started:[0-9T:Z-]+[[:space:]]*//") | |
| new_line=$(echo "$task_line" | sed -E "s/@${identity}[[:space:]]*//; s/started:[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z[[:space:]]*//") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In @.agents/scripts/pre-edit-check.sh:
- Around line 206-226: The owner extraction can pick up other `@-mentions`; change
the task_owner extraction to only match the claim pattern appended by cmd_claim
by anchoring the regex to the " started:" token. Replace the current extraction
that sets task_owner from task_line (the grep -oE
'@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?' | head -1 | sed 's/^@//') with a pattern
that matches the owner followed immediately by " started:" (e.g. use grep -oE
with a lookahead/anchored suffix like ' @[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?(?=
started:)' or an equivalent grep-compatible pattern, then strip the leading @)
so task_owner only captures the claim inserted by cmd_claim.
In @.agents/scripts/supervisor-helper.sh:
- Around line 2715-2725: The current flow lets dispatch continue when cmd_claim
fails; change it so dispatch is aborted on claim failure: after calling
cmd_claim "$task_id" (and redirecting stderr as appropriate), if cmd_claim exits
non‑zero then call check_task_claimed "$task_id" "${trepo:-.}" to detect a push
race and log either log_warn "Task $task_id is claimed by @$claimed_by —
skipping dispatch" if someone else claimed it or log_info "Could not claim
$task_id — aborting dispatch" for other failures, and then return a non‑zero
code (e.g., return 2) instead of proceeding; keep existing TODO.md semantics and
ensure task_id/trepo are used for the recheck.
- Around line 1973-2030: The sed substitution in cmd_unclaim uses the raw
identity variable (from get_aidevops_identity) in a regex, which can misbehave
if identity contains metacharacters; before building the sed expression, create
an escaped version (e.g., escaped_identity) that backslashes regex-special chars
in $identity and then use that escaped_identity in the sed -E substitution that
produces new_line (and in any other regex usages), leaving the rest of the logic
(removing optional `@host` and started: timestamp) intact; update references in
cmd_unclaim (and any helper calls that rely on the raw pattern) to use
escaped_identity and keep sed_inplace/commit_and_push_todo unchanged.
- Around line 1854-1881: get_task_owner currently returns the first `@mention`
anywhere in the task line which misclassifies description/tag mentions; change
the extraction to only accept an owner that was recorded with the claim marker
(the "@owner started:ISO" token) by matching the task_line for an `@OWNER`
immediately followed by whitespace and "started:" and extracting just OWNER
(e.g. use a regex like '@([^[:space:]]+)(?=\s+started:)' or POSIX equivalent)
instead of the first @... occurrence, preserve the existing empty-string
fallback and ensure the function still returns 0 on success or missing owner;
update the owner variable extraction in get_task_owner (refer to task_line and
owner) accordingly.
- Around line 1889-1966: The cmd_claim function uses the raw identity (from
get_aidevops_identity) directly in a sed replacement which breaks when identity
contains &, /, or backslashes; before building new_line escape identity (replace
\ with \\\\, & with \&, and / with \/ or choose a sed delimiter that avoids /)
and use that escaped_identity in the sed -E expression and in sed_inplace so the
replacement is safe; update references around new_line, the sed construction,
and the sed_inplace call to use escaped_identity (leave get_aidevops_identity,
new_line, cmd_claim, and sed_inplace names intact).
In @.agents/workflows/plans.md:
- Around line 702-706: Update the "Check" step to require inspecting the
specific task's line and the `@owner` field rather than grepping for any "@" in
TODO.md; explicitly state that the check must target the exact task line (by
task ID or line number) and validate the `@owner` token (e.g., match the literal
"@owner" field on that line) to avoid matching unrelated mentions or emails, and
replace the ambiguous example `grep "@" TODO.md` with an instruction that
selects the task line first and then checks for the `@owner` token.
🧹 Nitpick comments (1)
.agents/scripts/pre-edit-check.sh (1)
220-220: Identity derivation duplicatesget_aidevops_identity()from supervisor-helper.sh.The identity fallback logic here mirrors what
supervisor-helper.shprovides viaget_aidevops_identity(). If the two diverge over time, claim checks could silently fail to match. Consider sourcing the helper or extracting the identity logic intoshared-constants.sh(already sourced at Line 166) so there's a single source of truth.
.agents/scripts/pre-edit-check.sh
Outdated
| # Check if task is claimed by someone else via TODO.md @owner (t165) | ||
| # Note: no 'local' — this runs at script top-level, not inside a function | ||
| task_id_from_branch="" | ||
| task_id_from_branch=$(echo "$current_branch" | grep -oE 't[0-9]+' | head -1 || true) | ||
| if [[ -n "$task_id_from_branch" ]]; then | ||
| project_root="" | ||
| project_root=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") | ||
| todo_file="$project_root/TODO.md" | ||
| if [[ -f "$todo_file" ]]; then | ||
| task_line="" | ||
| task_line=$(grep -E "^\- \[.\] ${task_id_from_branch} " "$todo_file" | head -1 || true) | ||
| task_owner="" | ||
| task_owner=$(echo "$task_line" | grep -oE '@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?' | head -1 | sed 's/^@//' || true) | ||
| if [[ -n "$task_owner" ]]; then | ||
| my_identity="${AIDEVOPS_IDENTITY:-$(whoami 2>/dev/null || echo unknown)@$(hostname -s 2>/dev/null || echo local)}" | ||
| if [[ "$task_owner" != "$my_identity" ]]; then | ||
| echo -e "${YELLOW}WARNING${NC}: Task $task_id_from_branch is claimed by @$task_owner" | ||
| fi | ||
| fi | ||
| fi | ||
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Owner extraction regex may match non-owner @ mentions in task text.
Line 218's regex @[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)? with head -1 picks the first @-prefixed token on the task line. If the task description itself contains @ references (e.g., t165 Implement @mentionfeature@alex@host started:2026-02-08), the wrong token is captured.
Anchoring on the started: timestamp that the claim command appends would be more reliable:
Proposed fix
- task_owner=$(echo "$task_line" | grep -oE '@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?' | head -1 | sed 's/^@//' || true)
+ task_owner=$(echo "$task_line" | grep -oE '@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)? started:' | head -1 | sed 's/ started:$//' | sed 's/^@//' || true)This ensures only the @owner started:ISO pattern deposited by cmd_claim is matched, avoiding false positives from task descriptions containing @ tokens.
🤖 Prompt for AI Agents
In @.agents/scripts/pre-edit-check.sh around lines 206 - 226, The owner
extraction can pick up other `@-mentions`; change the task_owner extraction to
only match the claim pattern appended by cmd_claim by anchoring the regex to the
" started:" token. Replace the current extraction that sets task_owner from
task_line (the grep -oE '@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?' | head -1 | sed
's/^@//') with a pattern that matches the owner followed immediately by "
started:" (e.g. use grep -oE with a lookahead/anchored suffix like '
@[A-Za-z0-9._-]+(@[A-Za-z0-9._-]+)?(?= started:)' or an equivalent
grep-compatible pattern, then strip the leading @) so task_owner only captures
the claim inserted by cmd_claim.
52fe8d7 to
68e60a8
Compare
🔍 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 Feb 8 15:45:58 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 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 Feb 8 15:49:09 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 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 Feb 8 16:02:14 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 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 Feb 8 16:07:22 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.agents/scripts/pre-edit-check.sh (1)
165-166:⚠️ Potential issue | 🟡 MinorIndentation:
sourcestatement is at column 0 inside a nested block.Line 166 breaks the indentation of the surrounding
elseblock (4-space indent). This appears to be a formatting oversight.Fix indentation
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit -source "${SCRIPT_DIR}/shared-constants.sh" + source "${SCRIPT_DIR}/shared-constants.sh"
🤖 Fix all issues with AI agents
In @.agents/scripts/issue-sync-helper.sh:
- Around line 975-991: The sed replacement interpolates ${new_line} directly
into sed_inplace which will mangle lines containing |, &, or backslashes; fix by
either (A) replacing the line using a line-addressed tool instead of embedding
the raw string into a sed substitution (for example rewrite the file by
processing todo_file with awk or perl and emit new_line at the matching
line_num), or (B) if you must keep sed_inplace, add a helper to escape sed
replacement metacharacters (escape &, \ and whichever delimiter you use) before
calling sed_inplace and use a delimiter that won't appear in content; update the
block that computes new_line and the sed_inplace call (references: variables
new_line, current_line, line_num, todo_file, and function sed_inplace) to use
the safe path.
In @.agents/scripts/supervisor-helper.sh:
- Around line 1905-1932: The assignee parsing in get_task_assignee is too narrow
and should accept any non-whitespace identity (so names with +, :, etc. are
captured); update the extraction that sets the local variable assignee
(currently using grep -oE 'assignee:[A-Za-z0-9._@-]+') to use a pattern like
'assignee:[^[:space:]]+' (or equivalent) against task_line, then strip the
"assignee:" prefix as before and preserve the existing fallback (|| echo "") so
get_task_assignee returns the full non-space assignee token stored in the
assignee variable.
- Around line 1982-2004: The replacement string new_line must be safely escaped
before calling sed_inplace to avoid unescaped &, | or backslashes in task_line
corrupting TODO.md; update the block that builds new_line to produce an escaped
variable (e.g., escape &, \ and the sed delimiter you use) and pass that escaped
value to sed_inplace instead of raw new_line—use the existing identity_esc logic
for identity and add a new escaped_new_line (escaping &, \ and | or change
delimiter consistently) so sed_inplace("${line_num}s|.*|${escaped_new_line}|",
"$todo_file") receives a safe replacement.
🧹 Nitpick comments (3)
.agents/scripts/issue-sync-helper.sh (1)
936-991: No error handling if thesedinsertion (line 983) silently produces a malformed line.If
current_linedoesn't actually containlogged:but thegrep -qE 'logged:'on line 982 matched a substring in a different context (unlikely but possible with complex task lines), thesed -E "s/( logged:)/ assignee:${assignee_login}\1/"would still succeed but place the assignee in an unexpected position. Consider verifying the resulting line has exactly oneassignee:field after mutation, or at minimum log the before/after in verbose mode for debuggability.Suggested verbose logging for before/after
sed_inplace "${line_num}s|.*|${new_line}|" "$todo_file" - log_verbose "Synced assignee:$assignee_login to $task_id (from GH#$issue_number)" + log_verbose "Synced assignee:$assignee_login to $task_id (from GH#$issue_number): $current_line → $new_line".agents/scripts/pre-edit-check.sh (1)
220-222: Duplicated identity derivation — consider sourcing a shared function.Line 221 replicates the identity logic from
get_aidevops_identity()insupervisor-helper.sh. The comment on line 220 acknowledges this ("Must match"), but if the canonical function evolves (e.g., adds a fallback togit config user.email), this copy will silently drift.If sourcing
supervisor-helper.shis too heavy for pre-edit-check, consider extracting the one-liner intoshared-constants.shwhich is already sourced at line 166..agents/workflows/plans.md (1)
702-707: Claiming table should referencetodo_commit_push()for the commit+push step.Line 704's Claim step says
commit + pushbut doesn't mention that this must usetodo_commit_push()(the flock-based serialized locking function documented at line 757). Since the race protection on line 707 relies on git push rejection, and the MANDATORY section below explicitly requirestodo_commit_push()for all TODO.md writes, this table should cross-reference it to prevent implementers from using rawgit commit && git push.Suggested table update
-| **Claim** | `git pull` → check `assignee:` in TODO.md → add `assignee:identity started:ISO` → `commit + push` → sync to GH issue | +| **Claim** | `git pull` → check `assignee:` in TODO.md → add `assignee:identity started:ISO` → `todo_commit_push()` → sync to GH issue |
| # Add assignee:login before logged: or at end of line | ||
| local line_num | ||
| line_num=$(grep -nE "^- \[.\] ${task_id} " "$todo_file" | head -1 | cut -d: -f1) | ||
| if [[ -n "$line_num" ]]; then | ||
| local current_line | ||
| current_line=$(sed -n "${line_num}p" "$todo_file") | ||
| local new_line | ||
| if echo "$current_line" | grep -qE 'logged:'; then | ||
| new_line=$(echo "$current_line" | sed -E "s/( logged:)/ assignee:${assignee_login}\1/") | ||
| else | ||
| new_line="${current_line} assignee:${assignee_login}" | ||
| fi | ||
| sed_inplace "${line_num}s|.*|${new_line}|" "$todo_file" | ||
| log_verbose "Synced assignee:$assignee_login to $task_id (from GH#$issue_number)" | ||
| assignee_synced=$((assignee_synced + 1)) | ||
| fi | ||
| done < <(echo "$issues_json" | jq -c '.[]' 2>/dev/null || true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sed replacement with unescaped new_line can corrupt TODO.md lines containing |, &, or \.
Line 987 uses the pipe | as the sed delimiter and interpolates ${new_line} directly into the replacement string. If the original task line contains | (e.g., in a URL or table syntax), & (sed backreference), or \, the sed command will either fail or silently mangle the line. This is a data-corruption risk in your source of truth file.
A safer approach is to avoid sed for the full-line replacement and use a line-addressed write instead:
Proposed fix using awk for safe line replacement
- sed_inplace "${line_num}s|.*|${new_line}|" "$todo_file"
+ awk -v ln="$line_num" -v replacement="$new_line" 'NR==ln{print replacement; next}1' "$todo_file" > "${todo_file}.tmp" && mv "${todo_file}.tmp" "$todo_file"Alternatively, if you want to keep using sed_inplace, escape the sed metacharacters in new_line first:
+ escaped_line=$(printf '%s\n' "$new_line" | sed 's/[&/|\\]/\\&/g')
- sed_inplace "${line_num}s|.*|${new_line}|" "$todo_file"
+ sed_inplace "${line_num}s|.*|${escaped_line}|" "$todo_file"📝 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.
| # Add assignee:login before logged: or at end of line | |
| local line_num | |
| line_num=$(grep -nE "^- \[.\] ${task_id} " "$todo_file" | head -1 | cut -d: -f1) | |
| if [[ -n "$line_num" ]]; then | |
| local current_line | |
| current_line=$(sed -n "${line_num}p" "$todo_file") | |
| local new_line | |
| if echo "$current_line" | grep -qE 'logged:'; then | |
| new_line=$(echo "$current_line" | sed -E "s/( logged:)/ assignee:${assignee_login}\1/") | |
| else | |
| new_line="${current_line} assignee:${assignee_login}" | |
| fi | |
| sed_inplace "${line_num}s|.*|${new_line}|" "$todo_file" | |
| log_verbose "Synced assignee:$assignee_login to $task_id (from GH#$issue_number)" | |
| assignee_synced=$((assignee_synced + 1)) | |
| fi | |
| done < <(echo "$issues_json" | jq -c '.[]' 2>/dev/null || true) | |
| # Add assignee:login before logged: or at end of line | |
| local line_num | |
| line_num=$(grep -nE "^- \[.\] ${task_id} " "$todo_file" | head -1 | cut -d: -f1) | |
| if [[ -n "$line_num" ]]; then | |
| local current_line | |
| current_line=$(sed -n "${line_num}p" "$todo_file") | |
| local new_line | |
| if echo "$current_line" | grep -qE 'logged:'; then | |
| new_line=$(echo "$current_line" | sed -E "s/( logged:)/ assignee:${assignee_login}\1/") | |
| else | |
| new_line="${current_line} assignee:${assignee_login}" | |
| fi | |
| escaped_line=$(printf '%s\n' "$new_line" | sed 's/[&/|\\]/\\&/g') | |
| sed_inplace "${line_num}s|.*|${escaped_line}|" "$todo_file" | |
| log_verbose "Synced assignee:$assignee_login to $task_id (from GH#$issue_number)" | |
| assignee_synced=$((assignee_synced + 1)) | |
| fi | |
| done < <(echo "$issues_json" | jq -c '.[]' 2>/dev/null || true) |
🤖 Prompt for AI Agents
In @.agents/scripts/issue-sync-helper.sh around lines 975 - 991, The sed
replacement interpolates ${new_line} directly into sed_inplace which will mangle
lines containing |, &, or backslashes; fix by either (A) replacing the line
using a line-addressed tool instead of embedding the raw string into a sed
substitution (for example rewrite the file by processing todo_file with awk or
perl and emit new_line at the matching line_num), or (B) if you must keep
sed_inplace, add a helper to escape sed replacement metacharacters (escape &, \
and whichever delimiter you use) before calling sed_inplace and use a delimiter
that won't appear in content; update the block that computes new_line and the
sed_inplace call (references: variables new_line, current_line, line_num,
todo_file, and function sed_inplace) to use the safe path.
| ####################################### | ||
| # Get the assignee: value from a task line in TODO.md (t165) | ||
| # Outputs the assignee identity string, empty if unassigned. | ||
| # $1: task_id $2: todo_file path | ||
| ####################################### | ||
| get_task_assignee() { | ||
| local task_id="$1" | ||
| local todo_file="$2" | ||
|
|
||
| if [[ ! -f "$todo_file" ]]; then | ||
| return 0 | ||
| fi | ||
|
|
||
| local task_id_escaped | ||
| task_id_escaped=$(printf '%s' "$task_id" | sed 's/\./\\./g') | ||
|
|
||
| local task_line | ||
| task_line=$(grep -E "^- \[.\] ${task_id_escaped} " "$todo_file" | head -1 || echo "") | ||
| if [[ -z "$task_line" ]]; then | ||
| return 0 | ||
| fi | ||
|
|
||
| # Extract assignee:value — unambiguous key:value field | ||
| local assignee | ||
| assignee=$(echo "$task_line" | grep -oE 'assignee:[A-Za-z0-9._@-]+' | head -1 | sed 's/^assignee://' || echo "") | ||
| echo "$assignee" | ||
| return 0 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broaden assignee parsing to avoid silent mis-detection.
assignee: currently only matches a narrow character set, so identities with +, : or other non‑space chars won’t parse. That can allow double-claiming and make unclaim checks fail.
🔧 Suggested fix
- assignee=$(echo "$task_line" | grep -oE 'assignee:[A-Za-z0-9._@-]+' | head -1 | sed 's/^assignee://' || echo "")
+ assignee=$(echo "$task_line" | grep -oE 'assignee:[^[:space:]]+' | head -1 | sed 's/^assignee://' || echo "")🤖 Prompt for AI Agents
In @.agents/scripts/supervisor-helper.sh around lines 1905 - 1932, The assignee
parsing in get_task_assignee is too narrow and should accept any non-whitespace
identity (so names with +, :, etc. are captured); update the extraction that
sets the local variable assignee (currently using grep -oE
'assignee:[A-Za-z0-9._@-]+') to use a pattern like 'assignee:[^[:space:]]+' (or
equivalent) against task_line, then strip the "assignee:" prefix as before and
preserve the existing fallback (|| echo "") so get_task_assignee returns the
full non-space assignee token stored in the assignee variable.
🔍 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 Feb 8 16:12:19 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 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 Feb 8 16:13:44 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 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 Feb 8 16:17:34 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
- Add assignee:identity field for task claiming (replaces @owner) - assignee: follows key:value pattern consistent with logged:, started:, completed: - Avoids @mentions ambiguity in task descriptions - Optimistic locking via git push rejection for race protection - Dispatch aborts if claim fails (prevents duplicate workers) - Bi-directional sync: GitHub Issue assignees synced to TODO.md assignee: - TODO.md is authoritative — GitHub sync is optional overlay - Identity: AIDEVOPS_IDENTITY env var, fallback whoami@hostname - sed escaping for identity values in claim/unclaim - Updated pre-edit-check.sh, issue-sync pull, plans.md, TODO.md format spec
fe504f0 to
a34bd9c
Compare
🔍 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 Feb 8 16:26:42 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |



Summary
Replaces GitHub Issue-based task claiming (t164, PR #621 closed) with a provider-agnostic approach using TODO.md as the source of truth.
Key changes:
supervisor-helper.sh: Addedget_aidevops_identity(),get_task_owner(),cmd_claim,cmd_unclaim,check_task_claimed— all operate on TODO.md@ownerfieldpre-edit-check.sh: Warns if task (extracted from branch name) is claimed by another user via TODO.mdplans.md: Documented distributed claiming workflow@ownerbefore dispatching and claims task on dispatchHow it works:
@identity started:ISOto task line +git commit + pushgrep "@"on task line (instant, offline)AIDEVOPS_IDENTITYenv var, fallbackwhoami@hostnameWhy this replaces t164:
ghCLI requiredref:GH#needed on every taskGitHub Issue sync (
issue-sync-helper.sh) remains as optional overlay.Closes t165.
Summary by CodeRabbit
New Features
User Experience
Documentation