Skip to content

Reciprocal blocked_by edits on different branches merge clean into a dependency cycle that default pm validate misses; pm next then silently returns nothing #610

Closed as not planned

Description

@unbraind

Summary

Two agents on separate branches each add a blocked_by on the other's item (independent edits to different files → no git conflict). The merge is clean, but it creates a dependency cycle (pm-A → pm-B → pm-A) that the default pm validate does not flag, and pm next then silently returns nothing — both items become permanently un-actionable while the merge gate stays green.

Verified repro (pm 2026.7.18; items pm-AAAA, pm-BBBB)

git checkout -b brC
pm update pm-AAAA --blocked-by pm-BBBB --author agentA --json >/dev/null
git add -A && git commit -m "C: A blocked_by B"
git checkout -b brD main
pm update pm-BBBB --blocked-by pm-AAAA --author agentB --json >/dev/null
git add -A && git commit -m "D: B blocked_by A"
git checkout brC && git merge --no-edit brD            # CLEAN (rc=0)
pm validate --json                                              # ok: true   (cycle NOT caught)
pm validate --check-lifecycle --json                            # ok: true   (default cycle severity = warn)
pm validate --check-lifecycle --dependency-cycle-severity error --json   # ok: false (only this catches it)
pm next --json                                                  # no actionable item (silent dead-end)

Impact

A cross-branch dependency cycle is a classic multi-agent merge hazard (each agent's edit is locally valid; only the combination is broken). It survives the default merge gate and quietly starves the ready-queue. An agent running pm validate && merge sees green and moves on; pm next later returns nothing with no explanation.

Suggested fixes

  1. Make dependency-cycle detection part of the default pm validate (at minimum surfaced as an error in a --strict-exit/merge context), not gated behind --check-lifecycle --dependency-cycle-severity error.
  2. Have pm next emit an explicit blocked_by_cycle reason (with the offending item ids) instead of returning an empty recommendation, so the dead-end is self-diagnosing.

Filed from a multi-agent merge stress test; reproduced independently on 2026.7.18.

Activity

  1. added
    bugSomething isn't working
    agent-experienceImproves the AI agent / MCP / CLI ergonomics and token efficiency
    on Jul 18, 2026
  2. coderabbitai commented on Jul 18, 2026

    @coderabbitai
    🔗 Related PRs

    #37 - Improve agent token UX and blocked dependency handling [closed]
    #200 - Add validation self-repair and agent ergonomics primitives [closed]
    #406 - feat(mcp): extension-aware built-in actions + action-scoped name schema (pm-zumn, pm-fq80) [merged]
    #502 - Atomic agent work selection, dependency integrity, and recovery primitives [merged]
    #545 - SDK contract integrity: workspace paths, dependency truth, validation, and MCP parity [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. unbraind commented on Jul 19, 2026

    @unbraind
    OwnerAuthor

    Closing this as a duplicate of #590 (and the cycle-detection work in #271/#280, all completed) after a more precise re-test on pm 2026.7.18.

    On re-verification, the tool actually handles the merge-created cycle acceptably, and my original claims were imprecise:

    • Default pm validate does NOT "miss" the cycle — it reports it in the lifecycle check: dependency_cycle_count: 1, dependency_cycle_item_count: 2, plus dependency_cycle_item_ids and dependency_cycle_sample_paths. It stays ok:true only because dependency_cycle_severity_policy defaults to warn.
    • pm validate --strict-exit returns rc=1 on the merged cycle — so a merge-safety gate that uses strict-exit (as it should) does catch it. pm validate --check-lifecycle --dependency-cycle-severity error also returns ok:false.
    • pm next is not silent — it returns recommended: null and lists both items under blocked[].

    The only genuinely distinct angle vs #590 is that a cycle can be introduced by a clean git merge (each branch adds one edge to a different item, so no single mutation sees both edges and #590's inline warning cannot fire). But the post-merge gate already exists (--strict-exit → rc=1), so there is no un-addressed defect here. Closing to avoid duplicating the settled #590 decision. The genuinely novel merge findings from the same test are tracked separately in #608, #609, #611, #612.

  4. unbraind commented on Jul 19, 2026

    @unbraind
    OwnerAuthor

    pm tracker item: pm-i6pi (closed as duplicate of GH-590; mutation-time ordering-cycle advisories shipped in PR#593 — merge-path residue tracked by the pm-g5sx merge-semantics family)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-experienceImproves the AI agent / MCP / CLI ergonomics and token efficiencybugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions