Add lefthook git hooks with a vendor-manifest guard

pre-commit: ESLint --fix on staged files (vendored source excluded),
incremental typecheck, and the vendor-manifest guard — any staged
change under vendor/*/src must be accompanied by a vendor/README.md
update in the same commit, mechanizing the local-modification log
discipline. pre-push: tests + hygiene (knip/publint/constraints).
Hooks call the same package.json scripts CI runs (single source of
truth); installed automatically via postinstall.
This commit is contained in:
Tianyi Cui
2026-06-11 15:07:55 +08:00
parent 6796a3922d
commit 9d20a36cc4
4 changed files with 161 additions and 1 deletions
+29
View File
@@ -0,0 +1,29 @@
# Git hooks (lefthook). Hooks call the same package.json scripts CI runs —
# one source of truth; the hook is just an earlier, faster checkpoint.
# Install: `yarn lefthook install` (runs automatically via postinstall).
pre-commit:
parallel: true
jobs:
- name: lint (staged)
glob: '*.{ts,mts,cts,mjs}'
exclude:
- 'vendor/*/src/**'
run: node_modules/.bin/eslint --fix {staged_files} && git add {staged_files}
stage_fixed: true
- name: typecheck
glob: '*.ts'
run: yarn typecheck
- name: vendor manifest guard
run: scripts/check-vendor-manifest.sh
pre-push:
parallel: true
jobs:
- name: test
run: yarn test
- name: hygiene
run: yarn hygiene
+3 -1
View File
@@ -21,7 +21,8 @@
"knip": "knip",
"publint": "tsx scripts/publint-all.ts",
"hygiene": "yarn knip && yarn publint && yarn constraints",
"demo": "node --expose-internals --import tsx examples/echo-agent/start.ts"
"demo": "node --expose-internals --import tsx examples/echo-agent/start.ts",
"postinstall": "lefthook install"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^5.10.0",
@@ -31,6 +32,7 @@
"dumble": "^0.2.3",
"eslint": "^10.4.1",
"knip": "^6.16.1",
"lefthook": "^2.1.9",
"publint": "^0.3.21",
"tsx": "^4.22.4",
"typescript": "^6.0.3",
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Vendoring discipline, mechanized: any staged change under vendor/*/src or a
# vendored bin.js must come with a vendor/README.md change in the same commit
# (the manifest's local-modification log is the contract — see vendor/README.md).
set -euo pipefail
staged=$(git diff --cached --name-only)
vendor_src_changed=$(echo "$staged" | grep -E '^vendor/[^/]+/(src/|bin\.js)' || true)
manifest_changed=$(echo "$staged" | grep -x 'vendor/README.md' || true)
if [[ -n "$vendor_src_changed" && -z "$manifest_changed" ]]; then
echo 'vendor manifest guard: vendored SOURCE changed without updating vendor/README.md:'
echo "$vendor_src_changed" | sed 's/^/ /'
echo 'Log the modification in vendor/README.md ("Local modifications") and stage it.'
exit 1
fi
+112
View File
@@ -184,6 +184,7 @@ __metadata:
dumble: "npm:^0.2.3"
eslint: "npm:^10.4.1"
knip: "npm:^6.16.1"
lefthook: "npm:^2.1.9"
publint: "npm:^0.3.21"
tsx: "npm:^4.22.4"
typescript: "npm:^6.0.3"
@@ -2248,6 +2249,117 @@ __metadata:
languageName: node
linkType: hard
"lefthook-darwin-arm64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-darwin-arm64@npm:2.1.9"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"lefthook-darwin-x64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-darwin-x64@npm:2.1.9"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"lefthook-freebsd-arm64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-freebsd-arm64@npm:2.1.9"
conditions: os=freebsd & cpu=arm64
languageName: node
linkType: hard
"lefthook-freebsd-x64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-freebsd-x64@npm:2.1.9"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
"lefthook-linux-arm64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-linux-arm64@npm:2.1.9"
conditions: os=linux & cpu=arm64
languageName: node
linkType: hard
"lefthook-linux-x64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-linux-x64@npm:2.1.9"
conditions: os=linux & cpu=x64
languageName: node
linkType: hard
"lefthook-openbsd-arm64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-openbsd-arm64@npm:2.1.9"
conditions: os=openbsd & cpu=arm64
languageName: node
linkType: hard
"lefthook-openbsd-x64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-openbsd-x64@npm:2.1.9"
conditions: os=openbsd & cpu=x64
languageName: node
linkType: hard
"lefthook-windows-arm64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-windows-arm64@npm:2.1.9"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"lefthook-windows-x64@npm:2.1.9":
version: 2.1.9
resolution: "lefthook-windows-x64@npm:2.1.9"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"lefthook@npm:^2.1.9":
version: 2.1.9
resolution: "lefthook@npm:2.1.9"
dependencies:
lefthook-darwin-arm64: "npm:2.1.9"
lefthook-darwin-x64: "npm:2.1.9"
lefthook-freebsd-arm64: "npm:2.1.9"
lefthook-freebsd-x64: "npm:2.1.9"
lefthook-linux-arm64: "npm:2.1.9"
lefthook-linux-x64: "npm:2.1.9"
lefthook-openbsd-arm64: "npm:2.1.9"
lefthook-openbsd-x64: "npm:2.1.9"
lefthook-windows-arm64: "npm:2.1.9"
lefthook-windows-x64: "npm:2.1.9"
dependenciesMeta:
lefthook-darwin-arm64:
optional: true
lefthook-darwin-x64:
optional: true
lefthook-freebsd-arm64:
optional: true
lefthook-freebsd-x64:
optional: true
lefthook-linux-arm64:
optional: true
lefthook-linux-x64:
optional: true
lefthook-openbsd-arm64:
optional: true
lefthook-openbsd-x64:
optional: true
lefthook-windows-arm64:
optional: true
lefthook-windows-x64:
optional: true
bin:
lefthook: bin/index.js
checksum: 10c0/676d9798942439d1cd5373bb0b2c9907f6a8097b29c05cc028d87d897d2a2cfe15a8f7e4f40b02fa93cd1ae0f02528f24053a10fb5c5967210a9c23f3c7b5059
languageName: node
linkType: hard
"levn@npm:^0.4.1":
version: 0.4.1
resolution: "levn@npm:0.4.1"