mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-15 12:53:31 +08:00
Contributors and coding agents need one local command that both reports and enforces the quality contract. This change turns the PR gate into the shared verification entrypoint, adds path-selected local lanes, tightens coverage accounting around changed lines, and documents the repair loop in contributor and agent-facing guidance. Constraint: Ordinary PR verification must stay non-live and runnable without provider credentials Constraint: Coverage policy updates in this commit require maintainer approval before push/merge Rejected: Keep quality guidance only in docs | agents need executable scripts and AGENTS.md instructions to follow the loop consistently Confidence: high Scope-risk: broad Directive: Do not bypass `bun run verify` for production changes; fix failed lanes and coverage reports instead of lowering thresholds Tested: bun run check:policy Tested: ALLOW_CLI_CORE_CHANGE=1 ALLOW_COVERAGE_BASELINE_CHANGE=1 bun run verify Not-tested: live provider baseline; no provider credentials were required for this non-live PR gate
142 lines
2.7 KiB
TypeScript
142 lines
2.7 KiB
TypeScript
export type QualityGateMode = 'pr' | 'baseline' | 'release'
|
|
|
|
export type LaneKind = 'command' | 'baseline-case' | 'desktop-smoke' | 'provider-smoke'
|
|
|
|
export type LaneCategory =
|
|
| 'scope'
|
|
| 'governance'
|
|
| 'unit'
|
|
| 'coverage'
|
|
| 'integration'
|
|
| 'smoke'
|
|
| 'native'
|
|
| 'docs'
|
|
|
|
export type LaneDefinition = {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
kind: LaneKind
|
|
command?: string[]
|
|
impactRequiredCheck?: string
|
|
baselineCaseId?: string
|
|
baselineTarget?: BaselineTarget
|
|
requiredForModes: QualityGateMode[]
|
|
category?: LaneCategory
|
|
live?: boolean
|
|
}
|
|
|
|
export type BaselineCase = {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
fixture: string
|
|
prompt: string
|
|
mode: 'ui' | 'websocket'
|
|
requiredCapabilities: Array<'model' | 'file-edit' | 'shell' | 'permission' | 'browser'>
|
|
timeoutMs: number
|
|
verify: {
|
|
commands: string[][]
|
|
requiredFiles?: string[]
|
|
expectedFiles?: string[]
|
|
forbiddenFiles?: string[]
|
|
transcriptAssertions?: string[]
|
|
}
|
|
}
|
|
|
|
export type BaselineTarget = {
|
|
providerId: string | null
|
|
modelId: string
|
|
label: string
|
|
}
|
|
|
|
export type LaneStatus = 'passed' | 'failed' | 'skipped'
|
|
|
|
export type LaneResult = {
|
|
id: string
|
|
title: string
|
|
description?: string
|
|
category?: LaneCategory
|
|
live?: boolean
|
|
status: LaneStatus
|
|
command?: string[]
|
|
durationMs: number
|
|
exitCode?: number
|
|
skipReason?: string
|
|
error?: string
|
|
artifactDir?: string
|
|
logPath?: string
|
|
}
|
|
|
|
export type ImpactSummary = {
|
|
changedFiles?: number
|
|
areas: string[]
|
|
labels: string[]
|
|
blocked?: boolean
|
|
requiredChecks: string[]
|
|
testCoverageSignals: string[]
|
|
riskNotes: string[]
|
|
}
|
|
|
|
export type CoverageMetricSummary = {
|
|
pct: number
|
|
covered: number
|
|
total: number
|
|
}
|
|
|
|
export type CoverageSuiteSummary = {
|
|
id: string
|
|
title: string
|
|
status: string
|
|
lines?: CoverageMetricSummary
|
|
functions?: CoverageMetricSummary
|
|
branches?: CoverageMetricSummary
|
|
statements?: CoverageMetricSummary
|
|
}
|
|
|
|
export type ReportArtifact = {
|
|
title: string
|
|
path: string
|
|
}
|
|
|
|
export type QualityGateOptions = {
|
|
mode: QualityGateMode
|
|
dryRun: boolean
|
|
allowLive: boolean
|
|
baselineTargets: BaselineTarget[]
|
|
rootDir: string
|
|
artifactsDir?: string
|
|
runOutputDir?: string
|
|
runId?: string
|
|
onlyLaneSelectors?: string[]
|
|
skipLaneSelectors?: string[]
|
|
}
|
|
|
|
export type QualityGateReport = {
|
|
schemaVersion: 1
|
|
runId: string
|
|
mode: QualityGateMode
|
|
dryRun: boolean
|
|
allowLive: boolean
|
|
startedAt: string
|
|
finishedAt: string
|
|
rootDir: string
|
|
git: {
|
|
sha: string | null
|
|
dirty: boolean
|
|
}
|
|
results: LaneResult[]
|
|
impact?: ImpactSummary
|
|
coverage?: {
|
|
reportPath: string
|
|
suites: CoverageSuiteSummary[]
|
|
failures: string[]
|
|
}
|
|
artifacts: ReportArtifact[]
|
|
summary: {
|
|
passed: number
|
|
failed: number
|
|
skipped: number
|
|
}
|
|
}
|