Proposal: fix spec-updater — add Forgejo PR existence check before creating spec PRs to prevent duplicate PRs for same proposal #6172

Open
opened 2026-04-09 17:06:50 +00:00 by HAL9000 · 0 comments
Owner

Agent Improvement Proposal

Pattern Detected

Type: workflow_fix
Affected Agent: spec-updater
Evidence: System watchdog (cycle 31, issue #6163) reported "4 duplicate spec PRs for proposal #5942". Direct inspection confirms PRs #6007 and #6004 are exact duplicates with identical titles: docs(spec): document ReconciliationBlockedError and invariant reconciliation failure behavior. This occurs because the spec-updater stores pending_spec_proposals in-memory only. When the agent restarts (which happens frequently — the system has restarted multiple times today), it loses this state and re-creates PRs for proposals that already have open PRs.

Root Cause

The spec-updater's pending_spec_proposals dict is in-memory only. When the agent session ends and restarts, it has no knowledge of PRs it already created. The agent's process (Step 7) says to check pending_spec_proposals before creating a PR, but this check is useless after a restart because the dict is empty.

Proposed Change

Add a Forgejo PR existence check at the start of implement_approved_spec_proposal() and in the main loop's proposal monitoring. Before creating any spec PR, the agent should:

  1. Search Forgejo for open PRs with the same branch name (spec/update-<milestone>-<short-description>)
  2. If a PR already exists for that branch, skip PR creation and instead adopt the existing PR number into pending_spec_proposals
  3. Log a warning when a duplicate is detected

This is a Forgejo state check (not in-memory state), so it survives agent restarts.

Specifically, in the monitoring loop where proposals are checked for approval, before calling implement_approved_spec_proposal(desc_key, issue_number), add:

# Check if a PR already exists for this proposal
existing_prs = search Forgejo for open PRs where body contains "Closes #<issue_number>"
if existing_prs:
    # Adopt existing PR instead of creating duplicate
    log(f"Adopting existing PR #{existing_prs[0].number} for proposal #{issue_number}")
    pending_spec_prs[desc_key] = existing_prs[0].number
    continue  # Skip PR creation

Also add a startup recovery step: at the beginning of each session, query Forgejo for all open spec PRs and reconstruct pending_spec_proposals from them by parsing the Closes #N references in PR bodies.

Expected Impact

  • Eliminates duplicate spec PRs (currently 4 duplicates for proposal #5942 alone)
  • Reduces human review burden (fewer duplicate PRs to close)
  • Makes spec-updater resilient to restarts
  • Reduces noise in the PR list

Risk Assessment

  • Low risk: This is a purely additive check. If the Forgejo search fails, the agent falls back to creating a new PR (existing behavior). No existing functionality is removed.
  • Potential issue: If branch names are not deterministic across restarts, the search may miss existing PRs. Mitigation: also search by Closes #<issue_number> in PR body, which is more reliable.

This is a proposal from the agent evolver. A human must approve this issue before the change will be implemented. To approve: remove the needs feedback label, add State/Verified, or comment with approval.


Automated by CleverAgents Bot
Supervisor: Agent Evolver | Agent: agent-evolver

## Agent Improvement Proposal ### Pattern Detected **Type**: workflow_fix **Affected Agent**: spec-updater **Evidence**: System watchdog (cycle 31, issue #6163) reported "4 duplicate spec PRs for proposal #5942". Direct inspection confirms PRs #6007 and #6004 are exact duplicates with identical titles: `docs(spec): document ReconciliationBlockedError and invariant reconciliation failure behavior`. This occurs because the spec-updater stores `pending_spec_proposals` in-memory only. When the agent restarts (which happens frequently — the system has restarted multiple times today), it loses this state and re-creates PRs for proposals that already have open PRs. ### Root Cause The spec-updater's `pending_spec_proposals` dict is in-memory only. When the agent session ends and restarts, it has no knowledge of PRs it already created. The agent's process (Step 7) says to check `pending_spec_proposals` before creating a PR, but this check is useless after a restart because the dict is empty. ### Proposed Change Add a **Forgejo PR existence check** at the start of `implement_approved_spec_proposal()` and in the main loop's proposal monitoring. Before creating any spec PR, the agent should: 1. Search Forgejo for open PRs with the same branch name (`spec/update-<milestone>-<short-description>`) 2. If a PR already exists for that branch, skip PR creation and instead adopt the existing PR number into `pending_spec_proposals` 3. Log a warning when a duplicate is detected This is a **Forgejo state check** (not in-memory state), so it survives agent restarts. Specifically, in the monitoring loop where proposals are checked for approval, before calling `implement_approved_spec_proposal(desc_key, issue_number)`, add: ``` # Check if a PR already exists for this proposal existing_prs = search Forgejo for open PRs where body contains "Closes #<issue_number>" if existing_prs: # Adopt existing PR instead of creating duplicate log(f"Adopting existing PR #{existing_prs[0].number} for proposal #{issue_number}") pending_spec_prs[desc_key] = existing_prs[0].number continue # Skip PR creation ``` Also add a **startup recovery step**: at the beginning of each session, query Forgejo for all open spec PRs and reconstruct `pending_spec_proposals` from them by parsing the `Closes #N` references in PR bodies. ### Expected Impact - Eliminates duplicate spec PRs (currently 4 duplicates for proposal #5942 alone) - Reduces human review burden (fewer duplicate PRs to close) - Makes spec-updater resilient to restarts - Reduces noise in the PR list ### Risk Assessment - **Low risk**: This is a purely additive check. If the Forgejo search fails, the agent falls back to creating a new PR (existing behavior). No existing functionality is removed. - **Potential issue**: If branch names are not deterministic across restarts, the search may miss existing PRs. Mitigation: also search by `Closes #<issue_number>` in PR body, which is more reliable. --- *This is a proposal from the agent evolver. A human must approve this issue before the change will be implemented. To approve: remove the `needs feedback` label, add `State/Verified`, or comment with approval.* --- **Automated by CleverAgents Bot** Supervisor: Agent Evolver | Agent: agent-evolver
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#6172
No description provided.