Skip to content

Conversation

@alex-solovyev
Copy link
Collaborator

@alex-solovyev alex-solovyev commented Feb 8, 2026

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: Added get_aidevops_identity(), get_task_owner(), cmd_claim, cmd_unclaim, check_task_claimed — all operate on TODO.md @owner field
  • pre-edit-check.sh: Warns if task (extracted from branch name) is claimed by another user via TODO.md
  • plans.md: Documented distributed claiming workflow
  • Supervisor dispatch checks @owner before dispatching and claims task on dispatch

How it works:

  • Claim = add @identity started:ISO to task line + git commit + push
  • Check = grep "@" on task line (instant, offline)
  • Race protection = git push rejection (optimistic locking)
  • Identity = AIDEVOPS_IDENTITY env var, fallback whoami@hostname

Why this replaces t164:

  • No GitHub API dependency (works with GitLab, Gitea, self-hosted, offline)
  • No gh CLI required
  • No ref:GH# needed on every task
  • Instant local check vs HTTP latency
  • TODO.md is already the shared state for tasks

GitHub Issue sync (issue-sync-helper.sh) remains as optional overlay.

Closes t165.

Summary by CodeRabbit

  • New Features

    • Claim and unclaim tasks using TODO.md as the authoritative ownership record.
    • Bi-directional sync of task assignees with remote issue trackers (optional).
    • Offline-capable, race-aware claim-before-dispatch workflow; new claim/unclaim commands.
  • User Experience

    • Warnings when operating on tasks claimed by someone else; messages reference TODO.md assignee.
    • TODO.md now shows assignee and started timestamps; identity derived from env or local user@host.
  • Documentation

    • Expanded ownership, claiming, sync guidance, and workflow rules.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Warning

Rate limit exceeded

@alex-solovyev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 6 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

Walkthrough

Replaces 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

Cohort / File(s) Summary
Pre-edit-check
.agents/scripts/pre-edit-check.sh
Replaces GH-api ownership check with TODO.md parsing: finds task line, derives local identity (AIDEVOPS_IDENTITY or whoami@host), and emits a warning when TODO.md assignee differs from local identity.
Supervisor Task Claiming
.agents/scripts/supervisor-helper.sh
Adds identity helper (get_aidevops_identity), TODO.md assignee parser (get_task_assignee), claim/unclaim commands (cmd_claim, cmd_unclaim), check_task_claimed, and optional sync_claim_to_github; dispatch flow now checks/claims tasks via TODO.md with race-aware todo_commit_push locking.
Issue Sync
.agents/scripts/issue-sync-helper.sh
Extends cmd_pull to request issue assignees and optionally inject GitHub assignees into TODO.md when task lines lack assignee: (dry-run supported); updates pull summary counts.
Docs / Workflow & Format
.agents/workflows/plans.md, TODO.md
Documents TODO.md-first ownership model, claim/unclaim flows, identity rules, race protection and adds assignee:identity and @owner fields to TODO.md format.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

📝 A task line holds a tiny name,
Locks whisper softly, race checks tame.
Claim, stamp started, sync if you may —
Work flows tidy, warnings clear the way. 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: shifting from GitHub Issues to a provider-agnostic TODO.md-based task claiming system.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t165-todo-claiming

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @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

  • Provider-Agnostic Task Claiming: Switched from GitHub Issue-based task claiming to a system using TODO.md as the source of truth, making it compatible with any Git provider.
  • New supervisor-helper.sh Functions: Introduced get_aidevops_identity, get_task_owner, cmd_claim, cmd_unclaim, and check_task_claimed to manage task ownership within TODO.md.
  • Pre-Edit Claim Warning: pre-edit-check.sh now warns users if a task, identified from their branch name, is already claimed by someone else in TODO.md.
  • Automated Supervisor Claiming: The supervisor's cmd_dispatch function now checks if a task is claimed before dispatching and automatically claims it upon successful dispatch.
  • Optimistic Locking with Git: Task claiming and unclaiming leverage git commit and push for optimistic locking, handling race conditions by detecting push failures.
  • Identity Management: User identity for claiming is determined by the AIDEVOPS_IDENTITY environment variable, falling back to whoami@hostname.
  • Documentation Update: plans.md has been updated to detail the new distributed task claiming workflow, including its mechanics and actor responsibilities.
Changelog
  • .agents/scripts/pre-edit-check.sh
    • Added logic to extract a task ID from the current branch name.
    • Implemented a check against TODO.md to see if the extracted task is claimed by another user.
    • Displays a warning if the task is claimed by someone other than the current user.
  • .agents/scripts/supervisor-helper.sh
    • Introduced get_aidevops_identity to retrieve the current user's identity (from AIDEVOPS_IDENTITY or whoami@hostname).
    • Added get_task_owner to parse the @owner field from a TODO.md task line.
    • Implemented cmd_claim to mark a task as claimed in TODO.md by adding @identity and a started:ISO timestamp, using git commit and push for atomic updates and race condition handling.
    • Implemented cmd_unclaim to remove the claim information from a task in TODO.md.
    • Added check_task_claimed to determine if a task is currently claimed and by whom.
    • Modified cmd_dispatch to first check if a task is claimed by another user and, if not, to automatically claim it before proceeding with dispatch.
    • Registered claim and unclaim as new commands accessible via supervisor-helper.sh.
  • .agents/workflows/plans.md
    • Added a new section "Distributed Task Claiming (t165)".
    • Documented the claim and unclaim commands and their usage.
    • Explained the mechanics of claiming, checking, unclaiming, and race protection.
    • Clarified how user identity is determined.
    • Outlined the roles of the Supervisor, Human, and Pre-edit check in the claiming process.
    • Emphasized that TODO.md is the source of truth, even with optional GitHub Issue syncing.
Activity
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 15:25:19 UTC 2026: Code review monitoring started
Sun Feb 8 15:25:20 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 15:25:22 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@gemini-code-assist gemini-code-assist bot left a 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.

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)"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
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


# 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:]]*//")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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:]]*//")

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 duplicates get_aidevops_identity() from supervisor-helper.sh.

The identity fallback logic here mirrors what supervisor-helper.sh provides via get_aidevops_identity(). If the two diverge over time, claim checks could silently fail to match. Consider sourcing the helper or extracting the identity logic into shared-constants.sh (already sourced at Line 166) so there's a single source of truth.

Comment on lines 206 to 226
# 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

@alex-solovyev alex-solovyev force-pushed the feature/t165-todo-claiming branch from 52fe8d7 to 68e60a8 Compare February 8, 2026 15:45
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 15:45:55 UTC 2026: Code review monitoring started
Sun Feb 8 15:45:56 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 15:45:58 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 15:49:06 UTC 2026: Code review monitoring started
Sun Feb 8 15:49:07 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 15:49:09 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:02:11 UTC 2026: Code review monitoring started
Sun Feb 8 16:02:12 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 16:02:14 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:07:19 UTC 2026: Code review monitoring started
Sun Feb 8 16:07:20 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 16:07:22 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 | 🟡 Minor

Indentation: source statement is at column 0 inside a nested block.

Line 166 breaks the indentation of the surrounding else block (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 the sed insertion (line 983) silently produces a malformed line.

If current_line doesn't actually contain logged: but the grep -qE 'logged:' on line 982 matched a substring in a different context (unlikely but possible with complex task lines), the sed -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 one assignee: 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() in supervisor-helper.sh. The comment on line 220 acknowledges this ("Must match"), but if the canonical function evolves (e.g., adds a fallback to git config user.email), this copy will silently drift.

If sourcing supervisor-helper.sh is too heavy for pre-edit-check, consider extracting the one-liner into shared-constants.sh which is already sourced at line 166.

.agents/workflows/plans.md (1)

702-707: Claiming table should reference todo_commit_push() for the commit+push step.

Line 704's Claim step says commit + push but doesn't mention that this must use todo_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 requires todo_commit_push() for all TODO.md writes, this table should cross-reference it to prevent implementers from using raw git 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 |

Comment on lines +975 to +991
# 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
# 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.

Comment on lines +1905 to +1932
#######################################
# 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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:12:16 UTC 2026: Code review monitoring started
Sun Feb 8 16:12:17 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 16:12:19 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:13:41 UTC 2026: Code review monitoring started
Sun Feb 8 16:13:41 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 16:13:44 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:17:31 UTC 2026: Code review monitoring started
Sun Feb 8 16:17:31 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

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
@alex-solovyev alex-solovyev force-pushed the feature/t165-todo-claiming branch from fe504f0 to a34bd9c Compare February 8, 2026 16:26
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 37 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Feb 8 16:26:40 UTC 2026: Code review monitoring started
Sun Feb 8 16:26:40 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 37

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 37
  • VULNERABILITIES: 0

Generated on: Sun Feb 8 16:26:42 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 8, 2026

@alex-solovyev
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@alex-solovyev
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

✅ Actions performed

Full review triggered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant