Skip to content

refactor(prerequisites): name the bundled checker in hook notices instead of a /<plugin>:check skill #12485

Description

@kyle-sexton

Refs #7582

Outcome

A missing-tool hook notice names a command that runs the plugin's own bundled checker, not a /<plugin>:check skill. With that in place, the *:check consolidation waves can delete the per-plugin check and check-prerequisites skills without leaving a notice that points at a dead skill.

Design (owner-approved, lane 1 decision from evidence, 2026-11-02): delete the per-plugin check / check-prerequisites skills. Each plugin already declares its tools in prerequisites.json (schema docs/contracts/prerequisites/) and ships lib/prerequisites.mjs. /harness-ops:prerequisites stays as the fleet-wide view, and no plugin gains a dependency on harness-ops.

Why this is a separate slice: the contract names the skill in four places, and wave 1 cannot also carry them under the lane patch cap.

  • The schema requires check and restricts it to a slash command (docs/contracts/prerequisites/prerequisites.schema.json:36, :63).
  • The checker rejects any other value (lib/prerequisites.mjs:207-208).
  • The checker prints Then run ${entry.check}. (:520, :719).
  • The README tells notices to name /<plugin>:check (docs/contracts/prerequisites/README.md:71, :154-158).
  • lib/prerequisites.mjs has 73 byte-identical copies registered in scripts/shared-copies.txt.

Done when

  • Before any edit, a comment here gives this slice's measured git diff --no-renames byte size, counting all 73 regenerated copies and any .changes/ fragments --check-bump requires. The size must be under 262144 bytes; if it is not, this issue is split first.
  • A missing-tool notice, at session start and from hook::require, prints a command that runs the plugin's own lib/prerequisites.mjs with the plugin root already resolved. Copied verbatim into a Bash tool call, the command runs. The Bash tool's environment carries no plugin variables (docs/contracts/prerequisites/README.md:30), so the printed text contains no ${CLAUDE_PLUGIN_ROOT}.
  • The PR names the checker mode the notice uses and gives its basis. Recommended: check <plugin-root>, because README :104 makes it the per-plugin entry point with degrade and install text, while report emits the fleet TSV.
  • The schema and lib/prerequisites.mjs no longer require check to name a skill. Every existing prerequisites.json still validates (scripts/validate-plugins.sh passes).
  • docs/contracts/prerequisites/README.md "Hook notices" and the check row describe the new notice. A short note covers the /<plugin>:check text while the waves run: either it is temporarily still allowed, or it is left out.
  • lib/hook-utils.test.sh, lib/prerequisites.test.sh, lib/prerequisites.test.mjs and plugins/harness-ops/hooks/prerequisites-fleet.test.sh each assert the new notice text. Each fails on main and passes on the branch, red then green.
  • bash scripts/sync-shared-copies.sh --check and bash scripts/sync-shared-copies.sh --check-bump origin/main exit 0.
  • A merge probe is posted per D82/Q186: on a host with one hook dependency hidden from PATH, the notice appears, and running its printed command reports that dependency as FAIL.

Out of scope

  • Deleting any check or check-prerequisites skill (waves 1 to 3).
  • Renaming instruction-placement:check, skill-quality:check and toolchain:check (the naming slice).
  • /harness-ops:prerequisites, which stays as the fleet view.

Related

Activity

  1. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    on Nov 2, 2026
  2. github-actions commented on Nov 2, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: structural
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Knowable
    Flags: none
    Blocked by: none

    Understood: change the missing-tool hook notice (session start and hook::require) to print a runnable command for the plugin's bundled lib/prerequisites.mjs, with the plugin root already resolved. It replaces the /<plugin>:check skill name. The schema, checker, README and the shared-copy tests change with it. The design is already stated in the issue, and the acceptance items are specific, so I found no open intent question. The diff-size measurement and the merge probe on a host with a hidden dependency need a person or a host run. They don't block triage of the rest. I found no likely duplicates beyond the parent #7582.

    Automated triage, applied by the lanes App.

  3. added
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Nov 2, 2026
  4. melodic-automation-lanes commented on Nov 2, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: it carries host-run. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  5. melodic-automation-lanes commented on Nov 2, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: admission moved the issue to status: confirmed; its comment says why.

  6. self-assigned this
    on Nov 2, 2026
  7. kyle-sexton commented on Nov 2, 2026

    @kyle-sexton
    MemberAuthor
    No description provided.
  8. kyle-sexton commented on Nov 2, 2026

    @kyle-sexton
    MemberAuthor

    Slice size, measured before commit (AI-generated, lane 4 session).

    git diff --no-renames of the built slice against origin/main (258464e): 234772 bytes, under the 262144 cap.

    It counts:

    • 73 regenerated copies of lib/prerequisites.mjs (about 2.2 KB each) and the canonical.
    • 20 regenerated copies of lib/hook-utils.sh and the canonical. hook::require renders its notice there.
    • 73 patch fragments under .changes/, one per carrying plugin, that sync-shared-copies.sh --check-bump origin/main requires.
    • The schema, the contract README, and the four test files.

    How it was measured: synced every copy, git add -N .changes, then git diff --no-renames | wc -c. Basis: tool output in the worktree for branch refactor/12485-notice-names-bundled-checker.

  9. kyle-sexton commented on Nov 2, 2026

    @kyle-sexton
    MemberAuthor

    Merge probe (partial). Merged as #12510 (aece4c1).

    Run: a copy of plugins/biome-format/lib/prerequisites.mjs and prerequisites.json from origin/main, in a directory outside any repository, with PATH holding only node, using the command form the notice prints:

    $ node "<root>/lib/prerequisites.mjs" check "<root>"
    FAIL  biome (cli, required): biome was not found on PATH or as node_modules/.bin/biome. [...]
    FAIL  jq (cli, required): jq was not found on PATH. [...]
    PASS  node (runtime, required): [...]
    rc=1
    

    The printed command runs as written and reports the hidden dependency as FAIL.

    Not yet shown: the notice appearing in a live session. That needs this change in a released plugin version on the host; #12486's merge probe covers it. lib/hook-utils.test.sh and prerequisites-fleet.test.sh assert the notice text in the meantime.

    Until wave 2 (#12487), the checker's own failure line still ends "Then run /biome-format:check", from that plugin's check field. The waves remove these fields.

    Posted by the lane 4 session. This was generated by AI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

Type

Fields

Work status

confirmed

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions