Skip to content

Agent UX: pm update --dep accepts a self-referential ordering edge (id=<self>,kind=blocked_by) that pm graph audit forbids ('Self relationship is not allowed') #649

Closed

Description

@unbraind

Summary

pm update --dep id=<self>,kind=blocked_by (or kind=blocks) is accepted and persisted (exit 0), creating a self-referential ordering edge — but pm graph audit immediately declares that exact edge invalid: Self relationship is not allowed for blocked_by. The write path lacks the self-relationship guard that the governance audit enforces, so the CLI happily writes data that its own audit forbids.

Verified on pm --version 2026.7.22 (fresh pm init workspace).

Reproduction

pm init --pm-path /tmp/w --id-prefix px
ID=$(pm create task "Self ref" --pm-path /tmp/w --json | jq -r .id)   # px-1h25

# Write path ACCEPTS a self blocked_by edge:
pm update "$ID" --dep "id=$ID,kind=blocked_by" --pm-path /tmp/w --json
#   exit: 0
#   { "changed_field_count": 1, "status": "open",
#     "warnings": ["ordering_cycle_created:px-1h25 -> px-1h25:items_will_not_be_ready:run_pm_graph_audit"] }

# The edge is durably persisted:
pm show "$ID" --pm-path /tmp/w --json | jq .item.dependencies
#   [ { "id": "px-1h25", "kind": "blocked_by", "created_at": "..." } ]

# But pm graph audit — which the warning above literally tells the agent to run — forbids it:
pm graph audit --pm-path /tmp/w
#   ... "Self relationship is not allowed for blocked_by" ...

Cross-surface behavior (all on the same self-edge)

Surface Result
pm update --dep id=<self>,kind=blocked_by accepted, exit 0, edge persisted (only an advisory warnings[] entry)
pm graph audit rejects it: Self relationship is not allowed for blocked_by
pm deps <self> (--json) cycle: false, tree node not flagged cycle: true
pm next item never recommended/ready (permanently self-blocked)
pm validate counts it in dependency_cycle_count (policy warn, so ok: true)

Contrast pm deps on a multi-node blocked_by cycle (A→B→C→A): there the participating tree nodes are flagged cycle: true. Only the 1-node (self) cycle renders as cycle: false, so an agent inspecting pm deps sees no cycle indicator on the very item that is self-blocked.

Why this matters for agents

An agent can trivially introduce a self blocked_by edge (a mis-scoped --dep id=$ID, or a package that maps an issue-body reference where an item points at its own number). The item then becomes permanently un-ready and drops out of pm next with no hard error at the point of the mistake. The update-time advisory even directs the agent to run_pm_graph_audit, but the write that triggered the advisory was itself something the audit classifies as never-allowed — so the malformed state was fully writable in the first place.

Suggested fix (either is sufficient)

  1. Preferred — guard at write time. Have pm update --dep/--blocked-by reject a self blocked_by/blocks/other ordering edge with the same message the audit already uses (Self relationship is not allowed for <kind>) and exit_code: 2. A self ordering edge is never semantically valid (an item can never unblock itself), so this is safe to reject rather than warn — unlike legacy multi-node debt the advisory intentionally only warns about.
  2. Or — make pm deps consistent. If self-edges are intentionally writable (advisory-only), have pm deps <self> flag the 1-cycle (cycle: true on the node / top-level cycle) the same way multi-node cycles are flagged, so the audit surfaces agree.

Related but distinct: #271 (blocked_by cycle detection in validate) and #280 (parent-hierarchy cycle detection) — both about detection in validate; this report is about the write path accepting an edge the graph audit forbids, plus the pm deps 1-cycle rendering gap.

Activity

  1. coderabbitai commented on Jul 22, 2026

    @coderabbitai
    🔗 Related PRs

    #434 - Fix self-parent guards and pnpm 11 bootstrap gates [merged]
    #545 - SDK contract integrity: workspace paths, dependency truth, validation, and MCP parity [merged]
    #577 - SDK graph context explainability and missing-reference governance [merged]
    #579 - feat(sdk): semantic graph governance and shared actionability [merged]
    #593 - SDK-first agent UX graph, ownership, and recovery contracts [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!

  2. unbraind commented on Jul 23, 2026

    @unbraind
    OwnerAuthor

    pm tracker item:

    This canonical item is linked to the shipped ordering-cycle advisory and relationship-governance lineage and is now part of the active SDK/CLI context-integrity bundle.

  3. unbraind commented on Jul 25, 2026

    @unbraind
    OwnerAuthor

    Shipped. Tracked as pm-k9t17l and closed: alias-aware pre-write self-edge policy at the SDK mutation boundary, with public SDK customization support and zero-write CLI acceptance. Closing here to keep the tracker and this issue in sync.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions