From 5609507b88a84282ae0db11ecb73898e7b58a7d8 Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:41:02 +0000 Subject: [PATCH 1/2] chore: mark t169 blocked in TODO.md --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 2ece7893c..a0b0226c5 100644 --- a/TODO.md +++ b/TODO.md @@ -104,7 +104,7 @@ Tasks with no open blockers - ready to work on. Use `/ready` to refresh this lis - Notes: PR #548 merged. Guard arithmetic with `|| true` to prevent silent exit under `set -e`. - [ ] t169 Fix `aidevops update` skipping agent deployment — pass `--non-interactive` to setup.sh #bug #setup ~15m (ai:10m) ref:GH#550 assignee:marcusquinn@Marcus-MacBook-Pro started:2026-02-08T17:33:28Z logged:2026-02-08 - - Notes: `cmd_update()` in aidevops.sh calls `bash setup.sh` without `--non-interactive`, so interactive prompts silently skip in non-TTY contexts and agents never deploy. + - Notes: `cmd_update()` in aidevops.sh calls `bash setup.sh` without `--non-interactive`, so interactive prompts silently skip in non-TTY contexts and agents never deploy. BLOCKED: Re-prompt dispatch failed: ambiguous_skipped_ai - [ ] t170 Fix `import-credentials` ignoring multi-tenant credential files #bug #credentials ~30m (ai:20m) ref:GH#553 logged:2026-02-08 - Notes: `cmd_import_credentials()` in secret-helper.sh reads credentials.sh directly but with multi-tenant active, that file is a loader script. Actual credentials are in `tenants/{tenant}/credentials.sh`. From 2dfdcf597185f3d1cb3501d74217cb7e09b15835 Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:18:02 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20supervisor=20identity=20matching=20?= =?UTF-8?q?=E2=80=94=20prefer=20GitHub=20username,=20fuzzy=20compare?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_aidevops_identity() now prefers the GitHub username (via gh api user, cached per session) over user@host format. This matches how TODO.md assignees are typically written (e.g., assignee:marcusquinn). check_task_claimed() now does fuzzy matching: compares against the full identity, the username portion (before @), the local whoami, and the GitHub username. This prevents the supervisor from skipping its own tasks when assignee format doesn't exactly match identity format. cmd_claim() and cmd_unclaim() now delegate to check_task_claimed() for consistent matching instead of duplicating comparison logic. --- .agents/scripts/supervisor-helper.sh | 43 ++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/.agents/scripts/supervisor-helper.sh b/.agents/scripts/supervisor-helper.sh index 76b81aec2..f546873f6 100755 --- a/.agents/scripts/supervisor-helper.sh +++ b/.agents/scripts/supervisor-helper.sh @@ -1947,13 +1947,25 @@ find_task_issue_number() { ####################################### # Get the identity string for task claiming (t165) -# Uses AIDEVOPS_IDENTITY env var, falls back to user@hostname +# Priority: AIDEVOPS_IDENTITY env > GitHub username (cached) > user@hostname +# The GitHub username is preferred because TODO.md assignees typically use +# GitHub usernames (e.g., assignee:marcusquinn), not user@host format. ####################################### get_aidevops_identity() { if [[ -n "${AIDEVOPS_IDENTITY:-}" ]]; then echo "$AIDEVOPS_IDENTITY" return 0 fi + + # Try GitHub username (cached for the session to avoid repeated API calls) + if [[ -z "${_CACHED_GH_USERNAME:-}" ]]; then + _CACHED_GH_USERNAME=$(gh api user --jq '.login' 2>/dev/null || echo "") + fi + if [[ -n "$_CACHED_GH_USERNAME" ]]; then + echo "$_CACHED_GH_USERNAME" + return 0 + fi + local user host user=$(whoami 2>/dev/null || echo "unknown") host=$(hostname -s 2>/dev/null || echo "local") @@ -2020,8 +2032,12 @@ cmd_claim() { current_assignee=$(get_task_assignee "$task_id" "$todo_file") if [[ -n "$current_assignee" ]]; then - if [[ "$current_assignee" == "$identity" ]]; then - log_info "$task_id already claimed by you (assignee:$identity)" + # Use check_task_claimed for consistent fuzzy matching (handles + # username vs user@host mismatches) + local claimed_other="" + claimed_other=$(check_task_claimed "$task_id" "$project_root" 2>/dev/null) || true + if [[ -z "$claimed_other" ]]; then + log_info "$task_id already claimed by you (assignee:$current_assignee)" return 0 fi log_error "$task_id is claimed by assignee:$current_assignee" @@ -2115,7 +2131,10 @@ cmd_unclaim() { return 0 fi - if [[ "$current_assignee" != "$identity" ]]; then + # Use check_task_claimed for consistent fuzzy matching + local claimed_other="" + claimed_other=$(check_task_claimed "$task_id" "$project_root" 2>/dev/null) || true + if [[ -n "$claimed_other" ]]; then log_error "$task_id is claimed by assignee:$current_assignee, not by you (assignee:$identity)" return 1 fi @@ -2171,11 +2190,25 @@ check_task_claimed() { local identity identity=$(get_aidevops_identity) - # Claimed by self = OK + # Exact match = claimed by self if [[ "$current_assignee" == "$identity" ]]; then return 0 fi + # Fuzzy match: assignee might be just a username while identity is user@host, + # or vice versa. Also check the local username (whoami) and GitHub username. + local local_user + local_user=$(whoami 2>/dev/null || echo "") + local gh_user="${_CACHED_GH_USERNAME:-}" + local identity_user="${identity%%@*}" # Strip @host portion + + if [[ "$current_assignee" == "$local_user" ]] || + [[ "$current_assignee" == "$gh_user" ]] || + [[ "$current_assignee" == "$identity_user" ]] || + [[ "${current_assignee%%@*}" == "$identity_user" ]]; then + return 0 + fi + # Claimed by someone else echo "$current_assignee" return 1