Skip to content

Rejected command registration silently drops that command and all later siblings — dropped commands then exit 0 with a misleading arity error, and pm extension --manage leaves activation_status unknown #772

Closed

Description

@unbraind

Summary

When an extension's command registration is rejected (e.g. the 2026.7.27 host-owned global
flag guard), registration aborts at the offending command. Commands registered before
it stay live; the offending command and every command after it are silently dropped.

The dropped commands then behave in a way that actively misleads an agent:

  • pm <group> <dropped-command> --help exits 0 and prints the parent group's help. It
    does not say unknown_command, so the command looks like it exists.
  • pm <group> <dropped-command> fails with a Commander arity message —
    error: too many arguments for '<group>'. Expected 0 arguments but got 1: <cmd> — which
    never mentions extensions, activation, or the real cause.
  • Both exit 0, so pm <group> <cmd> || handle_failure never fires.

pm health does know (extensions=warn, warnings: ["extension_activate_failed:..."],
ok:false) and pm install does report ok:false. The information exists — it just never
reaches the command path where an agent actually hits the problem.

Reproduction (pm 2026.7.27)

pm-csv@2026.7.23 is a convenient real fixture: it declares --json on csv validate
(registration_index 1), which 2026.7.27 correctly rejects. It registers three subcommands in
order: import (0), validate (1), export (2).

W=$(mktemp -d); cd "$W"; export PM_PATH="$W/.pm"
pm init probe --json >/dev/null
pm install npm:pm-csv@2026.7.23 --project --json | jq '{ok, warnings}'
{ "ok": false,
  "warnings": ["extension_activate_failed:project:pm-csv",
               "extension_install_activation_failed:project:pm-csv:failed"] }

Now compare the registered surface against the fixed release, in identical fresh workspaces:

pm-csv 2026.7.23   subcommands registered: 1     `csv validate` flags: 0
pm-csv 2026.7.27   subcommands registered: 3     `csv validate` flags: 5

So validate and export are gone, while import survives. Then:

$ pm csv validate --help ; echo "exit=$?"
Usage: pm csv [options] [command]

Extension-provided command group.

Options:
  -h, --help        display help for command

Commands:
  import [options]  Import pm items from a CSV file with full RFC-4180 parsing
exit=0

$ pm csv validate ; echo "exit=$?"
Error: Invalid command usage

What happened:
  error: too many arguments for 'csv'. Expected 0 arguments but got 1: validate.
exit=0

Nothing in either response indicates that an extension failed to activate, which command was
dropped, or that a host-owned flag collision is the cause. The --help output is the most
misleading part: it renders a valid-looking group and silently omits two of three commands.

For contrast, the diagnostic is available elsewhere in the same workspace:

$ pm health --json | jq '.checks[]|select(.name=="extensions")|{status, warnings:.details.warnings}'
{ "status": "warn", "warnings": ["extension_activate_failed:project:pm-csv"] }

How this bites in practice

I hit this on a real hub tracker whose pm-csv install predated a host upgrade. The failure
surfaced only as an unrelated command's error payload happening to carry a failed_extensions
block. The natural audit command reports nothing useful:

$ pm extension --manage --json | jq '.details.extensions[]|{name, version, active, enabled, runtime_active, activation_status}'
{ "name": "pm-csv", "version": "2026.7.23", "active": true, "enabled": true,
  "runtime_active": null, "activation_status": "unknown" }

pm extension --manage is documented as "List managed extensions with update-check metadata"
and already carries exactly the two fields that would answer this — runtime_active and
activation_status — but they are null / "unknown" even in the same process that just
rejected the extension. Its whole payload contains zero occurrences of shadow,
host-owned, or reject. (pm extension --explore does surface the warning; --manage
does not; --describe does not.)

This is also why partial activation is more dangerous than a clean whole-extension failure: a
half-registered extension looks alive from every direction an agent would check.

Suggested fixes

  1. Do not leave dropped commands as silent gaps. When a command's registration is
    rejected, either fail the extension's registration as a unit, or keep a placeholder that
    reports the real cause. pm csv validate should say "command unavailable: pm-csv failed
    to activate — registerFlags flags[5] cannot shadow host-owned global flag --json", not
    an arity error.
  2. Non-zero exit for invoking a command that exists in the manifest but was dropped at
    activation. Exit 0 here defeats every shell and CI guard.
  3. Populate activation_status / runtime_active in pm extension --manage. The fields
    already exist; wiring them to the same signal pm health uses would make the one natural
    audit command sufficient.
  4. Have pm <group> --help note that N of M manifest-declared commands are unavailable due
    to activation failure, so the omission is visible where an agent reads the surface.

(1) and (3) are the high-leverage ones: (1) removes the misleading path, (3) makes the
problem discoverable before an agent trips over it.

Environment

Activity

  1. coderabbitai commented on Jul 27, 2026

    @coderabbitai
    🔗 Related PRs

    #150 - Extension SDK platform maturity: typed flags, self-identity, lifecycle teardown, field-type validation & override testing helpers [closed]
    #418 - Refactor residual CodeFactor complexity hotspots [merged]
    #428 - Harden SDK extension runtime packaging [merged]
    #475 - Improve package install and annotation agent UX [merged]
    #479 - feat(package): isolate project doctor diagnostics [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 27, 2026

    @unbraind
    OwnerAuthor

    Canonical PM owner: pm-4vwcvq. It is linked as discovered from the earlier activation-diagnostics owner and adds atomic registration, stable nonzero unavailable-command errors, manage/help parity, and packed-extension acceptance criteria.\n\nCodeRabbit's related-PR inventory is useful context; the new PM item captures the narrower partial-registration and zero-exit regression that those prior deliveries did not close.

  3. unbraind commented on Jul 27, 2026

    @unbraind
    OwnerAuthor

    Implementation is now in PR #777: atomic activation rollback, stable nonzero dropped-command recovery, default manage runtime activation truth, and packed pm-csv@2026.7.23 regression proof. Canonical tracker: https://github.com/unbraind/pm-cli/blob/feat/runtime-capability-contracts-mcp/.agents/pm/issues/pm-4vwcvq.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