Skip to content

v2.0.0 — a plan may not name a skill only its author has

Choose a tag to compare

@AleksandarBisevac AleksandarBisevac released this 31 Aug 20:47
· 7 commits to main since this release

An audit plan names its skills by string, and until now nothing asked whether anyone
else could load them. On the machine that wrote the plan every name resolves — so
/audit:doctor printed a green row while a teammate's clone loaded none of it, and
every task ran without the conventions it was written to follow.

Measured on a real repository: six named skills, five of them from ~/.claude/skills
(in no repository and no marketplace), and four live tasks in the phase due to run next.

What is new

Every discovered skill, subagent and MCP server now carries a verdict — would a clone
of this repository load this?
— and the basis behind it:

  • a capability under .claude/ travels;
  • one in a home directory never does;
  • one from a plugin travels only when the committed .claude/settings.json declares
    it in both extraKnownMarketplaces and enabledPlugins. When exactly one is
    present, the message names the one that is missing — committing only enabledPlugins
    is a documented trap that keeps working for whoever added it.

Four surfaces read that one verdict:

surface what it does
/audit:doctor a plan portability row — a warning at most, naming the skill, where the plan names it, and why
/audit:status --gate --fail-on stranded-skills the CI half, deliberately out of the default gate
the control panel lists what stays here, keeps it out of the pickers, predicts the refusal inline, and refuses the write
the report marks a stranded name from the repository alone, so a shared artifact reads the same on every machine

Read this before upgrading

portability ships "strict", and that changes what an untouched repository accepts.
The panel will refuse a save it took the day before, whenever a name in the patch resolves
on your machine and would not survive a clone. This is the one clause COMPATIBILITY.md
promises against — broken on purpose, recorded there with the reason, because the defect it
prevents is silent on exactly the machine that causes it.

Two ways out, each one row in the Settings tab or in .claude/audit.config.json:

{ "portability": "warn" }   // diagnose everything, refuse nothing
{ "portability": "off" }    // restore the previous behaviour exactly

Other things worth knowing:

  • a name discovery has never seen is still accepted, at every tier — an inventory is not
    a whitelist;
  • stranded-skills fails when the scan could not run, rather than passing quietly;
  • _panel_discovery._mcp_names is now _mcp_entries and returns rows, not strings;
  • check_plan_skills takes the config pair, mirroring check_policy.

Also fixed

  • Two docstrings asserted a layer their module had already left — now a lint
    (layer_doc_drift), proved red in both directions.
  • The policy tab rendered an MCP server's name in the source column.
  • A regression case that could not fail: it compared a level to "finding" while the
    collector writes "FINDING".

Full detail in CHANGELOG.md.