Skip to content

pm update --dep leaves Dependency.author null while --blocked-by/--note/--comment all attribute — the relationship graph is unattributed for every kind except blocked_by #755

Description

@unbraind

Summary

pm update --dep writes dependency edges with author: null, while the very same field, on the same item, written through pm update --blocked-by, is correctly attributed. Every other appended collection (notes, comments, learnings) resolves the author automatically.

Dependency.author exists in the public type and --dep accepts author=<value> explicitly — it is simply never defaulted on that code path.

Reproduction

pm-cli 2026.7.26, fresh pm init. Both edges below are kind=blocked_by, on the same item, written seconds apart:

pm update "$H" --dep "id=$X,kind=blocked_by"   # exit 0
pm update "$H" --blocked-by "$Y"               # exit 0
pm notes  "$H" --add "note for author comparison"
dependencies[2]{id,kind,created_at,author,source_kind}:
  pm-vx91,blocked_by,"2026-07-26T21:00:29.015Z",null,null                      # --dep
  pm-b8sc,blocked_by,"2026-07-26T21:00:29.582Z","harness:claude-code",null     # --blocked-by
notes[1]{created_at,author,text}:
  "2026-07-26T21:00:30.050Z","harness:claude-code",note for author comparison  # notes

Same command, same field, same kind — two flags, two different attribution outcomes.

Why the inconsistency exists

--blocked-by goes through reconcileBlockedByDependency(current, nextBlockedById, nowIsoValue, author), which takes and applies a resolved author. parseDependencyAdditions(raw, prefix, nowIso) — the --dep path — has no author parameter at all, so it can only ever emit what the user typed.

Impact on multi-agent workspaces

This is not cosmetic, for two compounding reasons:

  1. --dep is the only way to add any non-blocked_by kind. blocks, parent, child, related_to, implements, supersedes, verifies, discovered_from, … are reachable exclusively through the unattributed path. So in practice the overwhelming majority of the relationship graph is unattributed, and the one attributed kind is the one with a dedicated flag.

  2. The merge driver unions dependencies across branches (correct behaviour, verified). After N agents merge, the item holds a combined edge set with no provenance:

    dependencies[2]{id,kind,created_at,author,source_kind}:
      pm-djzp,blocked_by,"2026-07-26T20:57:41.001Z",null,null   # which agent?
      pm-idik,blocked_by,"2026-07-26T20:57:42.367Z",null,null   # which agent?

    created_at is the only discriminator, and it is useless when agents work concurrently. Notes merged in the same operation are attributed, so the item ends up self-inconsistent: you can tell who wrote a note but not who asserted a blocking relationship — which is the higher-stakes claim of the two, since blocked_by drives pm next and the scheduling surface.

For a tool whose stated purpose is coordinating multiple agents, "who claimed this dependency" is exactly the question the graph should be able to answer. It's also the natural input to any later dispute/reconciliation flow.

Suggested fix

Thread the already-resolved author into parseDependencyAdditions and default Dependency.author to it when the caller did not supply author= explicitly — i.e. make --dep behave like --blocked-by, --note, --comment, and --learning, all of which already do this.

Explicit author= should keep winning, so importer paths (e.g. pm-github --link-deps, which sets source_kind) can continue to attribute edges to their true origin.

Backfill is not required: existing null authors can stay as "unknown, pre-fix", since the field is already optional.

Environment

  • pm-cli 2026.7.26 (npm @unbrained/pm-cli)
  • Node 22, Linux
  • Fresh pm init; single workspace, no merge involved in the repro above (the merge case is only what makes it hurt).

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