Skip to content

pm read --fields <empty group> returns no id, no requested field, and only the groups you excluded #1033

Closed

Description

@unbraind

Summary

When an agent requests a specific field group with pm read <id> --fields <group> and that group is empty, the response contains no trace of the requested field, drops the item's identity entirely, and spends its whole payload listing the field groups that were not asked for.

For an agent doing --fields-scoped reads to control context size, this is three problems at once: the answer is ambiguous, unattributable, and larger than the thing it was asked for.

Reproduction

pm-cli 2026.8.15. An item that has tests and files but no docs:

$ pm --json read pm-beads-vulo --fields docs
{
  "item": {},
  "omission_receipt": {
    "has_omissions": true,
    "omitted_field_group_count": 5,
    "omitted_field_groups": [
      { "name": "comments", "restore_with": "--fields comments" },
      { "name": "files",    "restore_with": "--fields files" },
      { "name": "tests",    "restore_with": "--fields tests" },
      { "name": "children", "restore_with": "--fields children" },
      { "name": "linked",   "restore_with": "--fields linked" }
    ]
  }
}

The TOON form is the same shape, and omits the item: block altogether.

For contrast, an unknown field name is rejected cleanly, so this is specifically about empty groups:

$ pm read pm-beads-vulo --fields notarealfield
Error: Unknown get --fields value(s): notarealfield

Why this is a problem for agents

  1. docs appears nowhere in the response. It is not in item, and it is not in omitted_field_groups. "The item has no docs" and "the field was not returned" are indistinguishable from the payload. The only way to conclude "empty" is to notice a double absence, which is exactly the kind of inference that produces confident wrong answers.

  2. item is {} — the response has no id. An agent that issues several scoped reads (in parallel, or to fill a context pack) cannot attribute this response to the item it asked about without tracking call order out of band. Every other read shape carries the id.

  3. The omission receipt is inverted relative to the request. The caller asked for exactly one group; the response enumerates the five groups it deliberately excluded, with a restore_with hint for each. On an explicit --fields request those five are not omissions — they are the point of the flag. The receipt is pure overhead here, and it is the entire payload when the requested group is empty.

Suggested fix

For an explicit --fields <groups> request:

  • always include the item identity (id, and ideally title) in item, as every unscoped read does;
  • represent an empty requested group explicitly — "docs": [] — so present-and-empty is distinguishable from absent;
  • scope the omission receipt to groups the caller actually requested but did not fully receive, rather than to the groups --fields was used to exclude. If the receipt is retained for other reasons, an omitted_field_groups: [] for an explicit projection would at least stop it dominating the response.

The general principle: a projection request should answer in the shape of the projection. Today the caller narrows the read and receives a document about everything they narrowed away.

Environment

  • pm-cli 2026.8.15
  • Node 22, Linux

Activity

  1. coderabbitai commented on Aug 15, 2026

    @coderabbitai
    🔗 Related PRs

    #549 - feat(sdk): ship history time travel, rich reads, and runtime integrity [merged]
    #624 - SDK atomic structured mutations, lean output, and agent-first envelopes [merged]
    #818 - SDK context truth, bounded projections, and snapshot lease safety [merged]
    #829 - SDK context budgets, universal read contracts, and bounded diagnostics [merged]
    #957 - SDK agent command contracts, lossless recovery, and truthful context policy [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 Aug 15, 2026

    @unbraind
    OwnerAuthor

    Canonical PM item: pm-4fwgaz. This records the identity/requested-empty projection defect and its shared SDK read-output acceptance contract.

  3. unbraind commented on Aug 16, 2026

    @unbraind
    OwnerAuthor

    Resolved by merged PR #1041. Sparse projections now preserve required identity and requested empty collections across runtime and SDK types. Canonical PM record: https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-4fwgaz.toon

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