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
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.
Source
Handoff-inbox audit item
20260723-155027-claude-ops-plugins-sync-audit(producer: KyleSextonworkstation, CC 2.1.218) — full
/claude-ops:plugins syncrun. 3 findings, all re-verified againstcurrent 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'sresolve_default_marketplaceexact-matches the running plugin root against the version-pinned
installPathininstalled_plugins.json.Whenever the session's loaded version ≠ the installed version — a marketplace
autoUpdateshortlyafter session start, or
sync's own Step-3 self-update of claude-ops — the join finds nothing and theskill's primary no-
--marketplaceinvocation 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 scopedto "this host's jq build", but the hazard is any captured Windows value (
pythonprint, PowerShellinterop,
git config, CRLF file read) — a trailing\ron a constructedclaude pluginid makes theCLI report
Plugin "<name>" not foundwith 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.shsibling that owns the Step 2+3 update loop with the same CR-stripping/fail-loud hygiene.F3 (bug/stale doc; F3a done).
plugins/SKILL.mdtold sync to "branch on the rendered${user_config.install_new}value" and flag "any other value" as invalid — but an unset key rendersthe literal placeholder (the manifest
defaultis not substituted for an unset key; verified vs CC2.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-setunsupported value is flagged.
Acceptance criteria
resolve_default_marketplaceresolves the marketplace across a version skew (session version ≠ installed version); exact match still preferred.fleet-state.test.shhas a passing version-skew case; full suite green;shellcheck -S warningclean.gotchas.mdCRLF entry generalized to any captured Windows value, with the bare-name collision cross-referenced both ways.plugins/SKILL.mdtreats the literal${user_config.install_new}placeholder as the expected unset → defaultask, not invalid.Follow-ups (deferred, not in this PR)
sync-sweep.sh(Step 2+3 update loop as one fail-loud, CR-stripping script emittingstructured per-id JSON), shrinking
sync.mdto "run this, report from its output". Bigger net-newsurface with its own test; deferred to keep this PR focused.
userConfigdefault is intended to substitute for anunset key; file a CC docs issue if docs and behavior disagree. F3a is correct regardless of the answer.
Blocked by
None — can start immediately.