Repository navigation
fix(hook): resolve Charter through the repo package manager in the pre-commit hook (#366) - #379
Merged
Merged
Conversation
…repo package manager (#366) The generated pre-commit hook called a bare `npx charter` for tidy, the scoped doctor gate (#365) and adf evidence. Under Yarn Plug'n'Play npx cannot resolve the installed CLI and falls back to the unrelated registry package `charter`, so the gate failed before `yarn run verify:adf`. The hook now picks the package manager once (PnP markers, then the #365 lockfile + PATH order) and defines charter_cli: `yarn charter` (`yarn --silent charter` on Yarn 1), `pnpm exec charter`, or `npx --no-install charter`, none of which downloads a package. A missing pm binary warns and falls back to npx --no-install / npm run. A new marker lets doctor report a pre-#366 hook as INFO in PnP repos. The CHARTER_HOOK_SCOPED_DOCTOR token flow is unchanged. Tests run the generated hook with stub yarn/pnpm/npx/npm on PATH for yarn PnP, yarn classic, pnpm and npm fixtures, plus missing-pm fallbacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ade, scope the CLI hint (#366) Round 2 on review findings: - npm runner is `npm exec --no --no-update-notifier -- @stackbilt/cli`, never the bare name `charter`. Verified on npm 11.17 against an unreachable registry: a local install runs with no registry request; without one npm requests @stackbilt/cli metadata only (and may run a global install when online), and never installs anything. - Package manager choice walks PnP -> pnpm-lock -> yarn.lock -> npm and takes the first whose marker exists and whose binary is on PATH (the #365 cascade), warning when the first marker's binary is missing. - PnP detection comes from one source (PNP_MARKER_FILES, YARNRC_PNP_LINKER_ERE / yarnrcPnpLinkerRegExp) for the hook and doctor. - The devDependency hint prints only when `charter_cli --version` also fails, not when doctor ran and reported findings. - Docs: upgrading-to-2.0 drops the PnP known limitation; CHANGELOG and cli-reference state the exact network behaviour, global-install pickup, corepack first-use download, and that the fix covers the pre-commit hook only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
…l install (#366) Round 3 on review findings: - Resolve once at the top of the hook. Under npm, a local install (node_modules/.bin/charter or charter.cmd) runs through `npm exec --no --no-update-notifier --fetch-retries=0 -- @stackbilt/cli`; without one a global `charter` on PATH runs directly; with neither, charter_cli runs nothing, tidy is skipped and the gate fails after one devDependency hint, with no network request. Measured offline (npm 11.17, registry unreachable): local 6 s, none 0 s, global 2 s. - One `--version` probe per commit (HOOK_CLI_PROBE_BLOCK): unresolvable -> hint once; 1.x -> one warning to upgrade to @stackbilt/cli 2.x. - charter_cli runs $CHARTER_RUN, so the printed Run: commands are exactly what ran (HOOK_CLI_COMMANDS is the single source for hook, help, tests). - Shared PnP regex uses [ \t\r\f\v] instead of \s; the agreement test covers `nodeLinker:\n pnp`. A mocked-module test fails if doctor stops using the shared source. - hook --help lists the cascade order and the exact commands. - A failed tidy dry run no longer prints "Vendor config files are clean." (template and the repo's own .githooks/pre-commit). - docs/upgrading-to-2.0.md no longer says the hooks call `npx charter`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tidy notes (#366) Round 4 on review nits: - Yarn with a node_modules linker and no node_modules/.bin/charter now runs a global `charter` from PATH (as 2.1.0's `npx charter` found it), else reports Charter missing with no calls. Yarn PnP stays `yarn charter`. pnpm reports missing when neither a local bin nor a global charter exists (pnpm exec searches PATH itself). - The --version probe keeps stderr. A found binary whose --version fails is "installed but failed to run: <first line>", with no devDependency hint. Output without `charter v<digit>` warns that the charter found is not @stackbilt/cli and runs nothing else. `charter v10.0.0` is not flagged as 1.x (tested). The 1.x warning says to upgrade @stackbilt/cli to 2.x (as a devDependency, or your global install). - With nothing resolved, the gate prints no Run: command. - Tidy's stderr notes from the dry run (an unmanaged file it skips) are shown under "adf tidy notes:", and the hook no longer then claims the vendor files are clean (template and .githooks/pre-commit). - Docs: one table for local/global/neither per package manager in cli-reference; upgrading-to-2.0 and the CHANGELOG describe the global behaviour for npm, pnpm and Yarn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #366
Problem
Since #365, the generated pre-commit hook runs
npx charter doctor --adf-only --ci --staged …before<pm> run verify:adf. It has always runnpx charterfor tidy andadf evidencetoo.Under Yarn Plug'n'Play there is no
node_modules/.bin, so npx misses the installed CLI and falls back to the unrelated registry packagecharter(0.0.2, which has no bin). The gate fails beforeyarn run verify:adfruns. In any repo without Charter installed, the same fallback fetches that package.Fix (scope: the pre-commit hook only)
Package manager, picked once per hook run
HOOK_CLI_RESOLVE_BLOCKtakes the first candidate whose marker exists and whose binary is on PATH. This is #365's cascade with PnP in front:.pnp.cjs,.pnp.js, or.yarnrc.ymlwithnodeLinker: pnp→ yarnpnpm-lock.yaml→ pnpmyarn.lock→ yarnIf the first marker it finds has no binary on PATH, the hook warns and names the runner it uses instead. Under PnP the warning adds
corepack enable.How Charter runs
charter_cliruns exactly$CHARTER_RUN, and everyRun:hint prints that same command. The strings come fromHOOK_CLI_COMMANDS. "Local" meansnode_modules/.bin/charterorcharter.cmdexists; "global" means acharteron PATH.yarn charteryarn charter(no fallback: there is nonode_modulesto check)yarn charternode_moduleslinkeryarn charter(yarn --silent charteron Yarn 1)charter, run directlypnpm exec charterpnpm exec charter(it searches PATH)npm exec --no --no-update-notifier --fetch-retries=0 -- @stackbilt/clicharter, run directly"Nothing" means the hook calls neither Charter nor the package manager. It prints the devDependency hint once, skips tidy, and fails the gate. It prints no
Run:command, since none would work.One
--versionprobe per commitHOOK_CLI_PROBE_BLOCKruns once, before any other Charter call, and keeps stderr.--versionfails:Charter is installed but failed to run:plus the first error line. No devDependency hint.charter v<digit>: a warning that thecharterfound is not@stackbilt/cli, and nothing else runs.charter v0.x/v1.x: one warning to "Upgrade @stackbilt/cli to 2.x (as a devDependency, or your global install)".charter v10.0.0is not flagged.Network and timing
The hook never installs a package and never runs a downloaded one. The only network use left is Corepack downloading Yarn or pnpm on first use.
Measured offline, with npm 11.17, the registry at
127.0.0.1:9, a real@stackbilt/cli@2.1.0and a real hook run:Run:linecharterv1.9.3 onlyTidy notes
Tidy's dry-run stderr is now kept. A note about a staged file it leaves alone (an unmanaged
CLAUDE.md, verified against the real CLI) is shown under[pre-commit] adf tidy notes:. In that case, and when the dry run fails, the hook no longer prints "Vendor config files are clean."This was a pre-existing bug. It is fixed in the shared template and in the repo's own
.githooks/pre-commit.Other changes
PNP_MARKER_FILESandYARNRC_PNP_LINKER_ERE. The JS form,yarnrcPnpLinkerRegExp(), uses[ \t\r\f\v], so like grep it never matches across a newline.charter doctorreports a pre-hook: pre-commit gate fails under Yarn Plug'n'Play (npx charter can't resolve the PnP binary) #366 hook as INFO in PnP repos.hook --helplists the cascade, the commands, and how global installs are handled.CHARTER_HOOK_SCOPED_DOCTORtoken flow andsetup.ts. The CI workflow is fixed separately in Generated CI workflow still runs bare npx charter (breaks under Yarn PnP / without a local install) #380 / fix(setup): run Charter through the package manager in the generated workflow (#380) #388.Existing installs
Installed hooks do not update themselves. Re-run
charter hook install --pre-commit. It is required under Yarn PnP and recommended everywhere else. The CHANGELOG,docs/cli-reference.mdanddocs/upgrading-to-2.0.mdsay so.Tests
hook-pm.test.tsruns the real hook undersh, with stubs for yarn, pnpm, npx, npm and charter on PATH that record their argv. No network. It covers:.pnp.cjsand.pnp.jsalone, plus two mutation tests;v10/v2/v3-betanot being flagged;Run:line;Run:lines matching the command that actually ran;doctor-pnp-source.test.tsmocks the hook module's PnP exports, so a doctor that hard-codes detection fails.hook.test.tscovers the doctor rows.integration/precommit-hook.test.tsredefinescharter_cliahead of the probe.e55afd7: 1893 passed. The 3 failures are the known Windows-only path-separator cases (bootstrap bootstrap: phases 6/7 collect warnings without printing them; absoluteAiDirArg misses Windows paths on POSIX #307, context-refresh, serve-context).🤖 Generated with Claude Code