Skip to content

claude-ops: audit-skill-visibility never determines reachability in a live run and misattributes skillOverrides to plugin skills #4078

Description

@kyle-sexton

Summary

The skill's headline promise is "which skills can the model actually see". In every live run the reachability field is unknown for all skills with cause enablement-undetermined, because collect_fleet_at hardcodes plugin_enabled: None and no collector reads enabledPlugins. Two of the classifier's four documented-settings paths are dead: plugin-not-enabled has no collector, and skill-override-off cannot fire because the frontmatter parser never emits skill_override, and would be wrong if it did, since skillOverrides does not apply to plugin skills at all. The SKILL.md description says a plugin skill can be hidden by skillOverrides; docs and binary say it cannot.

Evidence

  • Live run in this repo, Claude Code 2.1.263: 258 of 258 skills reachability: unknown, cause enablement-undetermined, while .claude/settings.json carries an enabledPlugins map with one plugin set to false.
  • scripts/audit_skill_visibility.py: collect_fleet_at (around line 369) sets "plugin_enabled": None with the comment "Enablement is not knowable from the filesystem alone"; collect_installed (around line 569) never sets it either; reachability (around lines 989-1006) branches on skill_override and plugin_enabled, neither of which any live collector fills.
  • Official docs (settings-reference, skills): enabledPlugins maps plugin@marketplace to a Boolean at Any file scope; false means installed but disabled; "Project settings take precedence over user settings ... set it to false in .claude/settings.local.json ... managed settings override local settings." And: "Plugin skills are not affected by skillOverrides."
  • Binary (2.1.263): enabledPlugins schema text "Settings precedence is user < project < local < flag < policy", per-key merge, last defined scope wins. Listing resolver: if(e.type!=="prompt"||e.source==="plugin")return"on" so plugin-sourced skills never consult skillOverrides.

Expected behaviour

  1. --installed mode: read enabledPlugins through the settings reader introduced by claude-ops: audit-skill-visibility derives the listing budget from hardcoded defaults instead of the effective settings and model #4076 (per-key merge, user < project < local < policy; flag scope reported as unread). A plugin resolved to false makes every one of its skills reachability: hidden, cause plugin-not-enabled, evidence naming the scope file that supplied the false. Absent from every scope resolves to enabled, matching the product's default.
  2. --plugins-root (checkout) mode: enablement is a category error for a checkout. Emit one report line "reachability not assessed: a checkout is not an install" and set each row's reachability to not-assessed instead of 258 rows of unknown. Frontmatter-based misconfigured still fires in both modes.
  3. Remove the skillOverrides path: delete the skill-override-off branch in reachability and any skill_override field, and remove skillOverrides from the SKILL.md description and body as a cause a plugin skill can lose visibility to. State the current rule and its reason (plugin skills are governed by enabledPlugins; skillOverrides governs non-plugin skills this audit does not enumerate), per .claude/rules/skill-bodies-state-current-rules.md.
  4. Keep unknown only for the case the sources genuinely cannot answer (a manifest entry whose settings scopes are all unreadable), and say why in remedy.

Acceptance criteria

  • [event-driven] WHEN .claude/settings.json sets playgrounds@melodic-software: false and the script runs with --installed, every playgrounds:* row reads reachability: hidden, cause plugin-not-enabled, evidence .claude/settings.json.
  • [event-driven] WHEN user settings set a plugin to false and project settings set it to true, its skills are model-reachable (project wins); WHEN local sets false, they are hidden (local wins).
  • [state-driven] WHILE running with --plugins-root, no row reads unknown for enablement; the report carries the single not-assessed line.
  • [unwanted-behaviour] IF a settings file is unreadable or malformed, THEN affected rows read unknown with a remedy naming the file, never hidden or model-reachable.
  • [ubiquitous] No code path or SKILL.md sentence claims skillOverrides affects a plugin skill; ReachabilityTest covers the three precedence cases and the checkout-mode line.
  • scripts/affected-tests.sh --run is green.

Out of scope

Related

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions