CI job exemptions / 按职责免跑重型 CI¶
Policy, not a hand-maintained test selection¶
Every PR receives the same stable merge gate. The classifier reads the complete NUL-delimited Git diff at immutable base/head revisions; a PR title, label or author description cannot claim that runtime changes are “just UI”.
| Whole PR | Common TS/lint/contracts | Full Python / Windows | Stage2c | Packaged Dashboard |
|---|---|---|---|---|
| Existing Markdown-only documentation exemption | Skip | Skip | Skip | Existing Frontstage workflow |
| Client Dashboard source/assets only, optionally with docs | Run | Skip | Skip | Required build, freshness and browser smoke |
| Backend, prompt, tests, dependency, build, CI policy, mixed or unknown | Run | Run | Run | Also run for CI-policy rehearsal or forced-full UI |
| main push / manual run | Run | Run | Run | Existing surface workflows; CI-policy rehearsal when applicable |
The presentation boundary is deliberately small: Dashboard src/, public/
and packaged loopx/web/chat/, with explicit client-code/image/font extensions.
Package manifests, Vite/build configuration, native desktop code, backend Python
and arbitrary JSON are not exempt. Both sides of renames are classified; moving
runtime code into a UI directory stays full. Symlinks/type changes cannot qualify.
The new exemption is available only when the selector, gate and workflow blobs match the already-reviewed target branch. Changing CI policy cannot exempt its own PR. Missing policy or uncertain ownership runs full; missing Git revisions fail classification. The pre-existing documentation exemption remains supported.
本方案不是为每类 PR 维护一套测试清单,而是明确重型 job 的职责。纯前端变化不需要 重跑后端持久化与崩溃恢复矩阵,但前端自己的实际构建与浏览器验收成为必需项。 预算、静态宿主 prompt 和 Python/TS 逻辑暂不享受免跑;它们仍可能改变核心行为。 新增一种豁免只需审阅其业务边界和保留的验收,不要求列举全部替代测试文件。
Four complete Python shards¶
Full Python qualification uses four runners with two xdist workers each:
--splits 4 --group N --splitting-algorithm least_duration. It still partitions
the whole collection, excluding only the separately executed Stage2c marker.
No tests are removed. Without timing history the splitter uses equal weights;
four-way parallelism is not a claim of perfect duration balancing.
The aggregate requires every shard to succeed and all four coverage files to exist before combining them. The existing full-suite coverage floor remains. No Python coverage artifact or Sonar run is manufactured when Python is exempt.
全量 Python 从 2 个分片扩大到 4 个,每片仍为 2 个 worker,不提高单机进程争抢。 真实 pytest-split/xdist/coverage 回归覆盖分片集合互斥、并集完整、四份报告合并以及 缺失任意报告时拒绝通过。分片增加会增加安装开销与同时占用的 runner;应看实际 critical path 和 runner-minutes,而不是宣称“4 片必然快一倍”。
Override and evidence¶
Add the ci:full PR label to force full qualification. Label addition/removal
reruns the workflow. Manually dispatching Python Tests also runs full. The label
can only add checks, never waive them. Main retains full qualification.
The ci-impact-plan artifact and job summary report exact revisions, change kind,
per-job execution flags, reason and coverage scope. The merge gate requires
success for required jobs and an explicit skip for exempt ones; failure,
cancellation, missing outputs, contradictory flags or unexpected skips fail.
Stage2c retains all correctness cases: its E2E lane uses two runners with two workers each, while mutants and installed-package lanes remain separate. The small pytest plugin assigns whole modules using deterministic largest-first test-count balancing and retains collection order within each module. It does not split a stateful module across machines or workers. This is not timing-based optimal scheduling: one very large module can still dominate a shard.
Stage2c E2E 从单 runner 的 4 个 worker 改为两个 runner 各 2 个 worker;总 worker 数不增加,但不再挤在同一台机器。按完整模块分片,并保留 loadfile 与模块内顺序。 真实回归以共享状态、顺序敏感的模块验证两路并集完整且互斥,避免盲目按单测试分片。
The first implementation retains minimum-Node checks and removes the earlier vision selected-test runner, selected/full comparison machinery and its extra shadow workload. The prior shadow results remain historical evidence, not a permanent extra CI obligation.
Qualification¶
python -m unittest discover -s scripts/ci -p 'test_*.py'
python -m pytest tests/test_python_ci_workflow.py tests/test_sonarcloud_workflow.py -q
python scripts/ci/review_gate.py classify --base origin/main --head HEAD --plan impact-plan.json
python scripts/ci/review_gate.py classify --base origin/main --head HEAD --force-full --plan impact-plan.json
Use repository-supported Python/test dependencies. Keep generated plans and JUnit/coverage artifacts outside tracked source. Hosted CI must qualify the real workflow after policy changes; unit checks do not prove runner scheduling or latency. Paid model tests remain release/manual only. No Goal, automation, authority provider, runtime permission or live state is changed by this policy.