Skip to content

feat: adopt the uniform setup contract across 9 formatter/CLI plugins - #355

Merged
kyle-sexton merged 19 commits into
mainfrom
feat/setup-contract-tranche-a
Jul 19, 2026
Merged

feat: adopt the uniform setup contract across 9 formatter/CLI plugins#355
kyle-sexton merged 19 commits into
mainfrom
feat/setup-contract-tranche-a

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Tranche 2 of wave #314 (epic #313, dim 8): the battle-tested markdown-format exemplar from #342 (six adversarial review rounds), cloned to the nine collision-free shape-A plugins.

Plugin Version apply write path
actionlint 0.4.0 none — guidance only
bash-format 0.5.0 none — guidance only
powershell-format 0.4.0 none — guidance only (module install is user-scope guidance)
eol-normalizer 0.4.0 none — guidance only
desktop-notification 0.4.0 none — probes only the current OS family's channel deps
biome-format 0.4.0 apply install-biome — repo package manager (lockfile → packageManager → npm; Plug'n'Play → guidance)
ruff-format 0.4.0 apply install-ruff — only into a managed env the repo already uses; never creates one
firecrawl 0.3.0 none — defers to the plugin's lazy-install design; reports FIRECRAWL_API_KEY presence without printing it
playwright 0.3.0 apply install-cli — stated-before-running global npm install

Contract invariants everywhere: check reads the plugin's own hook/skill source as single source of truth and probes what it actually does (no hand-copied lists to drift); apply re-checks first, names every write path in the argument-hint, states it before running, re-verifies after every remediation; never writes the plugin cache, user settings, or pluginConfigs; non-interactive when the action is supplied; disable-model-invocation: true.

Also backfills the undocumented [0.3.1] CHANGELOG entries in actionlint and powershell-format (#298's hook-utils resync, verified via git log -S).

Deferred for lane ownership (per the org WIP survey): disk-hygiene (PR #286 touches its plugin.json/CHANGELOG) and guardrails (PR #305 ditto) — they join a later tranche after those PRs land.

Verification

  • validate-plugins.sh, validate-plugin-contracts.mjs (28 setup skills, 1513 files), markdownlint (55 files), typos: all green locally.

Related

No linked issue: tranche 2 of #314 — the issue closes with the wave's final tranche.

🤖 Generated with Claude Code

Tranche 2 of wave #314 (epic #313, dim 8), cloning the battle-tested
markdown-format exemplar from #342 to the collision-free shape-A
plugins: actionlint 0.4.0, bash-format 0.5.0, powershell-format 0.4.0,
biome-format 0.4.0, ruff-format 0.4.0, eol-normalizer 0.4.0,
desktop-notification 0.4.0, firecrawl 0.3.0, playwright 0.3.0.

Every setup: check reads the plugin's own hook/skill source as the
single source of truth and probes what it actually requires (no
hand-copied resolution paths or config lists); apply re-checks first,
resolves with guidance for system tools and native toggles, names any
write path in the argument-hint, states it before running, and
re-verifies after every remediation. Package-manager and environment
respect carried over from the exemplar's review rounds: biome-format
resolves lockfile -> packageManager -> npm and routes Plug'n'Play to
guidance; ruff-format installs only into a managed environment the
repo already uses; firecrawl reports FIRECRAWL_API_KEY presence
without ever printing it and defers to the plugin's lazy-install
design; desktop-notification probes only the current OS family's
channel dependencies.

Also backfills the undocumented [0.3.1] CHANGELOG entries in
actionlint and powershell-format (the #298 hook-utils resync, verified
via git log -S).

Deferred from this tranche for lane ownership: disk-hygiene (PR #286
touches its plugin.json/CHANGELOG) and guardrails (PR #305 ditto) —
they join a later tranche after those PRs land.

## Related

- Part of #314
- Part of #313

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton enabled auto-merge (squash) July 18, 2026 21:05
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 54s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read all 9 new SKILL.md files
  • Verify plugin.json version bumps
  • Check contract invariants (check/apply semantics, disable-model-invocation, no forbidden writes)
  • Security review (credential exposure, command injection, unintended writes)
  • Post findings

Overall

This is a well-executed, low-risk expansion of an established pattern. The nine new skills are structurally consistent with each other and with the stated contract. The following findings are ordered by severity.


Findings

Medium — biome-format: Yarn Classic detection is implicit

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 56–67

The Yarn linker disambiguation logic is:

  1. Detect yarn.lock → treat as Yarn repo
  2. Run yarn config get nodeLinker
  3. pnp → skip install (PnP shim incompatible with the hook's node_modules/.bin walk)
  4. node-modules/pnpm, or Yarn Classic → install

The gap: Yarn Classic (v1.x) doesn't recognise nodeLinker as a config key. Running yarn config get nodeLinker on a v1 repo may return undefined, an empty string, or an error — none of which are the named case values node-modules or pnpm. The skill says "Yarn Classic (which has no such setting…)" but doesn't say how to detect it, so a model following this instruction literally won't know when it's looking at a Classic repo vs an unset Berry setting (which is also pnp by Berry default, correctly caught).

Suggested clarification: after yarn config get nodeLinker, treat any return value other than pnp (including empty/error from Yarn Classic) as the node_modules path and proceed with the install — or explicitly note "check yarn --version for 1.x to identify Classic before running nodeLinker." Either way, the current text leaves a model-execution ambiguity.

Fix this →


Low — ruff-format: uv detection heuristic unspecified

File: plugins/ruff-format/skills/setup/SKILL.md
Line: 59

install into it with the repo's own tooling: uv pip install ruff when the repo uses uv, otherwise .venv's own pip install ruff

"When the repo uses uv" has no detection heuristic here (presence of uv.lock? [tool.uv] in pyproject.toml? command -v uv?). The "Read [the hook] first" mandate means a model will derive this from the hook source, so it won't drift catastrophically — but it makes this section of the skill text inconsistently specified compared to the rest.


Low — firecrawl: firecrawl --status is not fully read-only

File: plugins/firecrawl/skills/setup/SKILL.md
Line: 35

When present, report the version (firecrawl --version) and the auth line from firecrawl --status

firecrawl --status is described in the check (read-only) step but may make a network call to validate auth. This is probably acceptable for a CLI probe, but the check section's "Do not modify anything" framing could be tightened to note that --status is a read-only probe with the side-effect caveat acknowledged.


Contract invariants — all pass

Invariant Status
disable-model-invocation: true on all 9
check is read-only (only command -v and file presence probes)
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
Write stated before execution
Re-verify after remediation (not on exit code alone)
Never writes plugin cache, user settings, or pluginConfigs
Never writes repository files in guidance-only plugins
${CLAUDE_PLUGIN_ROOT} used for all plugin-relative paths
Hook/skill source designated as single source of truth; skills say "Read it first"

Security observations — all clear

  • FIRECRAWL_API_KEY: only checked for presence ([[ -n "${FIRECRAWL_API_KEY:-}" ]]); value is never printed, logged, or persisted. Enforced in the check step and the "does NOT" section. ✅
  • Optional firecrawl env vars (FIRECRAWL_API_URL, FIRECRAWL_NO_TELEMETRY) also presence-only. ✅
  • powershell-format trust warning for PSScriptAnalyzerSettings.psd1 (a CustomRulePath it declares runs during analysis) is surfaced correctly in the check step. ✅
  • playwright global install is clearly labelled as "mutates the user's machine (the global npm prefix)" and gated behind the explicit apply install-cli argument. ✅
  • No ../ reach-outs; all plugin-local paths use ${CLAUDE_PLUGIN_ROOT}. ✅
  • No hardcoded repo paths or project-specific values. ✅

Version consistency — all pass

Plugin Version in plugin.json PR table
actionlint 0.4.0 0.4.0
bash-format 0.5.0 0.5.0
biome-format 0.4.0 0.4.0
desktop-notification (not re-read, but CHANGELOG matches) 0.4.0
eol-normalizer (not re-read, but CHANGELOG matches) 0.4.0
firecrawl 0.3.0 0.3.0
playwright 0.3.0 0.3.0
powershell-format (CHANGELOG matches) 0.4.0
ruff-format 0.4.0 0.4.0

All bumps are minor semver additions (new skill), consistent with Keep-a-Changelog ### Added entries. bash-format's jump to 0.5.0 (skipping 0.4.1 in the PR table) is explained by the pre-existing [0.4.1] backfill entry in its changelog. ✅

CHANGELOG backfills

The two undocumented [0.3.1] entries (actionlint, powershell-format) are correctly labelled "Changed — Shared hook-utils.sh resynced" with "no behavior change" notes, consistent with a resync of library code. ✅


Summary: Three low-to-medium observations, all in the skill instruction text rather than in security or structural correctness. The Yarn Classic detection gap in biome-format is the one worth addressing before merge; the other two are clarifications. No blocking issues.

@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 5m 2s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read all 9 new SKILL.md files
  • Verify plugin.json version bumps
  • Check contract invariants (check/apply semantics, disable-model-invocation, no forbidden writes)
  • Security review (credential exposure, command injection, unintended writes)
  • Post findings

Summary

High-quality tranche. All 9 SKILL.md files conform to the uniform contract, version bumps match the PR table, and the three write-path skills (biome install-biome, ruff install-ruff, playwright install-cli) are properly gated. Two findings below — one consistency gap and one edge case.


Findings

1. CHANGELOG version gap in biome-format, ruff-format, and eol-normalizer (medium — consistency)

The PR explicitly backfills undocumented [0.3.1] entries for actionlint and powershell-format, but three other plugins in this same tranche have the same gap and don't receive the backfill:

Plugin plugin.json before CHANGELOG jumps
biome-format 0.3.1 0.3.0 → 0.4.0 (0.3.1 absent)
ruff-format 0.3.1 0.3.0 → 0.4.0 (0.3.1 absent)
eol-normalizer 0.3.1 0.3.0 → 0.4.0 (0.3.1 absent)

git log -S "hook-utils" on these three paths shows commit a961cdc (PR #328 "make missing hook prerequisites skip visibly") as the likely culprit — so the 0.3.1 bump is from a different PR than #298, which may be why it wasn't caught by the git log -S check cited in the PR description. If intentionally deferred, a note in the PR body would clarify; if not, these three need the same backfill treatment. Fix this →

2. Biome apply install-biome — Yarn Berry nodeLinker unset case (low — edge case)

biome-format/skills/setup/SKILL.md L62:

pnp (Berry's default when unset) → skip the install and give guidance

In Yarn Berry, yarn config get nodeLinker returns undefined (the literal string or exit-1) when the key is not explicitly set — not pnp. A freshly created Berry monorepo with no explicit nodeLinker in .yarnrc.yml will produce undefined here, but the effective linker IS PnP and an install into node_modules would fail to produce the .bin shim the hook resolves. The post-install binary re-probe is the backstop (correctly present), but the detection would misclassify these repos as "safe to install" and would only catch the problem after running the install. A tighter guard would match undefined alongside pnp as the skip-and-guide case.


Contract conformance ✓

All 9 skills pass every invariant:

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite the SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after every remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument is supplied

Security highlights ✓

  • Firecrawl credential protection is thorough: FIRECRAWL_API_KEY tested with [[ -n "${FIRECRAWL_API_KEY:-}" ]], result reported as "set/unset" only, with an explicit "NEVER print, echo, log, or persist the value" prohibition and the same constraint applied to the firecrawl --status re-check. Optional env vars (FIRECRAWL_API_URL, FIRECRAWL_NO_TELEMETRY) also presence-only. The three-state PASS/INFO/FAIL logic correctly handles the lazy-install model.

  • Playwright global install is the only machine-global write across all 9 skills (npm install -g @playwright/cli). It's correctly gated behind apply install-cli, explicitly labelled "global install that mutates the user's machine", stated before running, and re-probed afterward.

  • PSScriptAnalyzer trust callout in powershell-format correctly surfaces that CustomRulePath in a settings file executes during analysis on every edit — same trust level as build/CI config — and the check step's Get-Module -ListAvailable probe is correctly read-only (no format/lint/mutate side effects).

  • Ruff venv install never creates a virtual environment and refuses ambiguous states, matching the hook's own resolution path.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c799558d17

ℹ️ 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".

Comment thread plugins/eol-normalizer/skills/setup/SKILL.md Outdated
auto-merge was automatically disabled July 18, 2026 21:07

Repository rule violations found

… list

Codex on #355: git check-attr answers for any candidate path and the
hook normalizes untracked and brand-new files the same as tracked
ones (verified: no tracked-only restriction in the hook source), so
the policy probe no longer scopes itself to tracked paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 11s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (eol-normalizer candidate-path fix)
  • Verify open findings from prior reviews
  • Check CHANGELOG gaps (biome-format, ruff-format, eol-normalizer)
  • Verify Yarn Classic/Berry nodeLinker detection in biome-format
  • Post findings

What the latest commit fixed

The pushed commit (3be5adc) correctly addresses the Codex finding: the eol-normalizer check step now says "probe representative candidate paths (or report the declared patterns), never a tracked-files listing that would miss untracked matches" (SKILL.md line 44–48). This matches how the hook actually behaves — git check-attr runs on any candidate path, including a first write to an untracked file. ✅


Remaining findings

Medium — biome-format: pnp parenthetical is incorrect for Yarn Berry with unset nodeLinker

File: plugins/biome-format/skills/setup/SKILL.md
Line: 63

The skill says:

pnp (Berry's default when unset) → skip the install and give guidance

The parenthetical is factually incorrect. When nodeLinker is not set in .yarnrc.yml, running yarn config get nodeLinker on a Yarn Berry project returns undefined (literal string or exit-1) — not pnp. Berry's effective default is PnP, but the command does not output pnp for an unset key.

A model following this instruction literally will not match the pnp guard for a freshly created Berry project with no explicit nodeLinker. The undefined output also doesn't match node-modules or pnpm, so the model would either:

  • Fall into the "ambiguous / stop with guidance" path (benign, but not what the parenthetical implies), or
  • Infer the Yarn Classic match ("has no such setting") and attempt to install into a PnP environment — the post-install re-probe is the backstop, but a partial node_modules install would be created.

The unambiguous fix is to distinguish Classic from Berry before reading nodeLinker:

1. Check `yarn --version`:
   - 1.x → Yarn Classic → materializes node_modules → proceed with yarn add -D
   - 2+ → Yarn Berry → run `yarn config get nodeLinker`:
     - `pnp`, `undefined`, or empty (unset) → skip and give guidance (effective PnP)
     - `node-modules` or `pnpm` → proceed with yarn add -D

Alternatively: treat any nodeLinker value other than node-modules/pnpm (including undefined) as the skip case and reserve the Classic detection path for a yarn --version 1.x guard.

Fix this →


Medium — biome-format, ruff-format, eol-normalizer: Missing [0.3.1] CHANGELOG entries

These three plugins were bumped from 0.3.0 to 0.3.1 in commit 2bf1dd9 (PR #298 "feat(guardrails): add block-dangerous-git guard") as a hook-utils.sh resync. Their plugin.json on main reads 0.3.1, but none of their CHANGELOGs document the [0.3.1] release — they jump directly from [0.3.0] to [0.4.0].

This PR already backfills undocumented [0.3.1] entries for actionlint and powershell-format using the same git log -S rationale. The three plugins below have the identical gap:

Plugin plugin.json on main CHANGELOG gap
biome-format 0.3.1 [0.3.0][0.4.0], no [0.3.1]
ruff-format 0.3.1 [0.3.0][0.4.0], no [0.3.1]
eol-normalizer 0.3.1 [0.3.0][0.4.0], no [0.3.1]

The bump in PR #298 was purely a hook-utils.sh library resync (the same reason cited in the actionlint/powershell-format backfills) with no behavior change in any of the three plugins' own hooks. The same backfill text applies: "Changed — Shared hook-utils.sh resynced (lib sync only; no behavior change in this plugin's hook)."

Fix this →


Low — ruff-format: uv detection heuristic unspecified in apply install-ruff

File: plugins/ruff-format/skills/setup/SKILL.md
Line: 59–60

install into it with the repo's own tooling: uv pip install ruff when the repo uses uv, otherwise .venv's own pip install ruff

"When the repo uses uv" has no detection heuristic in the skill text (presence of uv.lock? [tool.uv] in pyproject.toml? command -v uv && uv venv --help?). The "Read the hook first" mandate means a model will derive this from the hook source, so drift is unlikely — but it is inconsistent with the explicit specification given for every other detection heuristic in the same file.


Low — firecrawl: firecrawl --status may make a network call in the check phase

File: plugins/firecrawl/skills/setup/SKILL.md
Line: 35

firecrawl --status is invoked in the check (read-only) step. Depending on the CLI implementation, --status may make a network call to validate the API key. The check section's framing is "Do not modify anything" — a network probe arguably falls within that intent, but the caveat is worth acknowledging explicitly: "note: --status is a read-only network probe; it does not modify any state."


Contract invariants — all pass

Invariant Status
disable-model-invocation: true on all 9
check is read-only (probes only)
apply re-runs check before acting
Write paths named in argument-hint
States change before executing
Re-verifies after remediation (not exit-code only)
Never writes plugin cache, user settings, or pluginConfigs
Hook/skill source is designated single source of truth

Security — all clear

Item Status
FIRECRAWL_API_KEY presence-only, never printed
Optional firecrawl env vars also presence-only
powershell-format PSScriptAnalyzer CustomRulePath trust callout
playwright global install gated behind explicit apply install-cli arg
No ../ reach-outs; all plugin paths use ${CLAUDE_PLUGIN_ROOT}
eol-normalizer candidate-path probe (latest commit)

Summary

Two medium items to address before merge: the pnp parenthetical in biome-format's Yarn detection (factually incorrect — an unset Berry nodeLinker returns undefined, not pnp) and the three missing [0.3.1] CHANGELOG entries (same backfill the PR already applies to actionlint/powershell-format). The two low items are clarifications. No blocking security or structural issues.

…t, eol-normalizer)

The #298 hook-utils resync bumped these three to 0.3.1 without a
changelog entry (verified via git log -S on main); same backfill as
actionlint and powershell-format in this tranche.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 58s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit changes (eol-normalizer fix + CHANGELOG backfills)
  • Check open findings from prior reviews (Yarn Classic, ruff uv heuristic, firecrawl --status)
  • Read biome-format SKILL.md for Yarn Classic fix status
  • Read ruff-format, firecrawl SKILL.md for remaining findings
  • Verify CHANGELOG backfills (biome-format, ruff-format, eol-normalizer)
  • Post findings

Fixes landed since the previous reviews

Two findings from the two prior round-trips have been closed:

eol-normalizer tracked-path probe (3be5adc) — the skill now says "probe representative candidate paths (or report the declared patterns), never a tracked-files listing that would miss untracked matches." This matches the Codex finding exactly. L43–49

CHANGELOG [0.3.1] backfills (45f4c66) — biome-format, ruff-format, and eol-normalizer now each have a [0.3.1] section between [0.4.0] and [0.3.0] with the hook-utils resync note. ✅


Remaining finding

Medium — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67

Both prior reviews independently flagged this; the text hasn't changed since c799558.

The current text is:

pnp (Berry's default when unset) → skip the install and give guidance … node-modules/pnpm, or Yarn Classic (which has no such setting and always materializes node_modules) → install.

The problem: yarn config get nodeLinker does not return pnp when the key is unset in Yarn Berry — it returns the literal string undefined. And Yarn Classic (v1.x) returns a non-zero exit or an error because it doesn't recognise nodeLinker. Both cases produce output that does not match the literal backtick-string pnp, so a model following these conditions literally would fall through to the install branch in both cases — which is correct for Classic but wrong for an unset Berry project (where PnP IS the active linker and an install into node_modules silently fails to produce the .bin shim).

The parenthetical "(Berry's default when unset)" tries to patch this, but it doesn't tell the model what actual command output to expect for the "unset" case. Similarly "(which has no such setting…)" describes the Classic situation conceptually without giving the model an execution path to distinguish it from an unset Berry.

The minimal fix is to add the disambiguation: check yarn --version first; a 1.x version means Classic (always node_modules → install), a 2.x+ version means Berry (then run nodeLinker; treat undefined or empty the same as pnp → skip). The post-install binary re-probe is the backstop but catching this before the install is cleaner.

Fix this →


Low-severity observations (not blocking)

ruff-format: uv detection heuristic unspecifiedSKILL.md L59–61 says uv pip install ruff "when the repo uses uv" with no detection heuristic. The "read the hook first" mandate is the backstop, so this won't drift badly — worth a follow-up but not blocking.

firecrawl: --status may make a network callSKILL.md L34–35 calls firecrawl --status in the check (read-only) step. This is a standard CLI status probe; the framing could note the potential network round-trip, but it's a weak finding and not blocking.


Contract conformance — all 9 pass

All invariants confirmed across all nine SKILL.md files:

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code alone)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), never printed — ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled — ✅
  • powershell-format trust callout for CustomRulePath in PSScriptAnalyzerSettings.psd1 surfaced in check — ✅
  • PSInstall-Module PSScriptAnalyzer correctly framed as user-scope guidance (stated for reader to run, never executed by the skill) — ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout — ✅

Summary: Two prior findings are closed (eol-normalizer probe scope, CHANGELOG backfills). One medium issue remains in biome-format: the Yarn Berry nodeLinker-unset vs Yarn Classic disambiguation needs a yarn --version gate before the nodeLinker check. The two low-severity observations (ruff uv heuristic, firecrawl status network call) are acceptable gaps. Everything else is clean.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 45f4c6618f

ℹ️ 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".

Comment thread plugins/firecrawl/skills/setup/SKILL.md
…esh session

Codex on #355: setx and profile edits do not reach the running
process, so the immediate re-check would report a false failure. The
env-var remediation now states the new-session requirement and defers
its verification to a fresh-session check instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 27s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (firecrawl env-var remediation fix)
  • Check open findings from prior reviews
  • Post findings

Fixes landed since the previous review

firecrawl setx new-session requirement (1ba8a1e) — the env-var remediation now tells the user that persistent env changes (setx, profile edits) do not reach the already-running session, and defers verification to a fresh-session setup check. The immediate re-check false-failure is gone. L60–70


Remaining finding

Medium — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (4th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–69

This finding has been independently raised by two reviewers across three prior rounds (rounds 1–3 of this PR) and has not changed since commit c799558. The current text:

pnp (Berry's default when unset) → skip the install and give guidance … node-modules/pnpm, or Yarn Classic (which has no such setting and always materializes node_modules) → install.

The problem in two parts:

  1. yarn config get nodeLinker does not return pnp when unset. On a Yarn Berry project where .yarnrc.yml has no nodeLinker key, the command outputs the literal string undefined (or exits non-zero). A model matching on the backtick-string pnp will not match undefined and will fall through to the install branch — which is the wrong outcome for an unset Berry project (where PnP is the effective linker).

  2. Yarn Classic exits non-zero for nodeLinker. Classic v1.x doesn't recognise nodeLinker as a config key; it returns a non-zero exit or an error string. The parenthetical "(which has no such setting…)" describes this conceptually but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output, one should install and one should not.

The unambiguous fix is a yarn --version gate before reading nodeLinker:

check yarn --version:
  1.x → Yarn Classic → always materialises node_modules → proceed with yarn add -D
  2.x+ → Yarn Berry → run yarn config get nodeLinker:
    pnp, undefined, or empty → skip and give guidance (effective PnP)
    node-modules or pnpm   → proceed with yarn add -D

Fix this →


Low-severity observations (not blocking)

ruff-format: uv detection heuristic unspecifiedSKILL.md L59–61: uv pip install ruff "when the repo uses uv" has no detection heuristic (presence of uv.lock? [tool.uv] in pyproject.toml?). The "read the hook first" mandate limits drift, but the section is inconsistently specified relative to every other heuristic in the file. Not blocking.

firecrawl: --status may make a network call in the check phaseSKILL.md L34–35: firecrawl --status is invoked in the read-only check step; depending on the CLI implementation it may make a network round-trip. The framing could acknowledge "read-only network probe; no state modified", but this is a weak finding. Not blocking.


Contract invariants — all pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: One medium finding remains in biome-format (Yarn Berry nodeLinker-unset vs Yarn Classic disambiguation — the yarn --version gate). This has now been raised four times across two independent reviewers without landing a fix. The firecrawl setx new-session fix (1ba8a1e) and all prior fixes are clean. Everything else is conformant.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ba8a1e68d

ℹ️ 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".

Comment thread plugins/firecrawl/skills/setup/SKILL.md Outdated
Codex on #355: firecrawl login/config state authenticates without any
env var, so env-unset with CLI present is not a failure when
firecrawl --status reports authenticated. The status line is now the
verdict; env-var presence is reported alongside, with an INFO note
when auth comes from persisted CLI config — never directing the user
to stack an env key on top of working CLI-config auth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 39s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (firecrawl CLI auth verdict fix)
  • Verify remaining finding: biome-format Yarn Classic/Berry disambiguation (still open)
  • Draft and commit fix locally; push blocked (no write permission to repo)
  • Post findings

Fix landed in this round

firecrawl: CLI --status auth line is the authoritative verdict (a5ce3aa) — the latest commit fully addresses the Codex finding. The check step now treats firecrawl --status as the authentication verdict (PASS when authenticated, regardless of whether auth comes from env-var or persisted CLI config), reports FIRECRAWL_API_KEY as an informational alongside, and explicitly notes when env-var and CLI-config auth coexist without directing the user to add a redundant key. The apply step correctly defers the re-check for setx/profile changes to a fresh session (carries over 1ba8a1e). ✅


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (5th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–69 (unchanged since c799558)

The text is still:

pnp (Berry's default when unset) → skip … node-modules/pnpm, or Yarn Classic (which has no such setting and always materializes node_modules) → install.

The parenthetical is factually incorrect: yarn config get nodeLinker returns the literal string undefined (not pnp) when nodeLinker is absent from .yarnrc.yml on Yarn Berry. And Yarn Classic v1.x doesn't recognise nodeLinker as a key — it exits non-zero. Neither returns the string pnp, so a model matching literally on that string would misclassify both cases and fall through to the install branch. For Classic that's correct; for an unset Berry project (whose effective linker is PnP) it's wrong.

This is the exact patch that should be applied (I committed it locally but cannot push):

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Fix this →


Low-severity observations (not blocking — carried forward, unchanged)

ruff-format: uv detection heuristic unspecifiedSKILL.md L59–61: uv pip install ruff "when the repo uses uv" has no detection heuristic (presence of uv.lock? [tool.uv] in pyproject.toml?). The "read the hook first" mandate limits drift; not blocking.

firecrawl: --status may make a network call in the check phaseSKILL.md L34–35: firecrawl --status is invoked in the read-only check step; depending on the CLI implementation it may make a network round-trip. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: One fix landed (a5ce3aa — firecrawl auth verdict). One medium finding remains in biome-format (Yarn --version gate before nodeLinker, now 5 rounds). The exact patch is included above. Everything else is conformant and ready to merge once that line is corrected.

@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 52s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read current state of biome-format/skills/setup/SKILL.md
  • Confirmed: Yarn Classic/Berry disambiguation fix not yet applied
  • Applied fix locally (push blocked — see below)
  • Final review posted

Fix applied locally — push blocked

I committed the Yarn disambiguation fix locally but the github-actions[bot] account does not have write access to this branch. The exact patch to apply is below.


Remaining medium finding — biome-format: Yarn detection (6th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Fix this →


Low-severity observations (not blocking — unchanged from prior rounds)

ruff-format: uv detection heuristic unspecifiedSKILL.md L59–61: uv pip install ruff "when the repo uses uv" has no detection heuristic. The "read the hook first" mandate limits drift; not blocking.

firecrawl: --status may make a network call in checkSKILL.md L34–35: firecrawl --status in the read-only check step may make a network round-trip. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: The Yarn --version gate fix (medium, 6 rounds) is written above as an exact diff — apply it to close the last open finding. Push access is unavailable to this bot account. Everything else is conformant and ready to merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6368269012

ℹ️ 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".

Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
kyle-sexton and others added 2 commits July 18, 2026 19:00
Codex on #355: a bare install into a uv- or Poetry-managed .venv
bypasses the manifest/lockfile, so uv sync or environment recreation
silently removes Ruff and the hook returns to its skip state. Managed
projects now get the project's own dependency command (uv add --dev /
poetry add --group dev); the direct pip install path is reserved for a
plain .venv with no managing tool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 7s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read current state of biome-format/skills/setup/SKILL.md (Yarn fix — still open)
  • Read ruff-format/skills/setup/SKILL.md (managed dependency state fix from 424c3fb)
  • Verify all prior findings status
  • Apply biome-format Yarn fix locally (push blocked — patch below)
  • Post findings

Fixes landed since the previous review

ruff-format: managed dependency state (424c3fb) — apply install-ruff now routes through the project's own dependency command for uv- and Poetry-managed repos (uv add --dev ruff / poetry add --group dev ruff), reserving the bare .venv pip install for a plain virtual environment with no managing tool. A uv sync or environment recreation will no longer silently drop Ruff after a successful setup. ✅

ruff-format: uv detection heuristic (carried from low-severity list) — the same 424c3fb commit closes this: detection is now explicitly specified as presence of uv.lock, poetry.lock, or the matching pyproject.toml tool section — no longer "when the repo uses uv" without criteria. ✅


Remaining finding

Medium — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (7th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

I committed the fix locally but the github-actions[bot] account does not have write access to this branch. The exact patch to apply is:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in checkSKILL.md L34–35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. The framing could acknowledge "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment or installs globally ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: Two findings closed this round (424c3fb): ruff-format's managed dependency state and the uv detection heuristic. One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 7 rounds). The exact patch is above. Push access is not available to this bot account.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aab8607af5

ℹ️ 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".

Comment thread plugins/firecrawl/skills/setup/SKILL.md Outdated
Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
Codex on #355: (1) firecrawl setup gains a remediation for the
key-set-but-unauthenticated state (replace the key without handling
the old value, then re-run --status) so apply can resolve its own
finding; (2) ruff-format's Poetry path first confirms an in-project
environment — Poetry defaults to a cache-dir virtualenv the hook never
resolves (hook resolves repo-ancestor .venv or PATH only), so without
one the skill guides (virtualenvs.in-project true + recreate, or PATH)
instead of running an install that leaves the check failing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 16s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (7efba13) — firecrawl invalid-key remediation + ruff Poetry in-project gate ✅
  • Verify biome-format Yarn Classic/Berry disambiguation (still open after 7 rounds)
  • Apply biome-format Yarn fix locally (push blocked — patch below)
  • Post findings

Fixes confirmed in 7efba13

firecrawl: key-set-but-unauthenticated remediation — The skill now has a distinct third state: when firecrawl --status reports unauthenticated while FIRECRAWL_API_KEY is set (expired/revoked/malformed key), apply directs the user to mint a fresh key and replace the stored value, then re-run firecrawl --status (same-session works for an exported replacement; a persistent-only change follows the fresh-session rule). The previous gap where apply had no remediation for this state is closed. ✅

ruff-format: Poetry in-project gateapply install-ruff now confirms an in-project Poetry environment (poetry config virtualenvs.in-project effective true, or a repo .venv Poetry manages) before running poetry add --group dev ruff. Without one, it guides instead: enable virtualenvs.in-project true, recreate the environment, or put Ruff on PATH. Installs into the Poetry cache dir (where the hook can't find the binary) are no longer a silent false-success. ✅

ruff-format: uv detection heuristic — Detection is now explicit: uv.lock, poetry.lock, or the matching pyproject.toml tool section. The previous "when the repo uses uv" with no criteria is gone. ✅


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (8th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

I applied the fix locally but github-actions[bot] does not have write access to this branch. The exact patch to land:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

The two-part problem, unchanged from prior rounds:

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching on the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" describes this conceptually but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip depending on the CLI implementation. The framing could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: Three findings closed this round (7efba13): firecrawl invalid-key remediation, ruff Poetry in-project gate, and ruff uv detection heuristic. One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 8 rounds). The exact patch is in the diff above. Push access is not available to this bot account — the fix needs to be applied by @kyle-sexton.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7efba136d9

ℹ️ 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".

Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
Codex on #355: a Pipenv project with an in-repo .venv fell through to
the bare pip install branch, leaving Pipfile/Pipfile.lock unchanged so
pipenv clean or recreation removes Ruff. Pipenv joins the managed-tool
set (pipenv install --dev ruff) with the same in-project-environment
gate as Poetry, and the plain-.venv branch now requires no
uv/Poetry/Pipenv markers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 54s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (a8f2c11 — Pipenv managed-tool gate for ruff-format) ✅
  • Verified biome-format Yarn Classic/Berry fix — still open; applied locally, push blocked
  • Post final findings

Fix confirmed in a8f2c11

ruff-format: Pipenv managed-tool gate (a8f2c11) — Pipenv projects (Pipfile/Pipfile.lock) now join the managed-tool set with pipenv install --dev ruff, gated on an in-project environment (PIPENV_VENV_IN_PROJECT=1 or a Pipenv-managed repo .venv) exactly like Poetry. The bare-pip branch now correctly requires the absence of all three tool markers. ✅


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (9th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

I committed the fix locally but github-actions[bot] does not have write access to this branch. The exact patch to apply:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

The two-part problem (unchanged from all prior rounds):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching on the backtick-string pnp won't catch undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" is descriptive but gives no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observations (not blocking — unchanged from prior rounds)

firecrawl: --status may make a network call in checkSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: a8f2c11 cleanly closes the Pipenv managed-dependency-state finding. One medium finding remains in biome-format (Yarn --version gate before nodeLinker, now 9 rounds). The exact patch is above — push access is not available to this bot account, so it needs to be applied by @kyle-sexton.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a8f2c110bb

ℹ️ 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".

Comment thread plugins/firecrawl/skills/setup/SKILL.md Outdated
Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
Codex on #355: (1) firecrawl setup adds the missing decision-table row
— status errors with a set key report INDETERMINATE with the error and
a retry suggestion, never a key-change directive off an unanswered
probe; (2) ruff-format's pyproject test now states the hook's actual
rule: [tool.ruff] or any [tool.ruff.*] subtable counts as governing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 5s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (a97fd8f — firecrawl indeterminate-status verdict; ruff subtable config test)
  • Applied biome-format Yarn fix locally (push blocked — patch below)
  • Post final findings

Fixes confirmed in a97fd8f

firecrawl: INDETERMINATE state for status errors while key is set — When firecrawl --status cannot answer (error/timeout/network failure) while FIRECRAWL_API_KEY is set, the skill now correctly reports INDETERMINATE, surfaces the error verbatim, and suggests retrying — no verdict and no key-change directive off an unanswered probe. L48–51

ruff-format: subtable-only Ruff config recognition — The check step now explicitly counts a pyproject.toml only when it carries [tool.ruff] or any [tool.ruff.*] subtable such as [tool.ruff.lint], matching the hook's actual test at hooks/ruff-format.sh:137–140. A subtable-only config no longer yields a false "no governing Ruff config" result. L43–44


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (10th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

I applied and committed the fix locally (6162a40) but github-actions[bot] does not have write access to this branch. The exact patch to apply:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

The two-part problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" is descriptive but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. The framing could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: Two findings closed in a97fd8f (firecrawl INDETERMINATE state; ruff subtable config). One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 10 rounds). The exact patch is above; local commit 6162a40 is ready but push access is unavailable to this bot account.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a97fd8f6d3

ℹ️ 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".

Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
…back

Codex on #355: a uv project before its first lock ([tool.uv] present,
no uv.lock) with an existing .venv fell through to bare pip install,
leaving Ruff out of uv's declared dependencies. The uv marker set now
includes the [tool.uv] section, and the plain-venv branch requires the
absence of lockfiles AND pyproject sections for all three tools.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 54s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (beed7e9) — ruff-format [tool.uv] marker fix ✅
  • Verify biome-format Yarn Classic/Berry disambiguation (still open)
  • Apply biome-format Yarn fix locally (push blocked — patch below)
  • Post final findings

Fix confirmed in beed7e9

ruff-format: [tool.uv] section counts as a uv marker — A uv-managed project with [tool.uv] in pyproject.toml but no committed uv.lock (before its first lock) with an existing .venv now correctly routes to uv add --dev ruff instead of bare pip install. The plain-venv branch now also explicitly requires the absence of lockfiles and pyproject sections for all three tools. ✅


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (11th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 62–67 (unchanged since c799558)

I committed the fix locally (d79ec03) but github-actions[bot] does not have write access to this branch. The exact patch to apply:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

The two-part problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" is descriptive but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. The framing could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: beed7e9 closes the ruff-format [tool.uv] finding cleanly. One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 11 rounds). The exact patch is in the diff above; local commit d79ec03 is ready but push access is not available to this bot account — the fix needs to be applied by @kyle-sexton.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: beed7e9c6a

ℹ️ 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".

Comment thread plugins/actionlint/skills/setup/SKILL.md
Comment thread plugins/firecrawl/skills/setup/SKILL.md Outdated
…determinate covers unset key

Codex on #355 flagged actionlint's setup reporting FAIL prerequisites
while the toggle deliberately disables the hook (which exits through
its enabled-gate before probing). Applied as a class fix across all
seven hook-plugin setups in this tranche: a disabled toggle downgrades
every prerequisite absence to INFO, noted as restoring FAIL semantics
on re-enable. Firecrawl's INDETERMINATE verdict now covers an
unanswered status probe regardless of key state — persisted CLI-config
credentials may be valid, so no key creation is directed off an
unanswered probe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 27s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (249c52c) — disabled-toggle prereq FAILs (7 setups) + firecrawl indeterminate covers unset key
  • Apply biome-format Yarn Classic/Berry fix (push blocked — patch below)
  • Post findings

Fixes confirmed in 249c52c

Disabled-toggle prerequisite downgrade — Seven hook-plugin setup skills (actionlint, bash-format, biome-format, desktop-notification, eol-normalizer, powershell-format, ruff-format) now carry the enabled-gate paragraph: when *_enabled=false, every prerequisite absence downgrades from FAIL to INFO — the hook exits before probing anything, so a disabled plugin is not broken. This is a class fix across all seven and matches the Codex finding exactly. ✅

firecrawl: INDETERMINATE covers the unset-key case (249c52c) — The INDETERMINATE state now applies regardless of key state (Status CANNOT answer (error, timeout, network failure) → INDETERMINATE regardless of the key's state). An unanswered probe no longer directs any key creation off an unconfirmed result, even when the key is unset. L47–51


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (12th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 67–72 (unchanged since c799558)

I committed the fix locally (c5529bb) but github-actions[bot] does not have write access to this branch. The exact patch to apply:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

The two-part problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching on the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" is descriptive but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip depending on the CLI implementation. The framing could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied
Disabled-toggle downgrades prereq FAILs to INFO (7 hook plugins)

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: Two findings closed in 249c52c (disabled-toggle prereq downgrade across 7 hook plugins; firecrawl INDETERMINATE regardless of key state). One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 12 rounds). The exact patch is in the diff above; local commit c5529bb is ready but push access is not available to this bot account — the fix needs to be applied by @kyle-sexton.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 249c52c1cb

ℹ️ 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".

Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
kyle-sexton and others added 2 commits July 18, 2026 19:57
Codex on #355: uv add syncs by default and creates .venv when absent,
violating the skill's never-create guarantee. With no existing .venv
the skill now records the dependency via uv add --dev ruff --no-sync
and hands uv sync to the consumer as their own step, deferring the
re-check until after it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 20s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (d1ec672) — ruff-format uv add --no-sync fix ✅
  • Check remaining open finding: biome-format Yarn Classic/Berry disambiguation (still open — patch prepared; push blocked)
  • Verify contract invariants and security posture
  • Post findings

Fix confirmed in d1ec672

ruff-format: uv add --no-sync when no .venv existsapply install-ruff now uses uv add --dev ruff --no-sync when a uv-managed project has no existing .venv, records the dependency without syncing (which would create .venv and violate the skill's never-create guarantee), and defers uv sync to the consumer as their own step with the re-check after it. L79–82


Remaining medium finding — biome-format: Yarn Berry nodeLinker unset returns undefined, not pnp (13th round)

File: plugins/biome-format/skills/setup/SKILL.md
Lines: 67–72 (unchanged since c799558)

I committed the fix locally (03faaf3) but github-actions[bot] does not have write access to this branch. The exact patch to apply:

-For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install.
+For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance.

The two-part problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" is descriptive but gives the model no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. The framing could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied
Disabled-toggle downgrades prereq FAILs to INFO (7 hook plugins)

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • ruff uv no-.venv path uses --no-sync to avoid creating the environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: d1ec672 closes the ruff-format uv add --no-sync finding cleanly. One medium finding remains in biome-format (Yarn --version gate before nodeLinker, 13 rounds). The exact patch is in the diff above; local commit 03faaf3 is ready but push access is not available to this bot account — the fix needs to be applied by @kyle-sexton.

Carries the class fix from this PR's seven other hook-plugin setups to
the freshly merged flagship: a disabled toggle downgrades prerequisite
FAILs to INFO, noted as restoring FAIL semantics on re-enable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 5m 5s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (421051a — markdown-format disabled-toggle downgrade)
  • Check biome-format Yarn Classic/Berry disambiguation (still open at round 13)
  • Discovered: markdown-format exemplar carries the identical Yarn detection issue
  • Applied fix locally to both files (commit 2c514d9 — push blocked, patch below)
  • Post findings

Fix confirmed in 421051a

markdown-format: disabled-toggle downgrade (421051a) — The markdown-format exemplar now has the same enabled-gate paragraph as the nine cloned skills: when the toggle is disabled, every prerequisite absence downgrades from FAIL to INFO. ✅


Fixes applied locally — push blocked

I committed both fixes below as 2c514d9 but github-actions[bot] does not have write access to this branch. Apply either via the Fix this → link or by cherry-picking the diff below.


Medium — biome-format AND markdown-format: Yarn Berry nodeLinker unset returns undefined, not pnp

Reading the latest commit surfaced that markdown-format (the exemplar that was cloned to all 9 skills) carries the same pnp (Berry's default when unset) language that has been flagged in biome-format across 13 rounds. Both need the fix.

Files:

The problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching on the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" describes this conceptually but gives no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Exact patch for biome-format:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Exact patch for markdown-format:

-never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — ask
-the repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default
-when unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on
-`PATH` or switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such
-setting and always materializes `node_modules`) → install. The
-verify-after-remediation rule below is the backstop when an install still yields no
+never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The
+verify-after-remediation rule below is the backstop when an install still yields no

Low-severity observation (not blocking)

firecrawl: --status may make a network call in the check phaseSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied
Disabled-toggle downgrades prereq FAILs to INFO (all 9 including markdown-format)

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: 421051a closes the markdown-format disabled-toggle gap. One medium finding spans both biome-format (13 rounds) and markdown-format (newly identified as the exemplar source): the Yarn --version gate before nodeLinker. Local commit 2c514d9 has the exact patch for both — push access is not available to this bot account, so the fix needs to be applied by @kyle-sexton.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 421051aa1e

ℹ️ 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".

Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
Comment thread plugins/ruff-format/skills/setup/SKILL.md Outdated
… ladder

Codex rounds kept finding tools and states the enumerated ladder
missed (PDM; env-creating add commands under in-project config). The
section is now six ordered principles — identify the manager from the
repo's own markers, record through it never around it, never create or
mutate an environment (record-only mode or hand the sync to the
consumer), install only where the hook resolves, bare pip only in a
plain unmanaged .venv, ambiguity stops — with the tool commands as
examples. Any manager, present or future, resolves through the same
rules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 0s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (90f184f — ruff-format ordered-principles refactor)
  • Verify biome-format Yarn Classic/Berry disambiguation (still open — patch below)
  • Verify markdown-format Yarn fix (same issue — patch below)
  • Applied both fixes locally (push blocked — patch included)
  • Post findings

Fix confirmed in 90f184f

ruff-format: install-ruff as ordered principles — The previous tool-enumeration ladder (uv → Poetry → Pipenv → plain pip) is replaced by six ordered principles that decide every case regardless of which manager the repo uses. This cleanly closes all of the Codex findings from the previous rounds:

  • Principle 1 (identify manager from markers) + principle 2 (record through the manager) — covers PDM, Hatch, and any other future manager without needing to enumerate them.
  • Principle 3 (never create/mutate an environment) — closes the uv --no-sync finding and the "don't run poetry add / pipenv install when the environment doesn't exist yet" finding in one rule.
  • Principle 4 (only where the hook resolves; in-project gate for Poetry/Pipenv) — closes the Poetry cache-dir venv finding.
  • Principle 5 (bare pip only into a plain existing .venv with no manager markers) — restricts the pip path correctly.
  • Principle 6 (ambiguity stops) — safe fallback.

The resulting skill section is more rigorous, more maintainable, and will age better than the previous enumerated ladder. ✅


Remaining medium finding — biome-format AND markdown-format: Yarn Berry nodeLinker unset returns undefined, not pnp

This finding has been flagged since round 1 of this PR. The identical text exists in both files and is unchanged since c799558. I committed the fix locally (16cae19) but github-actions[bot] has no push access to this branch.

Files:

The problem:

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" describes this conceptually but gives no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Exact patch for biome-format/skills/setup/SKILL.md:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Exact patch for markdown-format/skills/setup/SKILL.md:

-never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — ask
-the repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default
-when unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on
-`PATH` or switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such
-setting and always materializes `node_modules`) → install. The
-verify-after-remediation rule below is the backstop when an install still yields no
+never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The
+verify-after-remediation rule below is the backstop when an install still yields no

Fix this →


Low-severity observation (not blocking — unchanged from prior rounds)

firecrawl: --status may make a network call in checkSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied
Disabled-toggle downgrades prereq FAILs to INFO (all 9 + markdown-format)

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff never creates an environment, installs globally, or installs outside a managed environment ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: 90f184f closes the remaining ruff-format findings cleanly — the ordered-principles structure is comprehensive and future-proof. One medium finding remains across both biome-format and markdown-format (Yarn --version gate before nodeLinker). The fix has been committed locally as 16cae19 but push access is unavailable to this bot account — apply the diffs above to close this PR.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90f184f8e2

ℹ️ 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".

Comment thread plugins/actionlint/skills/setup/SKILL.md Outdated
…y semantics (8 setups)

Codex on #355: per the playbook's smoke-tested finding, --config is
ignored once a plugin is installed, so the advertised headless
reconfigure command could not change the setting on the only state
setup runs in. All eight hook-plugin setups now direct interactive
/plugin configure any time, and the headless path states the
fresh-install-only semantics with uninstall-then-install --config.
(source-control's setup carries the same stale command — tranche-3
scope, noted for that PR.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 41s —— View job


PR Review — feat: adopt the uniform setup contract across 9 formatter/CLI plugins

  • Gather context and understand request
  • Read latest commit (9851ef8 — headless toggle remediation) ✅
  • Verify biome-format and markdown-format Yarn Classic/Berry fix status (still open)
  • Apply Yarn fix locally to both files (commit de7bbdc — push blocked)
  • Post findings

Fix confirmed in 9851ef8

Headless toggle remediation across 8 setups — All eight hook-plugin setup skills (actionlint, bash-format, biome-format, desktop-notification, eol-normalizer, markdown-format, powershell-format, ruff-format) now state the correct reconfigure path: /plugin configure <plugin> for interactive (any time), and for headless the fresh-install-only semantics of --config are made explicit: claude plugin uninstall <plugin> then claude plugin install <plugin>@<marketplace> --config <flag>=true. The previous single branch that showed only the --config command (which is ignored on an already-installed plugin) is gone. ✅

playwright is guidance-only and has no toggle, so it's correctly excluded from this change.


Remaining medium finding — biome-format AND markdown-format: Yarn Berry nodeLinker unset returns undefined, not pnp

This finding has been open since round 1 (prior to c799558). I applied the fix locally as commit de7bbdc but github-actions[bot] does not have write access to this branch.

Files:

Exact patch for biome-format/skills/setup/SKILL.md:

-change is stated before running. For a Yarn repository, don't infer the linker — ask the
-repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default when
-unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or
-switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such setting and
-always materializes `node_modules`) → install. The verify-after-remediation rule below is
+change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `@biomejs/biome` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The verify-after-remediation rule below is

Exact patch for markdown-format/skills/setup/SKILL.md:

-never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — ask
-the repo's own Yarn: run `yarn config get nodeLinker` in the repo. `pnp` (Berry's default
-when unset) → skip the install and give guidance, because Plug'n'Play generates a loader file,
-not the `node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on
-`PATH` or switch the linker. `node-modules`/`pnpm`, or Yarn Classic (which has no such
-setting and always materializes `node_modules`) → install. The
-verify-after-remediation rule below is the backstop when an install still yields no
+never introduce a competing lockfile. The change is stated before running. For a Yarn repository, don't infer the linker — probe
+the repo's own Yarn in two steps. First run `yarn --version`: a `1.x` output means Yarn
+Classic, which always materialises `node_modules` → proceed with `yarn add -D`. For `2.x`+
+(Yarn Berry), run `yarn config get nodeLinker`: `node-modules` or `pnpm` → install; `pnp`
+→ skip and give guidance, because Plug'n'Play generates a loader file, not the
+`node_modules/.bin` shim the hook resolves; install `markdownlint-cli2` on `PATH` or switch
+the linker. Treat `undefined`, empty, or a non-zero exit (Berry's state when `nodeLinker`
+is absent from `.yarnrc.yml`, whose effective linker is PnP) the same as `pnp` → skip and
+give guidance. The
+verify-after-remediation rule below is the backstop when an install still yields no

The two-part problem (unchanged since round 1):

  1. yarn config get nodeLinker returns the literal string undefined (not pnp) on Yarn Berry when nodeLinker is absent from .yarnrc.yml. A model matching on the backtick-string pnp won't match undefined and falls through to the install branch — wrong for an unset Berry project whose effective linker is PnP.
  2. Yarn Classic v1.x exits non-zero for nodeLinker. The parenthetical "(which has no such setting…)" describes this conceptually but gives no execution path to distinguish Classic from an unset Berry project — both produce non-pnp output; one should install and one should not.

Fix this →


Low-severity observation (not blocking)

firecrawl: --status may make a network call in checkSKILL.md L35: firecrawl --status is invoked in the read-only check step and may make a network round-trip depending on the CLI implementation. Could note "read-only network probe; no state modified." Weak finding; not blocking.


Contract invariants — all 9 pass

Invariant All 9
disable-model-invocation: true
Reads hook/skill source first, doesn't recite SKILL.md
apply re-runs check before acting
Write paths named in argument-hint (biome/ruff/playwright)
States change before running
Re-probes after remediation (never trusts exit code)
Never writes plugin cache, user settings, or pluginConfigs
Non-interactive when action argument supplied
Disabled-toggle downgrades prereq FAILs to INFO (all 9 + markdown-format)
Headless toggle remediation states --config fresh-install-only semantics (8 hook plugins)

Security — all clear

  • Firecrawl FIRECRAWL_API_KEY presence-only ([[ -n "${FIRECRAWL_API_KEY:-}" ]]), value never printed ✅
  • playwright apply install-cli is the only machine-global write, correctly gated and labelled ✅
  • powershell-format CustomRulePath trust callout surfaced in check
  • ruff apply install-ruff ordered-principles: never creates an environment, never installs outside a managed environment, --no-sync when no .venv exists ✅
  • No ../ reach-outs; ${CLAUDE_PLUGIN_ROOT} used throughout ✅

Summary: 9851ef8 closes the headless toggle finding cleanly across all eight hook-plugin setups. One medium finding remains: the Yarn --version gate before nodeLinker in biome-format and markdown-format. The fix has been committed locally as de7bbdc but push access is unavailable to this bot account — apply the two diffs above to close the last open finding before merge.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant