Skip to content

Extension CommandHandlerContext never populates PortableWorkspaceContext (GH-685 contract declared but unimplemented) #703

Closed

Description

@unbraind

Summary

PortableWorkspaceContext — the contract added for GH-685 — is declared on CommandHandlerContext but is never populated when an extension command handler is invoked. All three fields are absent at runtime, so the original defect (extension output can only report an absolute pm_root, leaking host paths) is unchanged.

Verified against published @unbrained/pm-cli 2026.7.25.

Contract

dist/core/extensions/extension-types.d.ts:

export interface PortableWorkspaceContext {
  /** Immutable source workspace root, distinct from a sandboxed tracker root. */
  source_workspace_root?: string;
  /** Source VCS repository root when one can be resolved. */
  repo_root?: string;
  /** POSIX tracker path relative to the source workspace when contained there. */
  pm_root_rel?: string;
}

export interface CommandHandlerContext extends PortableWorkspaceContext { /* … */ }

Reproduction

Minimal project-scope extension (.agents/pm/extensions/pm-flagprobe/):

{ "name": "pm-flagprobe", "version": "1.0.0", "entry": "./index.js",
  "capabilities": ["commands", "schema"], "pm": { "compatibility": "v2" } }
export default {
  name: "pm-flagprobe", version: "1.0.0",
  activate(api) {
    api.registerCommand({
      name: "flagprobe",
      description: "Report portable workspace context.",
      async run(ctx) {
        return {
          pm_root_rel: ctx.pm_root_rel ?? null,
          repo_root: ctx.repo_root ?? null,
          source_workspace_root: ctx.source_workspace_root ?? null,
          pm_root: ctx.pm_root,
        };
      },
    });
  },
};
$ git init -q . && pm init            # plain git repo, tracker contained at .agents/pm
$ pm flagprobe --json
{
  "pm_root_rel": null,
  "repo_root": null,
  "source_workspace_root": null,
  "pm_root": "/abs/host/path/evt-test/.agents/pm"
}

Expected

In a git repository whose tracker is contained in the checkout:

  • repo_root → the resolved VCS root
  • source_workspace_root → the immutable source workspace root
  • pm_root_rel → .agents/pm

Actual

All three are undefined. Reproduces both with and without an explicit --pm-path, invoked from the repo root.

Impact

This is the whole point of the GH-685 contract: an extension that wants to record a re-runnable command, a portable file reference, or any user-visible path has nothing but the absolute pm_root. Every such string is machine-specific — it breaks re-runnability for another agent or a CI checkout, and it leaks host filesystem layout into committed tracker items and published output.

Concretely, in our fleet this blocks emitting checkout-relative test commands in tracker items; we currently have to post-process absolute paths out of extension output.

Suggestion

Populate the three fields in the same place the host builds CommandHandlerContext (alongside pm_root) and ExtensionCommandSdk. Since all three are optional, extensions cannot distinguish "host too old" from "not resolvable" — so leaving them unset in a resolvable git checkout is silently indistinguishable from a correct absent value. A contract test asserting pm_root_rel === ".agents/pm" for a contained tracker in a git repo would pin this.

Activity

  1. coderabbitai commented on Jul 25, 2026

    @coderabbitai
    ⚠️ Possible Duplicate Issue(s)
    🔗 Related PRs

    #406 - feat(mcp): extension-aware built-in actions + action-scoped name schema (pm-zumn, pm-fq80) [merged]
    #479 - feat(package): isolate project doctor diagnostics [merged]
    #491 - Harden init target safety and package install verification [merged]
    #545 - SDK contract integrity: workspace paths, dependency truth, validation, and MCP parity [merged]
    #561 - SDK: unify extension input and output host 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 25, 2026

    @unbraind
    OwnerAuthor

    Tracked and actively repaired in pm-fc9gm4, linked to the completed GH-685 lineage.

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