feat(claude-ops): surface missing fleet prerequisites without installing (#4240) - #5096
Conversation
|
PR body contract — issue linkage This PR body conforms to the issue-linkage contract. Nothing to do. |
c693470 to
09f2ea7
Compare
Prerequisite notices latch once per session and keep the install route. markdown-format, biome-format, and go-format probe at session start and name a model-invocable check skill. claude-ops:prerequisites reads each plugin's prerequisites.json and prints which tools are missing. Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
09f2ea7 to
5a15299
Compare
# Conflicts: # plugins/claude-ops/.claude-plugin/plugin.json # plugins/claude-ops/CHANGELOG.md
Hoist each probe's early exit above the hook-utils source, run the three SessionStart probes in exec form, let the format-hook launch gates admit that probe row, add evals for the four new skills, register the new check leaf owners, count thirteen claude-ops skills in the README, and replace A && B || C test lines shellcheck flags. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PT4esxbdC7eQiwQxy35Mie
Resolve conflicts in claude-ops (identical-bump collision at 0.63.25, renumbered to 0.63.26; description conflict resolved by keeping the PR's content unchanged, since main's description text matched the merge base) and source-control (identical-bump collision at 0.62.9, renumbered to 0.62.10). The other 17 touched plugins' version bumps were already strictly above main's and merged clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PT4esxbdC7eQiwQxy35Mie
Re-bump every touched plugin one patch above main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
…eement The session-start probes in biome-format, go-format, and markdown-format are one shared script that takes every tool name, local_bin, check, and install line from the plugin's prerequisites.json instead of hardcoding them. scripts/check-prerequisite-probes.test.sh fails when a probe drifts from the shared reader, carries an install command, or omits a declared tool's name, check, or install text. markdown-format's edit hook now latches on the same notice key as its probe. Restore the claude-ops description the re-bump dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
Re-bump every touched plugin one patch above main and keep the claude-ops description's prerequisites entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c144dfdbc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Re-bump every touched plugin one patch above main. State the prerequisite notice cadence (once per session, renewal keeps the install route) in the hook-observability convention and the biome-format and go-format READMEs, beside main's once-per-session-and-agent wording for other skip notices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
|
Claude finished @kyle-sexton's task in 2m 45s —— View job Security review —
|
|
Claude finished @kyle-sexton's task in 3m 17s —— View job Code review —
|
Register hooks/probe-prerequisite.sh in the cross-plugin source registry with check-prerequisite-probes.test.sh as its drift check, and drop the GNU \b and the piped early-exit grep from that test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
Re-bump claude-ops and source-control one patch above main and keep the claude-ops description's prerequisites entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
|
Claude finished @kyle-sexton's task in 1m 47s —— View job Code review —
|
|
Claude finished @kyle-sexton's task in 1m 1s —— View job Security review —
|
…mpty fleet check-prerequisites.sh merges enabledPlugins from user, project, and local settings (later scope wins), and falls back to scanning the repository only when no settings or install state exists, so a read state with nothing enabled prints an empty table. The skill's Next line points at the row's own check skill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh
|
Claude finished @kyle-sexton's task in 53s —— View job Security review —
|
|
Claude finished @kyle-sexton's task in 2m 54s —— View job Code review —
|
…t:check The setup skill's pre-computed jq row only runs when setup itself loads, so under check it is literal command text. The check skill now runs the probe itself, setup tells a reader to do the same when the row carries no result, and a new eval requires a jq FAIL row when jq is absent. Refs #5096, #4566 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
…pped (#5245) Refs: #4240 Refs: #5096 Refs: #4612 ## Summary The 0.8.5 CHANGELOG entry for `powershell-format` said format hooks probe at session start and that `/claude-ops:prerequisites` reads a `prerequisites.json` from this plugin. Neither exists: `hooks/hooks.json` has only PostToolUse rows, and the plugin ships no `prerequisites.json` or `probe-prerequisite.sh`. The omission is deliberate (README Requirements, `skills/setup/SKILL.md`): `jq` is the only prerequisite the hook script probes, and pwsh, PSScriptAnalyzer and the settings file stay quiet not-applicable. Two cross-group requests also landed here: every hook row runs through `node hooks/exec-bash.mjs`, so Node.js is now a declared prerequisite; and the hook budget figures predate that launcher. ## Fix - Rewrote the single 0.8.5 bullet to state what shipped here: `hooks/hook-utils.sh` was resynced, `hook::notice_once` gained an optional `prerequisite` class, no hook in this plugin passes it, and there is no probe or `prerequisites.json`. - Bumped the plugin to 0.8.6 and added a 0.8.6 `Fixed` entry noting the correction. It links #5286, which tracks adding the probe and manifest to the remaining binary-probing format plugins. - README Requirements now lists Node.js on `PATH` (Claude Code's native binary neither ships nor uses Node, so without `node` the hooks do not launch); the setup `check` gains a `node` probe run through Bash, FAIL when absent, next to `jq`. - README hook budget table carries a dated note that its 0.7.45 figures predate the node launcher and that each fire now adds one `node` process. - Extended the 0.8.6 CHANGELOG entry for the above, no second version bump. - No probe or `prerequisites.json` was added (waits on the #4240 Q1 owner answer); `hook-utils.sh` and `exec-bash.mjs` are untouched. ## Verification - `bash scripts/check-changelog-parity.sh --check --check-order`: pass - `bash scripts/validate-plugins.sh`: all manifests and the catalog validated - `bash scripts/check-purged-em-dashes.sh`: no em dashes - `bash scripts/check-cross-plugin-source-drift.sh`: exit 0 - `bash scripts/check-prerequisite-probes.test.sh`: 18 cases, 0 failed - `bash plugins/powershell-format/hooks/powershell-format.test.sh`: PASS=91 FAIL=0 ## Related - Audit finding `plugin-powershell-format` (changelog-integrity, medium) in `.work/audit/REPORT.md`; originating change #4240, resync in #5096, README note #4612. - No owned issues. Cross-group requests applied: hook-launcher (F26 budget note and node declaration; the launcher code stays with #5309, which also bumps this plugin to 0.8.6, so whichever merges second needs a version and CHANGELOG reconcile) and biome-format (link #5286, no probe or `prerequisites.json` until #4240 Q1 is answered). - Follow-up for the other binary-probing plugins: #5286. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… docs (#5266) Refs: #3574 Refs: #4784 Refs: #4671 Refs: #5096 Refs: #3686 Refs: #4240 Refs: #3356 Refs: #5057 Refs: #4581 ## Summary Audit fixes for `plugins/go-format` (REPORT.md finding `plugin-go-format` and the 3c row for `hooks/probe-prerequisite.sh:43-52`). Closes no issue: #3574 is owned by core-docs and waits on an owner decision. - The SessionStart prerequisite probe ran even with `go_format_enabled=false`, so the disabled plugin still printed a `goimports was not found` notice. - README, setup skill, hook header comments and evals still described the hook as unconditional, which predates the gitignore exemption (#4784). - The setup skill's toggle-off step carried stale scope advice that contradicts the reconfiguration convention. ## Fix - `hooks/hooks.json`: the SessionStart row passes `--run-if-unset-or-true GO_FORMAT_ENABLED` to the launcher, the same shape as `typos-format`. `probe-prerequisite.sh`, `hook-utils.sh` and `exec-bash.mjs` are untouched (the first two are byte-pinned to the shared copy). - `hooks/go-format.test.sh`: hook-wiring selectors match the new args; new behavioral cases assert no notice with the switch off and the notice with it unset or `true`. - `README.md`, `skills/setup/SKILL.md`, `hooks/go-format.sh` and `go-format.test.sh` header comments: "no consumer-config opt-in gate" replaces "unconditional"; the gitignored-file skip and `go_format_lint_gitignored` are documented; the setup `check` action reports the option's effective value. - `skills/setup/SKILL.md` toggle-off: prints the convention's short form (`-s user`, never uninstall to reconfigure, next-session observation, read output not exit code) and cites the convention. - `skills/setup/evals/evals.json`: new eval for the gitignore option; eval 5 aligned with the short form. - `plugin.json` 0.4.5 to 0.4.6 with a CHANGELOG entry. The `plugin.json` description ("Runs unconditionally (no consumer-config gate)") stays accurate; changing it would force a `docs/catalog.md` regeneration outside this change's scope. - Cross-group requests applied: the setup toggle-off step keeps `-s user` per the convention on main, and the setup `check` action keeps `node` a FAIL behind the kill switch. README Requirements and the setup `check` action declare Node.js (hook-launcher request). CHANGELOG entries 0.3.62, 0.3.63, 0.4.2 and 0.4.3 read "Shared launcher/library sync; no change to this plugin's behavior" and 0.4.1 drops the shell-form sentence; these released-entry edits are declared in the 0.4.6 entry and are not folded or renumbered. ## Verification - `bash plugins/go-format/hooks/go-format.test.sh`: PASS=66 FAIL=0 - `bash scripts/validate-plugins.sh`: all manifests and catalog validated - `bash scripts/check-changelog-parity.sh --check --check-order`: pass - `bash scripts/check-prerequisite-probes.test.sh`, `check-hook-exec-form.sh`, `check-hook-userconfig-argv.sh`, `check-hook-wiring-liveness.sh`, `check-killswitch-hoist.sh`, `check-cross-plugin-source-drift.sh`, `check-hooks-description.sh`, `check-purged-em-dashes.sh`: exit 0 - `bash scripts/check-changed-skills.sh origin/main`: setup skill PASS, 0 errors - `python3 scripts/sync-plugin-options-docs.py --check`, `node scripts/generate-catalog.mjs --check`: exit 0 ## Related Audit findings: `plugin-go-format` (correctness, docs-coherence, convention); 3c row `probe-prerequisite.sh:43-52`; 3d finding #3574 (owned by core-docs, not changed here). Related issues: #4784, #4671, #5096, #3686, #4240, #3356, #5057, #4581. Applied from other groups: hook-launcher F43, F44 and the node declaration; the scope wording request was not applied (see below). Skipped: biome-format request to gate the SessionStart row, already done in this PR (`hooks.json` passes `--run-if-unset-or-true GO_FORMAT_ENABLED`, with disabled, unset and `true` probe tests). The setup toggle-off step follows caveat 2 as it reads on main (`-s user`); the conventions group (#5313) owns changing it, after which the setup skills can follow. Cross-group requests: - core-docs: include go-format's setup rationale (`SKILL.md:69`) as evidence in the #3574 decision packet; optionally reword the `plugin.json` description together with `docs/catalog.md` if the owner wants the gitignore exemption named. - conventions: `scripts/sync-plugin-options-docs.py:126` emits "pass the scope `claude plugin list` reports", contradicting the reconfiguration convention's caveat 2; fix the template and regenerate every README's generated options block (go-format's generated block changes in that run). - biome-format and markdown-format carry the same probe-gate defect; their own groups own the fix. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t-ssot, write-for-agents and the changelog (#5296) Refs: #3574 Refs: #4784 Refs: #4671 Refs: #5096 Refs: #3686 Refs: #4240 Refs: #3356 Refs: #5057 Refs: #4581 ## Summary Audit fixes for `plugins/go-format` (REPORT.md finding `plugin-go-format` and the 3c row for `hooks/probe-prerequisite.sh:43-52`). Closes no issue: #3574 is owned by core-docs and waits on an owner decision. - The SessionStart prerequisite probe ran even with `go_format_enabled=false`, so the disabled plugin still printed a `goimports was not found` notice. - README, setup skill, hook header comments and evals still described the hook as unconditional, which predates the gitignore exemption (#4784). - The setup skill's toggle-off step carried stale scope advice that contradicts the reconfiguration convention. ## Fix - `hooks/hooks.json`: the SessionStart row passes `--run-if-unset-or-true GO_FORMAT_ENABLED` to the launcher, the same shape as `typos-format`. `probe-prerequisite.sh`, `hook-utils.sh` and `exec-bash.mjs` are untouched (the first two are byte-pinned to the shared copy). - `hooks/go-format.test.sh`: hook-wiring selectors match the new args; new behavioral cases assert no notice with the switch off and the notice with it unset or `true`. - `README.md`, `skills/setup/SKILL.md`, `hooks/go-format.sh` and `go-format.test.sh` header comments: "no consumer-config opt-in gate" replaces "unconditional"; the gitignored-file skip and `go_format_lint_gitignored` are documented; the setup `check` action reports the option's effective value. - `skills/setup/SKILL.md` toggle-off: prints the convention's short form (`-s user`, never uninstall to reconfigure, next-session observation, read output not exit code) and cites the convention. - `skills/setup/evals/evals.json`: new eval for the gitignore option; eval 5 aligned with the short form. - `plugin.json` 0.4.5 to 0.4.6 with a CHANGELOG entry. The `plugin.json` description ("Runs unconditionally (no consumer-config gate)") stays accurate; changing it would force a `docs/catalog.md` regeneration outside this change's scope. - Cross-group requests applied: the setup toggle-off step keeps `-s user` per the convention on main, and the setup `check` action keeps `node` a FAIL behind the kill switch. README Requirements and the setup `check` action declare Node.js (hook-launcher request). CHANGELOG entries 0.3.62, 0.3.63, 0.4.2 and 0.4.3 read "Shared launcher/library sync; no change to this plugin's behavior" and 0.4.1 drops the shell-form sentence; these released-entry edits are declared in the 0.4.6 entry and are not folded or renumbered. ## Verification - `bash plugins/go-format/hooks/go-format.test.sh`: PASS=66 FAIL=0 - `bash scripts/validate-plugins.sh`: all manifests and catalog validated - `bash scripts/check-changelog-parity.sh --check --check-order`: pass - `bash scripts/check-prerequisite-probes.test.sh`, `check-hook-exec-form.sh`, `check-hook-userconfig-argv.sh`, `check-hook-wiring-liveness.sh`, `check-killswitch-hoist.sh`, `check-cross-plugin-source-drift.sh`, `check-hooks-description.sh`, `check-purged-em-dashes.sh`: exit 0 - `bash scripts/check-changed-skills.sh origin/main`: setup skill PASS, 0 errors - `python3 scripts/sync-plugin-options-docs.py --check`, `node scripts/generate-catalog.mjs --check`: exit 0 ## Related Audit findings: `plugin-go-format` (correctness, docs-coherence, convention); 3c row `probe-prerequisite.sh:43-52`; 3d finding #3574 (owned by core-docs, not changed here). Related issues: #4784, #4671, #5096, #3686, #4240, #3356, #5057, #4581. Applied from other groups: hook-launcher F43, F44 and the node declaration; the scope wording request was not applied (see below). Skipped: biome-format request to gate the SessionStart row, already done in this PR (`hooks.json` passes `--run-if-unset-or-true GO_FORMAT_ENABLED`, with disabled, unset and `true` probe tests). The setup toggle-off step follows caveat 2 as it reads on main (`-s user`); the conventions group (#5313) owns changing it, after which the setup skills can follow. Cross-group requests: - core-docs: include go-format's setup rationale (`SKILL.md:69`) as evidence in the #3574 decision packet; optionally reword the `plugin.json` description together with `docs/catalog.md` if the owner wants the gitignore exemption named. - conventions: `scripts/sync-plugin-options-docs.py:126` emits "pass the scope `claude plugin list` reports", contradicting the reconfiguration convention's caveat 2; fix the template and regenerate every README's generated options block (go-format's generated block changes in that run). - biome-format and markdown-format carry the same probe-gate defect; their own groups own the fix. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… and correct notice docs (#5275) Closes #4265 Refs #4240 Refs #5096 ## Summary Audit fixes for the `markdown-format` plugin (0.11.79). The SessionStart prerequisite probe ignored the `markdown_format_enabled` kill switch, the missing-`markdownlint-cli2` notice and the README described a once-per-session latch that the code no longer has, no test covered the 8-fire renewal sequence, the setup skill told the reader to copy a scope from `claude plugin list`, and the check skill relied on a pre-computed `jq` row that never runs under it. ## Fix - `hooks/hooks.json`: the SessionStart row passes `--run-if-unset-or-true MARKDOWN_FORMAT_ENABLED` to the launcher, the same shape `typos-format` uses. `probe-prerequisite.sh` and `exec-bash.mjs` are untouched. - `hooks/markdown-format.sh`: the notice says it is shown on the first skip and renewed every eighth (`there is no skip latch` kept); comments corrected, including that `rewrite-guard.sh` is sourced only for the gitignore helper. - `hooks/markdown-format.test.sh`: new `SessionStart probe` section (row args, kill switch silences the probe, notice when unset) and an 8-fire renewal test. - `README.md`: notice paragraphs split by class, the session-start probe and `/markdown-format:check` documented, and why `jq` is absent from `prerequisites.json`. The probe's lack of a markdownlint config check is stated factually; no owner decision is taken. - `skills/setup`: the reconfiguration command passes `-s user` and cites the plugin-reconfiguration convention, which says the same, instead of telling the reader to copy a scope from `claude plugin list`; notice wording corrected; a Node.js row added to `check`; evals updated. - `skills/check`: runs its own `jq` probe via Bash; eval 4 added, eval 3 extended. - `README.md`: Requirements declare Node.js on `PATH` (every hook row launches through `hooks/exec-bash.mjs`); the hook budget and cost figures are annotated as predating the launcher and the SessionStart probe, with the probe's k stated (1, not measured). - `CHANGELOG.md`: 0.11.66 and 0.11.67 gain their `### Fixed`/`### Changed` headings; 0.11.74 no longer says the hook rows are unchanged. - Version 0.11.79 with a CHANGELOG entry. ## Verification - `bash plugins/markdown-format/hooks/markdown-format.test.sh`: PASS=182 FAIL=0 SKIPPED=0 - `bash scripts/check-prerequisite-probes.test.sh`: 18 cases, 0 failed - `bash scripts/check-changelog-parity.sh --check --check-order`: pass - `bash scripts/validate-plugins.sh`: all manifests and the catalog validated - `python3 scripts/sync-plugin-options-docs.py --check`: up to date - Per-task checks (hook exec form, userconfig argv, wiring liveness, kill-switch hoist, shell portability, hook-utils sync, skill precompute compose, skill portability, leaf names, eval JSON, skill-quality check and validate-evals) passed on the task commits. - `git grep docs.claude.com -- plugins/markdown-format` hits only historical CHANGELOG entries. ## Related - Audit findings: `.work/audit/REPORT.md`, issues #4265 (closed here) and #4240 (session-start probe opt-in, owner decision stays open). - Cross-group requests: - scripts: reword the `latches once per session` string in `lib/hook-utils.sh` and sync; fix the `claude plugin list` scope advice in the `sync-plugin-options-docs.py` template and regenerate READMEs; optionally lift `hook::gitignored_out_of_scope` into the shared lib. - biome-format (owner of #4240): the SessionStart probe never consults a per-repo opt-in; include markdown-format in the #4240 decision. - conventions: sweep sibling setup skills for the `claude plugin list` scope advice; give cluster-sync changelog entries a fixed line. - typos-format: reword `typos-format.sh:156` notice string. - Requests received from other groups, applied here: hook-launcher (Node.js requirement and `check` row, budget figure annotations, CHANGELOG headings and 0.11.74 wording) and conventions (the setup skill and its evals prescribe `-s user` and do not copy a scope from `claude plugin list`; this matches the convention text on main). The biome-format request (gate the SessionStart row with `--run-if-unset-or-true MARKDOWN_FORMAT_ENABLED`, add disabled and unset probe cases, leave the `no config, no run, no notice` comment and `probe-prerequisite.sh` alone until #4240 Q1 is answered) was already met by the first commits on this branch, so nothing changed for it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…aining format plugins (#5468) Closes #5286 ## Summary bash-format, ruff-format, typos-format, actionlint and powershell-format probed binaries with no manifest, so `/claude-ops:prerequisites` reported `missing=0` on a host lacking their tools. Each now declares its prerequisites, probes at SessionStart and ships a `check` skill. ## Fix - Each plugin ships `prerequisites.json`, a SessionStart probe, and `skills/check`; its hook notice names the check skill. - bash-format (`shfmt`, `shellcheck`) and ruff-format (`ruff`) move their missing-tool notices to the `prerequisite` class: once per session, shared by all agents, install route kept on renewal. The `jq` notice stays once per session and agent. - In every probed plugin whose hook has a missing-binary notice (all but powershell-format, whose hook exits quietly without `pwsh`), the SessionStart probe and the PostToolUse notice share one latch key, so the probe's notice counts as the first and the first PostToolUse notice stays silent until the renewal. actionlint's hook latched on `actionlint-missing` while its probe used `actionlint-actionlint`; the hook now uses the probe's key, and a suite case pins it. - `scripts/check-prerequisite-probes.test.sh` binds each notice text to its manifest and covers the new plugins. - `docs/formatter-path-probes.md`, the skill cheat sheet and the leaf-name registry list the new probes and skills. - claude-ops `prerequisites` Next section points at every formatter and linter check skill, `/actionlint:check` included. - The `hooks.json` description of each of the five plugins names the SessionStart probe. - ruff-format docs: the probe checks the working directory plus seven ancestors for `.venv/bin/ruff`, and say that a Windows host whose only ruff is `.venv/Scripts/ruff.exe` still gets the probe notice (the manifest holds one `local_bin` and the probe script is shared byte-for-byte by every probed plugin, so a second path is a shared-schema change left out of this PR). - powershell-format docs: a machine without `pwsh` is INFO in `check`, and the probe notice appears on it once per session while the plugin is enabled (owner decision Q1 A on #4240); the setup skill and its evals no longer call it not-applicable by design. - Versions: actionlint 0.11.0, bash-format 0.9.0, powershell-format 0.9.0, ruff-format 0.8.0, typos-format 0.8.0, claude-ops 0.71.3, each with a CHANGELOG entry. The bash-format, ruff-format, typos-format and actionlint entries record the latch change. ## Verification - Merged origin/main; the conflicts were the claude-ops and typos-format versions and CHANGELOGs (main ships claude-ops 0.71.2 and typos-format 0.7.9), resolved by re-bumping to claude-ops 0.71.3 and typos-format 0.8.0 above main's entries. - `scripts/check-changelog-parity.sh --check`, `--check-order`, `--check-bump origin/main` and `--check-preserved origin/main`: pass. - `scripts/validate-plugins.sh`: all manifests and the catalog validated. - `scripts/sync-hook-utils.sh --check`, `scripts/sync-exec-bash.sh --check`, `scripts/check-changed-skills.sh origin/main`, `scripts/generate-cheatsheet.mjs --check`, `check-evals-quality.sh` on the two edited evals files: pass. - Hook suites for actionlint (60 cases), bash-format (69), ruff-format (76), typos-format (205), powershell-format (96): 0 failed. The new actionlint case fails against the old `actionlint-missing` key. - `scripts/check-prerequisite-probes.test.sh`: 51 cases, 0 failed. It runs in CI (`ci.yml`). - `check-prerequisites.test.sh` (claude-ops): 30 cases, 0 failed. - The 0.x.5 CHANGELOG entries on main already say no probe ships (for example `plugins/bash-format/CHANGELOG.md` 0.8.5 and `plugins/ruff-format/CHANGELOG.md` 0.7.5). That correction satisfies AC4; the probes now exist. ## Related Refs #4240, #5096. PR 5377 covers playwright, biome and markdown separately. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Closes #4240
Summary
Missing external tools now surface to the main session and are reported, never installed. This follows the operator decision on #4240: a
claude-ops:prerequisitesskill backed by aprerequisites.jsonmanifest per plugin, with every probe reading that file.Fix
prerequisites.jsonat the root of biome-format, go-format, markdown-format, context7, and playwright declares each tool:name, optionallocal_bin,check, andinstall.claude-ops:prerequisites(check-prerequisites.sh) reads the manifest of each enabled plugin and prints a present/missing table. It does not install, download, or runnpx.hooks/probe-prerequisite.shin biome-format, go-format, and markdown-format is one shared script. It takes every tool name,local_bin, check command, and install line from its plugin'sprerequisites.json; no binary name or install text is hardcoded.hook::notice_oncetakes an optionalprerequisiteclass: the notice latches once per session instead of per agent, and a renewal keeps the install route. Callers that omit the class, including every guardrails, context-guard, and rate-limit-guard hook, behave exactly as before. The sharedlib/hook-utils.shis synced to all 17 copies.checkskills for the three format plugins are read-only and never runapply.Verification
scripts/check-prerequisite-probes.test.sh(new, 18 cases). It fails when a probe differs from the shared manifest reader, contains an install command, omits a declared tool's name, check, or install text from its notice while the tool is missing, or prints anything when every declared tool is present.check-prerequisites.test.sh6/0,lib/hook-utils.test.sh582/0,sync-hook-utils.sh --check, go-format 63/0, biome-format 54/0.run-guards.test.sh(309/2) fail the same two cases each on a cleanorigin/maincheckout on this machine, so those failures are not from this diff.hook-utils.shnotice path. No guard hook passes theprerequisiteclass, so their allow and deny decisions are unchanged from main.validate-plugins.sh,check-changelog-parity.sh --check --check-order,check-changed-skills.sh origin/main,validate-plugin-contracts.mjs, catalog and cheat-sheet--check, skill-count claims, skill leaf names, purged em dashes, and shellcheck all pass.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01WejvGhkHUSWPRim2caW2Wh