Keep pre-push fast by moving coverage out of the hook

Daily pushes should catch policy and path-aware local failures without making every contributor wait for full coverage. The hook now runs a new quality:push entrypoint that reuses the PR quality gate while skipping coverage; verify, quality:pr, and CI still retain the full coverage gate for PR readiness.

Constraint: Forks and local contributors need a faster default push path
Rejected: Remove coverage from quality:pr | PR readiness and CI still need the ratcheted coverage signal
Confidence: high
Scope-risk: narrow
Directive: Keep pre-push on quality:push; use verify or quality:pr when coverage evidence is required
Tested: bun test scripts/pr/quality-contract.test.ts scripts/git-hooks/install.test.ts
Tested: bun run check:policy
Tested: bun run quality:push
Not-tested: Live provider smoke; intentionally remains opt-in
This commit is contained in:
程序员阿江(Relakkes) 2026-05-16 19:11:48 +08:00
parent 3489157bad
commit 83a96ef13d
7 changed files with 17 additions and 8 deletions

View File

@ -54,7 +54,7 @@ explicitly requested it.
bun run hooks:install
```
安装后,每次 push 都会先运行同一套验证入口(内部是 `bun run quality:pr`,等价于 `bun run verify`),失败则 push 中止。维护者机器可以把真实模型/桌面 smoke 也纳入 pre-push
安装后,每次 push 都会先运行快速本地门禁(内部是 `bun run quality:push`)。它复用 PR gate 的 impact/policy/路径检查,但默认跳过耗时的 coverage lane完整覆盖率仍保留在 `bun run verify``bun run quality:pr` 和 CI。维护者机器可以把真实模型/桌面 smoke 也纳入 pre-push
```bash
bun run quality:providers

View File

@ -97,7 +97,7 @@ Git hooks are local, so each clone needs to install the hook once:
bun run hooks:install
```
After installation, every `git push` runs the same verification entrypoint internally (`bun run quality:pr`, equivalent to `bun run verify`). If unit tests, coverage, docs/native/adapter checks, or any other selected path-aware lane fails, the local hook blocks the push.
After installation, every `git push` runs the fast local gate internally (`bun run quality:push`). It reuses the PR gate impact, policy, and path-aware checks, but skips the expensive coverage lane by default; full coverage remains in `bun run verify`, `bun run quality:pr`, and CI. If unit tests, docs/native/adapter checks, or any other selected fast path-aware lane fails, the local hook blocks the push.
Maintainers or contributors with model quota can also add real provider smoke and desktop agent-browser smoke to the pre-push hook:
@ -114,7 +114,7 @@ bun run hooks:install -- --live-provider-model minimax:main:minimax-main --live-
These options are stored in local `.git/config` as `quality.prePush*` keys, so provider selectors and secrets are not committed. `smoke` mode covers real provider connectivity plus the desktop UI chat smoke; `baseline` mode also runs every real Coding Agent baseline case.
Maintainer-level overrides must also be explicit local config before the hook passes them to `quality:pr`:
Maintainer-level overrides must also be explicit local config before the hook passes them to `quality:push`:
```bash
bun run hooks:install -- --allow-cli-core-change --allow-coverage-baseline-change

View File

@ -97,7 +97,7 @@ Git hook 不能提交到远端自动生效,所以每个 clone 需要安装一
bun run hooks:install
```
安装后,每次 `git push` 都会先运行同一套验证入口(内部是 `bun run quality:pr`,等价于 `bun run verify`)。如果单元测试、覆盖率、文档/native/adapter 等按路径选中的门禁失败push 会被本机 hook 阻断。
安装后,每次 `git push` 都会先运行快速本地门禁(内部是 `bun run quality:push`)。它复用 PR gate 的 impact/policy/路径检查,但默认跳过耗时的 coverage lane完整覆盖率仍保留在 `bun run verify``bun run quality:pr` 和 CI。如果单元测试、文档/native/adapter 等按路径选中的快速门禁失败push 会被本机 hook 阻断。
维护者或有模型额度的贡献者可以把真实 provider smoke 和桌面 agent-browser smoke 也纳入 push 前门禁:
@ -114,7 +114,7 @@ bun run hooks:install -- --live-provider-model minimax:main:minimax-main --live-
这些选项写入本机 `.git/config``quality.prePush*` 配置,不会提交 provider selector 或密钥。`smoke` 模式覆盖真实 provider 连通性和桌面 UI 聊天 smoke`baseline` 模式会额外跑全部真实 Coding Agent baseline case。
维护者级 override 也必须显式写入本机配置hook 才会传给 `quality:pr`
维护者级 override 也必须显式写入本机配置hook 才会传给 `quality:push`
```bash
bun run hooks:install -- --allow-cli-core-change --allow-coverage-baseline-change

View File

@ -26,6 +26,7 @@
"quality:verify": "bun run quality:pr",
"quality:providers": "bun run scripts/quality-gate/providers.ts",
"quality:pr": "bun run quality:gate --mode pr",
"quality:push": "bun run quality:gate --mode pr --skip coverage",
"quality:baseline": "bun run quality:gate --mode baseline",
"quality:release": "bun run quality:gate --mode release",
"quality:smoke": "bun run quality:gate --mode baseline --allow-live --only 'provider-smoke:*' --only 'desktop-smoke:*'",

View File

@ -196,7 +196,8 @@ if (import.meta.main) {
})
console.log(`Installed pre-push quality gate: ${result.hookPath}`)
console.log('Every git push now runs: bun run quality:pr')
console.log('Every git push now runs: bun run quality:push')
console.log('Coverage remains in bun run verify, quality:pr, and CI.')
if (args.liveProviderModels.length > 0) {
console.log(`Live ${args.liveMode ?? 'smoke'} gate is enabled for ${args.liveProviderModels.length} provider selector(s).`)

View File

@ -16,7 +16,7 @@ is_enabled() {
esac
}
echo "[pre-push] Running PR quality gate: bun run quality:pr"
echo "[pre-push] Running fast pre-push quality gate: bun run quality:push"
if is_enabled "$(git_config quality.allowCliCoreChange)"; then
export ALLOW_CLI_CORE_CHANGE=1
@ -30,7 +30,7 @@ if is_enabled "$(git_config quality.allowCoverageBaselineChange)"; then
export ALLOW_COVERAGE_BASELINE_CHANGE=1
fi
bun run quality:pr
bun run quality:push
live="${QUALITY_PRE_PUSH_LIVE:-$(git_config quality.prePushLive)}"

View File

@ -36,18 +36,25 @@ describe('feature quality contract', () => {
const packageJson = JSON.parse(readFileSync('package.json', 'utf8')) as {
scripts?: Record<string, string>
}
const prePushHook = readFileSync('scripts/git-hooks/pre-push', 'utf8')
const contributing = readFileSync('docs/guide/contributing.md', 'utf8')
const englishContributing = readFileSync('docs/en/guide/contributing.md', 'utf8')
const rootContributing = readFileSync('CONTRIBUTING.md', 'utf8')
expect(packageJson.scripts?.verify).toBe('bun run quality:pr')
expect(packageJson.scripts?.['quality:verify']).toBe('bun run quality:pr')
expect(packageJson.scripts?.['quality:push']).toBe('bun run quality:gate --mode pr --skip coverage')
expect(packageJson.scripts?.['check:persistence-upgrade']).toBe('bun run scripts/quality-gate/persistence-upgrade.ts')
expect(prePushHook).toContain('bun run quality:push')
expect(prePushHook).not.toContain('\nbun run quality:pr\n')
expect(contributing).toContain('bun run verify')
expect(contributing).toContain('bun run quality:push')
expect(contributing).toContain('AI Coding Agent 修复循环')
expect(englishContributing).toContain('bun run verify')
expect(englishContributing).toContain('bun run quality:push')
expect(englishContributing).toContain('AI Coding Agent Fix Loop')
expect(rootContributing).toContain('bun run verify')
expect(rootContributing).toContain('bun run quality:push')
})
test('keeps general AI coding tools pointed at the same quality bar', () => {