Skip to content

fix: supervisor lifecycle gaps — Phase 3d and orphan PR adoption#2205

Merged
marcusquinn merged 1 commit intomainfrom
bugfix/supervisor-lifecycle-gaps
Feb 24, 2026
Merged

fix: supervisor lifecycle gaps — Phase 3d and orphan PR adoption#2205
marcusquinn merged 1 commit intomainfrom
bugfix/supervisor-lifecycle-gaps

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 24, 2026

Summary

Root Causes Fixed

  1. Phase 3d gap: process_ai_lifecycle() only processes tasks in states complete, pr_review, review_triage, merging, merged, deploying, blocked — NOT verified or deployed. Open PRs for verified tasks were invisible.
  2. Orphan PR skip: adopt_untracked_prs did continue when no tNNN: prefix found in PR title (line 3853). PRs like chore: scrub private repo references were invisible to the supervisor.

Changes

  • pulse.sh: +157/-8 lines
    • New Phase 3d block (~80 lines) after Phase 3c
    • Enhanced adopt_untracked_prs with branch-name task ID extraction and orphan PR adoption
    • ShellCheck clean

Testing

  • ShellCheck: zero violations
  • Verified all 3 previously-stale PRs merged successfully
  • Phase 3d logic tested against real PR state data from GitHub API

Summary by CodeRabbit

  • New Features

    • Added automated PR reconciliation for verified/deployed tasks, including automatic squash merging when CI is green and branch updates for behind PRs.
    • Enhanced orphaned PR adoption to create task records when no match exists.
  • Bug Fixes

    • Improved PR lifecycle flow management reducing stuck pull requests.
    • Better PR-to-task linking and state tracking.

…an PRs

- Phase 3d: finds verified/deployed tasks with open PRs on GitHub and
  squash-merges them if CI is green, updates branch if behind, or logs
  if blocked. Runs on the same cooldown as Phase 3c.
- adopt_untracked_prs: now extracts task IDs from branch names as
  fallback when PR title has no tNNN: prefix.
- adopt_untracked_prs: creates synthetic task entries (prNNN) for
  orphan PRs with no task ID, allowing Phase 3 lifecycle to process
  them through review → merge → verify.
- adopt_untracked_prs: logs verified/deployed tasks for Phase 3d
  handling instead of silently skipping.
@gemini-code-assist
Copy link

Summary of Changes

Hello @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 significantly improves the supervisor's ability to manage the lifecycle of pull requests, particularly those associated with tasks that have reached terminal states or those lacking explicit task identifiers. By introducing a new reconciliation phase and enhancing PR adoption mechanisms, the system can now automatically resolve lingering PRs and ensure all relevant changes are properly integrated, thereby streamlining the development workflow and reducing manual intervention.

Highlights

Changelog
  • .agents/scripts/supervisor/pulse.sh
    • Added a new 'Phase 3d' block to automatically merge or update open pull requests for 'verified' or 'deployed' tasks based on their GitHub status and CI results.
    • Modified adopt_untracked_prs to fetch headRefName (branch name) when listing open PRs from GitHub.
    • Implemented logic in adopt_untracked_prs to extract task IDs from branch names as a secondary lookup.
    • Added functionality to adopt_untracked_prs to create synthetic task entries for PRs that lack task IDs in both their title and branch name, enabling their tracking and processing.
    • Introduced a verbose log message in adopt_untracked_prs for PRs linked to 'verified', 'deployed', or 'merged' tasks, indicating that Phase 3d will handle them.
Activity
  • The author implemented a new Phase 3d to handle PRs for verified/deployed tasks.
  • The adopt_untracked_prs function was updated to better handle PRs without explicit task IDs.
  • Testing included ShellCheck for zero violations and verification that three previously stale PRs were successfully merged.
  • Phase 3d logic was tested against real GitHub API PR state data.
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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Walkthrough

The pull request extends the pulse flow with Phase 3d, a new automated PR reconciliation phase that queries GitHub for merged PR states and performs squash merges, plus-updates branch handling for OPEN PRs. It also extends the adopt_untracked_prs function to extract task IDs from PR branch names via headRefName and create synthetic tasks for orphaned PRs.

Changes

Cohort / File(s) Summary
Phase 3d PR Reconciliation
.agents/scripts/supervisor/pulse.sh
Introduces Phase 3d logic that scans verified/deployed tasks with PR URLs, queries GitHub for PR state, and acts on OPEN PRs: squash-merges when CLEAN/UNSTABLE with green CI, updates branches when BEHIND, and logs skipped BLOCKED/UNKNOWN PRs. Reports merged/closed statistics.
Orphan PR Adoption & Linkage
.agents/scripts/supervisor/pulse.sh
Extends adopt_untracked_prs to parse headRefName from gh pr list and extract task IDs from PR branch names. Creates synthetic tasks (id pr<PR_number>) for orphaned PRs. Updates Phase 3a linkage to set status complete and log Phase 3d handling for terminal-state tasks.

Sequence Diagram(s)

sequenceDiagram
    participant Supervisor as Supervisor<br/>(pulse.sh)
    participant GitHub as GitHub API
    participant DB as Task DB
    participant Repo as Git Repo

    rect rgba(100, 150, 200, 0.5)
    Note over Supervisor,GitHub: Phase 3d: PR Reconciliation (when should_reconcile=true)
    Supervisor->>DB: Scan verified/deployed tasks with PR URLs
    DB-->>Supervisor: List of tasks with PR URLs
    
    loop For each PR with valid URL
        Supervisor->>GitHub: Query PR state (number, repo)
        GitHub-->>Supervisor: PR state (OPEN/CLOSED, mergeStateStatus, CI status)
        
        alt PR is OPEN & (CLEAN/UNSTABLE) & CI green
            Supervisor->>GitHub: Attempt squash merge
            GitHub-->>Supervisor: Merge successful/failed
            opt Merge successful
                Supervisor->>Repo: Pull main & cleanup worktrees
                Repo-->>Supervisor: Complete
                Supervisor->>DB: Log proof statement, increment merged counter
            end
        else PR is BEHIND
            Supervisor->>GitHub: Update PR branch
            GitHub-->>Supervisor: Update complete
        else PR is BLOCKED/UNKNOWN
            Supervisor->>Supervisor: Log as skipped
        end
    end
    Supervisor->>Supervisor: Report merged/closed stats
    end

    rect rgba(150, 200, 100, 0.5)
    Note over Supervisor,GitHub: Phase 3a Extended: Orphan PR Adoption & Linkage
    Supervisor->>GitHub: List PRs with headRefName
    GitHub-->>Supervisor: PR list (includes headRefName)
    
    alt Task ID found in PR title or branch
        Supervisor->>DB: Find existing task
        DB-->>Supervisor: Existing task
        Supervisor->>DB: Link PR to task (status=complete)
        DB-->>Supervisor: Linked
        opt Task in terminal state (verified/deployed/merged)
            Supervisor->>Supervisor: Log Phase 3d will handle
        end
    else No task ID found
        Supervisor->>DB: Create synthetic task (id pr<number>)
        DB-->>Supervisor: Task created
        Supervisor->>Supervisor: Log adoption, increment counter
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #917: Implements orphaned-PR detection and linking logic; directly related to the enhanced adopt_untracked_prs function in this PR.
  • PR #1704: Extends adopt_untracked_prs Phase 3a adoption logic with synthetic task creation for orphan PRs; core overlap with this PR's orphan handling.
  • PR #1790: Modifies pulse.sh Phase 3 PR/merge handling including post-merge git operations; shares Phase 3 reconciliation scope.

Poem

🔀 Branch Reconcilers Unite

Phase 3d now closes what lingers and waits,
While orphaned PRs find their fated fates,
GitHub queries dance, merges align,
From BEHIND to CLEAN, the branches now shine! 🚀

🚥 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 changes: introduction of Phase 3d for PR lifecycle handling and orphan PR adoption logic, which are the primary objectives of this changeset.
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 docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/supervisor-lifecycle-gaps

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.

@github-actions
Copy link

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Tue Feb 24 04:44:44 UTC 2026: Code review monitoring started
Tue Feb 24 04:44:44 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 42

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 42
  • VULNERABILITIES: 0

Generated on: Tue Feb 24 04:44:47 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

@marcusquinn marcusquinn merged commit 3a95409 into main Feb 24, 2026
10 of 11 checks passed
@marcusquinn marcusquinn deleted the bugfix/supervisor-lifecycle-gaps branch February 24, 2026 04:47
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 two significant improvements to the supervisor's lifecycle management: a new 'Phase 3d' to merge pull requests for already verified or deployed tasks, and an enhanced orphan PR adoption mechanism. The logic to address these gaps is sound. My review focuses on improving the implementation's robustness and performance by addressing the use of 2>/dev/null where it can hide important errors, while acknowledging specific exceptions for non-blocking SQLite writes, and by suggesting optimizations for repeated jq calls, in line with the repository's general rules.

Comment on lines +2271 to +2282
verified_with_prs=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT id, status, pr_url, repo FROM tasks
WHERE status IN ('verified', 'deployed')
AND pr_url IS NOT NULL
AND pr_url != ''
AND pr_url != 'no_pr'
AND pr_url != 'task_only'
AND pr_url != 'verified_complete'
AND pr_url != 'task_obsolete'
ORDER BY updated_at DESC
LIMIT 50;
" 2>/dev/null || echo "")

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors from the db command, such as SQL syntax errors or database connection issues. According to the repository's general rules, error suppression should be avoided to aid debugging. Please remove 2>/dev/null to ensure any potential database errors are visible.

Suggested change
verified_with_prs=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT id, status, pr_url, repo FROM tasks
WHERE status IN ('verified', 'deployed')
AND pr_url IS NOT NULL
AND pr_url != ''
AND pr_url != 'no_pr'
AND pr_url != 'task_only'
AND pr_url != 'verified_complete'
AND pr_url != 'task_obsolete'
ORDER BY updated_at DESC
LIMIT 50;
" 2>/dev/null || echo "")
verified_with_prs=$(db -separator '|' "$SUPERVISOR_DB" "
SELECT id, status, pr_url, repo FROM tasks
WHERE status IN ('verified', 'deployed')
AND pr_url IS NOT NULL
AND pr_url != ''
AND pr_url != 'no_pr'
AND pr_url != 'task_only'
AND pr_url != 'verified_complete'
AND pr_url != 'task_obsolete'
ORDER BY updated_at DESC
LIMIT 50;
" || echo "")
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines +2300 to +2301
vt_pr_json=$(gh pr view "$vt_pr_number" --repo "$vt_repo_slug" \
--json state,mergeStateStatus,mergeable 2>/dev/null || echo "")

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors from the gh command, such as authentication failures, network issues, or if the PR/repo doesn't exist. According to the repository's general rules, error suppression should be avoided to aid debugging. Please remove 2>/dev/null.

Suggested change
vt_pr_json=$(gh pr view "$vt_pr_number" --repo "$vt_repo_slug" \
--json state,mergeStateStatus,mergeable 2>/dev/null || echo "")
vt_pr_json=$(gh pr view "$vt_pr_number" --repo "$vt_repo_slug" \
--json state,mergeStateStatus,mergeable || echo "")
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines 3833 to +3834
open_prs=$(gh pr list --repo "$repo_slug" --state open --limit 20 \
--json number,title,url 2>/dev/null || echo "[]")
--json number,title,url,headRefName 2>/dev/null || echo "[]")

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors from the gh command, such as authentication failures or network issues. According to the repository's general rules, error suppression should be avoided to aid debugging. Please remove 2>/dev/null.

Suggested change
open_prs=$(gh pr list --repo "$repo_slug" --state open --limit 20 \
--json number,title,url 2>/dev/null || echo "[]")
--json number,title,url,headRefName 2>/dev/null || echo "[]")
open_prs=$(gh pr list --repo "$repo_slug" --state open --limit 20 \
--json number,title,url,headRefName || echo "[]")
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines +3864 to +3866
orphan_existing=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE pr_url = '$(sql_escape "$pr_url")' LIMIT 1;
" 2>/dev/null || echo "")

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors from the db command, such as SQL syntax errors or database connection issues. According to the repository's general rules, error suppression should be avoided to aid debugging. Please remove 2>/dev/null.

Suggested change
orphan_existing=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE pr_url = '$(sql_escape "$pr_url")' LIMIT 1;
" 2>/dev/null || echo "")
orphan_existing=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE pr_url = '$(sql_escape "$pr_url")' LIMIT 1;
" || echo "")
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines +3879 to +3881
already_adopted=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE id = '$(sql_escape "$orphan_id")' LIMIT 1;
" 2>/dev/null || echo "")

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors from the db command, such as SQL syntax errors or database connection issues. According to the repository's general rules, error suppression should be avoided to aid debugging. Please remove 2>/dev/null.

Suggested change
already_adopted=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE id = '$(sql_escape "$orphan_id")' LIMIT 1;
" 2>/dev/null || echo "")
already_adopted=$(db "$SUPERVISOR_DB" "
SELECT id FROM tasks WHERE id = '$(sql_escape "$orphan_id")' LIMIT 1;
" || echo "")
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

[[ -z "$vt_pr_json" ]] && continue

local vt_pr_state
vt_pr_state=$(printf '%s' "$vt_pr_json" | jq -r '.state // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")

Choose a reason for hiding this comment

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

medium

Suppressing stderr with 2>/dev/null can hide jq syntax errors or issues with the input JSON. The repository's general rules recommend using || true for optional lookups but keeping stderr visible for debugging. Please remove 2>/dev/null.

Suggested change
vt_pr_state=$(printf '%s' "$vt_pr_json" | jq -r '.state // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")
vt_pr_state=$(printf '%s' "$vt_pr_json" | jq -r '.state // "UNKNOWN"' || echo "UNKNOWN")
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.


if [[ "$vt_pr_state" == "OPEN" ]]; then
local vt_merge_state
vt_merge_state=$(printf '%s' "$vt_pr_json" | jq -r '.mergeStateStatus // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")

Choose a reason for hiding this comment

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

medium

Suppressing stderr with 2>/dev/null can hide jq syntax errors or issues with the input JSON. The repository's general rules recommend using || true for optional lookups but keeping stderr visible for debugging. Please remove 2>/dev/null.

Suggested change
vt_merge_state=$(printf '%s' "$vt_pr_json" | jq -r '.mergeStateStatus // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")
vt_merge_state=$(printf '%s' "$vt_pr_json" | jq -r '.mergeStateStatus // "UNKNOWN"' || echo "UNKNOWN")
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

Comment on lines +2324 to +2327
write_proof_log --task "$vt_id" --event "phase3d_merge" --stage "phase_3d" \
--decision "merged open PR for verified task" \
--evidence "pr=#$vt_pr_number merge_state=$vt_merge_state task_status=$vt_status" \
--maker "pulse:phase_3d" 2>/dev/null || true

Choose a reason for hiding this comment

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

medium

Suppressing stderr with 2>/dev/null can hide important errors from write_proof_log, such as file permission issues or invalid arguments. The repository's general rules advise against this to aid debugging. Please remove 2>/dev/null.

Suggested change
write_proof_log --task "$vt_id" --event "phase3d_merge" --stage "phase_3d" \
--decision "merged open PR for verified task" \
--evidence "pr=#$vt_pr_number merge_state=$vt_merge_state task_status=$vt_status" \
--maker "pulse:phase_3d" 2>/dev/null || true
write_proof_log --task "$vt_id" --event "phase3d_merge" --stage "phase_3d" \
--decision "merged open PR for verified task" \
--evidence "pr=#$vt_pr_number merge_state=$vt_merge_state task_status=$vt_status" \
--maker "pulse:phase_3d" || true
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines 3840 to 3846
while [[ "$i" -lt "$pr_count" ]]; do
local pr_number pr_title pr_url
local pr_number pr_title pr_url pr_branch
pr_number=$(printf '%s' "$open_prs" | jq -r ".[$i].number" 2>/dev/null || echo "")
pr_title=$(printf '%s' "$open_prs" | jq -r ".[$i].title" 2>/dev/null || echo "")
pr_url=$(printf '%s' "$open_prs" | jq -r ".[$i].url" 2>/dev/null || echo "")
pr_branch=$(printf '%s' "$open_prs" | jq -r ".[$i].headRefName" 2>/dev/null || echo "")
i=$((i + 1))

Choose a reason for hiding this comment

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

medium

This loop makes multiple jq calls to extract different fields from the same JSON object, which is inefficient. The repository's general rules recommend consolidating multiple jq calls into a single pass. Additionally, suppressing stderr with 2>/dev/null hides potential jq errors.

A more efficient and robust approach would be to refactor the entire loop to let jq handle the iteration:

printf '%s' "$open_prs" | jq -c '.[]' | while IFS= read -r pr_json; do
    local pr_number pr_title pr_url pr_branch
    pr_number=$(printf '%s' "$pr_json" | jq -r '.number // ""')
    pr_title=$(printf '%s' "$pr_json" | jq -r '.title // ""')
    pr_url=$(printf '%s' "$pr_json" | jq -r '.url // ""')
    pr_branch=$(printf '%s' "$pr_json" | jq -r '.headRefName // ""')

    # ... rest of the loop logic ...
done

This avoids the shell loop counter, repeated parsing of the large $open_prs variable, and allows for more graceful error handling.

References
  1. Consolidate multiple 'jq' calls into a single pass where possible to improve performance and script efficiency.
  2. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/supervisor/pulse.sh:
- Around line 3945-3950: The current branch skips adopting PRs when
existing_status matches verified|deployed|merged, leaving new PRs untracked;
update the conditional handling in pulse.sh so that when existing_status =~
^(verified|deployed|merged)$ you still detect whether the PR (pr_number) is
already linked to the task (task_id) and, if not, adopt it by invoking a linkage
routine (e.g., link_pr_to_task or create_synthetic_orphan_task) or create a
synthetic orphan task that records pr_number/task_id so Phase 3d can close/merge
it; ensure the new logic logs the adoption and preserves the original
log_verbose message for already-linked PRs.
- Around line 2307-2315: The current merge condition treats mergeStateStatus
"UNSTABLE" as acceptable; change the logic so only "CLEAN" allows merging:
update the check that inspects vt_merge_state (derived from
vt_pr_json/.mergeStateStatus) to permit merging only when vt_merge_state ==
"CLEAN" and treat "UNSTABLE" as a skip (log a skip message and do not call gh pr
merge for vt_pr_number in vt_repo_slug); ensure existing logging and
success/failure handling around gh pr merge remains consistent.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a088f4d and f21a18c.

📒 Files selected for processing (1)
  • .agents/scripts/supervisor/pulse.sh

Comment on lines +2307 to +2315
if [[ "$vt_pr_state" == "OPEN" ]]; then
local vt_merge_state
vt_merge_state=$(printf '%s' "$vt_pr_json" | jq -r '.mergeStateStatus // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")

if [[ "$vt_merge_state" == "CLEAN" || "$vt_merge_state" == "UNSTABLE" ]]; then
# CI passed — squash merge the PR
log_info " Phase 3d: $vt_id ($vt_status) — PR #$vt_pr_number still open with CI green, merging"
if gh pr merge "$vt_pr_number" --repo "$vt_repo_slug" --squash --delete-branch 2>>"$SUPERVISOR_LOG"; then
log_success " Phase 3d: Merged PR #$vt_pr_number for $vt_id"
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

🧩 Analysis chain

🌐 Web query:

GitHub API mergeStateStatus CLEAN UNSTABLE meanings documentation

💡 Result:

In GitHub’s GraphQL API (PullRequest.mergeStateStatus, type MergeStateStatus):

  • CLEAN: The PR is mergeable and its commit status checks are passing. [1]
  • UNSTABLE: The PR is mergeable, but its commit status checks are not passing (e.g., failing or not successful). [1]

Source: GitHub GraphQL enum docs for MergeStateStatus. [1]

References

  1. GitHub Docs – MergeStateStatus enum (CLEAN, UNSTABLE definitions). [1]

🏁 Script executed:

# First, check the actual file and lines in question
wc -l .agents/scripts/supervisor/pulse.sh

Repository: marcusquinn/aidevops

Length of output: 104


🏁 Script executed:

# Read the section around lines 2307-2315
sed -n '2300,2330p' .agents/scripts/supervisor/pulse.sh

Repository: marcusquinn/aidevops

Length of output: 1722


🏁 Script executed:

# Run ShellCheck on the entire file
shellcheck .agents/scripts/supervisor/pulse.sh

Repository: marcusquinn/aidevops

Length of output: 46


Restrict merges to CLEAN merge state only; UNSTABLE indicates failing checks.

GitHub's mergeStateStatus=UNSTABLE means commit checks are not passing—contradicting the log message "CI passed." Merging here bypasses CI gating and breaks the automation guarantee. Restrict to CLEAN only and treat UNSTABLE as a skip condition.

Fix: Gate on CLEAN state exclusively
-					if [[ "$vt_merge_state" == "CLEAN" || "$vt_merge_state" == "UNSTABLE" ]]; then
+					if [[ "$vt_merge_state" == "CLEAN" ]]; then
 						# CI passed — squash merge the PR
 						log_info "  Phase 3d: $vt_id ($vt_status) — PR #$vt_pr_number still open with CI green, merging"
 						if gh pr merge "$vt_pr_number" --repo "$vt_repo_slug" --squash --delete-branch 2>>"$SUPERVISOR_LOG"; then
+					elif [[ "$vt_merge_state" == "UNSTABLE" ]]; then
+						log_verbose "  Phase 3d: $vt_id — PR #$vt_pr_number has failing checks, skipping"
 					elif [[ "$vt_merge_state" == "BEHIND" ]]; then
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/supervisor/pulse.sh around lines 2307 - 2315, The current
merge condition treats mergeStateStatus "UNSTABLE" as acceptable; change the
logic so only "CLEAN" allows merging: update the check that inspects
vt_merge_state (derived from vt_pr_json/.mergeStateStatus) to permit merging
only when vt_merge_state == "CLEAN" and treat "UNSTABLE" as a skip (log a skip
message and do not call gh pr merge for vt_pr_number in vt_repo_slug); ensure
existing logging and success/failure handling around gh pr merge remains
consistent.

Comment on lines +3945 to +3950
# For verified/deployed tasks: the PR is a new/different one for
# an already-completed task. Phase 3d will handle merging/closing
# open PRs for verified tasks, so just log and skip here.
if [[ "$existing_status" =~ ^(verified|deployed|merged)$ ]]; then
log_verbose "Phase 3a: PR #$pr_number for $task_id (status: $existing_status) — Phase 3d will handle"
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 | 🟠 Major

Terminal tasks with new PRs are left untracked.

When existing_status is verified/deployed/merged, the PR is only logged and skipped. If this is a new PR (e.g., interactive follow‑up), it never gets adopted and Phase 3d won’t act on it. Consider linking the PR for terminal tasks (or creating a synthetic orphan task) so the lifecycle can close it.

🔧 Minimal linkage option (keeps Phase 3d functional)
-				if [[ "$existing_status" =~ ^(verified|deployed|merged)$ ]]; then
-					log_verbose "Phase 3a: PR #$pr_number for $task_id (status: $existing_status) — Phase 3d will handle"
-				fi
+				if [[ "$existing_status" =~ ^(verified|deployed|merged)$ ]]; then
+					# Link the PR so Phase 3d can act on it
+					db "$SUPERVISOR_DB" "
+					UPDATE tasks
+					SET pr_url = '$(sql_escape "$pr_url")',
+					    updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
+					WHERE id = '$(sql_escape "$task_id")';
+				" 2>/dev/null || true
+					log_verbose "Phase 3a: PR #$pr_number linked to terminal task $task_id (status: $existing_status)"
+				fi
📝 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
# For verified/deployed tasks: the PR is a new/different one for
# an already-completed task. Phase 3d will handle merging/closing
# open PRs for verified tasks, so just log and skip here.
if [[ "$existing_status" =~ ^(verified|deployed|merged)$ ]]; then
log_verbose "Phase 3a: PR #$pr_number for $task_id (status: $existing_status) — Phase 3d will handle"
fi
# For verified/deployed tasks: the PR is a new/different one for
# an already-completed task. Phase 3d will handle merging/closing
# open PRs for verified tasks, so just log and skip here.
if [[ "$existing_status" =~ ^(verified|deployed|merged)$ ]]; then
# Link the PR so Phase 3d can act on it
db "$SUPERVISOR_DB" "
UPDATE tasks
SET pr_url = '$(sql_escape "$pr_url")',
updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
WHERE id = '$(sql_escape "$task_id")';
" 2>/dev/null || true
log_verbose "Phase 3a: PR #$pr_number linked to terminal task $task_id (status: $existing_status)"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/supervisor/pulse.sh around lines 3945 - 3950, The current
branch skips adopting PRs when existing_status matches verified|deployed|merged,
leaving new PRs untracked; update the conditional handling in pulse.sh so that
when existing_status =~ ^(verified|deployed|merged)$ you still detect whether
the PR (pr_number) is already linked to the task (task_id) and, if not, adopt it
by invoking a linkage routine (e.g., link_pr_to_task or
create_synthetic_orphan_task) or create a synthetic orphan task that records
pr_number/task_id so Phase 3d can close/merge it; ensure the new logic logs the
adoption and preserves the original log_verbose message for already-linked PRs.

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