Skip to content

claude-ops: fix plugins-skill default-marketplace resolver on version skew; generalize CRLF gotcha; correct install_new render doc (F1-F3) #1176

Description

@kyle-sexton

Source

Handoff-inbox audit item 20260723-155027-claude-ops-plugins-sync-audit (producer: KyleSexton
workstation, CC 2.1.218) — full /claude-ops:plugins sync run. 3 findings, all re-verified against
current source (claude-ops 0.19.0) before implementing.

What to build (one PR, claude-ops 0.19.0 → 0.19.1)

  • F1 (bug, HIGH within item; mechanic). fleet-state.sh's resolve_default_marketplace exact-
    matches the running plugin root against the version-pinned installPath in installed_plugins.json.
    Whenever the session's loaded version ≠ the installed version — a marketplace autoUpdate shortly
    after session start, or sync's own Step-3 self-update of claude-ops — the join finds nothing and the
    skill's primary no---marketplace invocation fails with "could not resolve the default marketplace".
    Fix: version-agnostic fallback matching the version-stripped …/cache/<marketplace>/<plugin> prefix
    (exact match tried first; marketplace stays distinguishable via the path), plus a clearer error that
    prints the searched root and names the version-skew cause. Add a version-skew fixture to
    fleet-state.test.sh.

  • F2 (doc bug + enhancement; F2a done, F2b deferred). context/gotchas.md's CRLF entry was scoped
    to "this host's jq build", but the hazard is any captured Windows value (python print, PowerShell
    interop, git config, CRLF file read) — a trailing \r on a constructed claude plugin id makes the
    CLI report Plugin "<name>" not found with the full id passed (marketplace suffix corrupted),
    colliding with the bare-name symptom. F2a (done): generalized the gotcha to "any captured value",
    documented the collision, cross-referenced the two. F2b (deferred — see Follow-ups): ship a
    sync-sweep.sh sibling that owns the Step 2+3 update loop with the same CR-stripping/fail-loud hygiene.

  • F3 (bug/stale doc; F3a done). plugins/SKILL.md told sync to "branch on the rendered
    ${user_config.install_new} value" and flag "any other value" as invalid — but an unset key renders
    the literal placeholder (the manifest default is not substituted for an unset key; verified vs CC
    2.1.218), which is the common default-config case. F3a (done): doc now reads the literal
    placeholder as the expected unset state → default ask, not an invalid value; only an explicitly-set
    unsupported value is flagged.

Acceptance criteria

  • resolve_default_marketplace resolves the marketplace across a version skew (session version ≠ installed version); exact match still preferred.
  • The unresolved-default error prints the searched root and names the version-skew cause.
  • fleet-state.test.sh has a passing version-skew case; full suite green; shellcheck -S warning clean.
  • gotchas.md CRLF entry generalized to any captured Windows value, with the bare-name collision cross-referenced both ways.
  • plugins/SKILL.md treats the literal ${user_config.install_new} placeholder as the expected unset → default ask, not invalid.
  • Version bumped 0.19.0 → 0.19.1; CHANGELOG updated.

Follow-ups (deferred, not in this PR)

  • F2b: ship sync-sweep.sh (Step 2+3 update loop as one fail-loud, CR-stripping script emitting
    structured per-id JSON), shrinking sync.md to "run this, report from its output". Bigger net-new
    surface with its own test; deferred to keep this PR focused.
  • F3b: verify upstream whether a declared userConfig default is intended to substitute for an
    unset key; file a CC docs issue if docs and behavior disagree. F3a is correct regardless of the answer.

Blocked by

None — can start immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions