Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

A push runs what CI would find first, and CI decides

A push runs what CI would find first, and CI decides

majordomus://rule/project.a-push-runs-what-ci-would-find-first@2aktivní ciproces

odkazuje na něj

Nic ve vrstvě to nejmenuje. Zpětné odkazy se odvozují, takže prázdný seznam je odpověď, ne opomenutí.

Zdůvodnění

Dne 2026-10-09 CI dvakrát odmítlo release 0.19.0, pokaždé kvůli něčemu, co lokální běh najde za pár sekund. Prvním byla strukturní kontrola, economics-claims, za 6 s a always: true. Druhým případ sady, 08, za 1 s. Ani jedno před pushem neběželo. Pre-push hook spustil finish --check, který hlásí požadované kontroly jako nikdy nenahlášené a žádnou z nich nespouští, a případy se vybíraly odhadem. Každé odmítnutí stálo okruh přes CI delší než hodinu, pak další derive za zámkem stroje, a to u jediné změny, na kterou vlastník čekal.

Celá úloha structure odpovědí není. Trvá asi 20 minut, sahá na API GitHubu a z jednoho stroje pushuje devět relací. Co push dluží, je ta část CI, která je levná, lokální a jistě selže stejným způsobem, vybraná podle toho, co CI měřilo.

Version 1 refused the push on every failed gate, and on a loaded machine that made the hook the slowest part of the work: on 2026-10-20 a push of a rescue ref spent 3490 s in the step at load 70 to 90, and a commit hook started a cold cargo build. On 2026-10-21 the owner relaxed the cooperation model (rule project.the-cooperation-model-is-the-owners-word, version 2, I3824): local gates are informative and CI holds the verdict. A finding CI will reach again is therefore reported here, not refused (I3830). A check CI cannot reach, or reaches only after a merge or a deploy it would break, still refuses: it takes seconds and nothing else would say it.

Požadované chování

  • .githooks/pre-push calls scripts/ci/run-plan --before-push after finish --check. The policy declares it (enforcement: structure-gates-on-push, wired by git-hook:pre-push), so doctor finds a clone whose hook stops calling it: the commit hook reports that finding and CI's core-check, which runs doctor again, refuses it.
  • The step computes the push's plan, as CI does, from the commits the push sends: the merge base up to HEAD (scripts/ci-plan --head HEAD), never the working tree. An untracked file is not a change a push carries; on 2026-10-22 git's .merge_file_* temporaries, left at a checkout's root by an interrupted merge, put a push that only deleted remote refs into the full plan for more than 15 minutes (#2372). The step refuses the push (exit 12) when the plan cannot be computed. scripts/ci-plan refuses a base or head that names no commit. It used to pipe a failing git diff into sort, whose status hid the failure, and so returned a plan computed from nothing with exit 0.
  • Kontroly. Spouští vybrané strukturní kontroly plánu, které nejsou v network: true označeny .ai/repo/ci/gates.yaml a jejichž zaznamenané sekundy nejsou víc než MJ_PUSH_GATE_SECONDS (výchozí 15). Sekundy pocházejí z .ai/repo/ci/structure-durations.tsv, které scripts/ci-baseline --structure-durations zapisuje z artefaktů ci-metrics-structure, jež CI nahrává. Bere je od nejlevnější, dokud jejich součet zůstává v MJ_PUSH_GATE_BUDGET (výchozí 120).
  • Skipped gates. Every gate left out prints one line naming it and why: it reaches the network, it has no recorded duration, it is over the per-gate limit, or it is past the budget. A missing durations file refuses the push (exit 12).
  • Případy. Spouští případy, které .ai/repo/ci/suite-durations.tsv zaznamenal nejvýše MJ_PUSH_CASE_SECONDS (výchozí 5), po čtyřech zároveň. Jmenovitě vynechává případ, který deklaruje majordomus-exclusive nebo spouští server (serve_up, mcp_shared, serve ensure|start, launcher MCP). Rychlé je to, co zaznamenalo CI. Případ se serverem měří časování a porty a na stroji, který sdílí devět relací, selže kvůli zátěži, ne kvůli změně: pět jich tak selhalo při prvním běhu.
  • Bound. It reports its measured time against MJ_PUSH_BOUND (default 180). An overrun names the slowest steps and never refuses the push: a busy machine must not fail it, or people route around the step.
  • Verdict. A failed gate or case exits 1 with the tail of its output and a last line that names it and says CI holds the verdict. The hook prints reported, not refused: CI holds the verdict and lets the push through; CI's validate refuses the same head. Any other non-zero exit of the step, 12 above all, refuses the push: what cannot be measured is not passed.
  • Stdin. Každá kontrola a každý případ běží se zavřeným stdin. Stdin hooku je seznam refů. test/run.sh dal každému případu stdin runneru, protože úloha na pozadí pod řízením úloh si jej ponechává, takže případ, který četl stdin, čekal věčně na otevřené rouře: případ 54, 39 minut, téhož dne.
  • Deletions. A push whose every ref has an all-zero local sha carries no commit, so the hook exits 0 before finish --check and the plan, as it does for refs/majordomus/* (I4008: 16 deletions waited 2400 s on the build lock, 2026-10-22); one ref that carries a commit and the whole hook applies.

What refuses and what reports

HookKontrolaLocal verdictProč
pre-pushbin/majordomus finish --checkrefusesthe task's scope and contract exist only on this machine
pre-pushscripts/case-numbers checkrefuseseach branch is clean alone; the pair exists only after a merge
pre-pushscripts/ci/run-plan --before-push, exit 12refusesa plan that cannot be computed is not a pass
pre-pushscripts/ci/run-plan --before-push, exit 1reportsCI's structure job and suite run the same gates and cases
pre-pushscripts/rust-check --docreportsCI's rustdoc job refuses the same head
pre-commitbin/majordomus doctorreportsCI's core-check runs doctor and refuses
pre-commitbin/majordomus-cli worktree guardrefusesCI checks out a fresh clone and never sees which worktree a commit came from (rule project.worktree-topology)
pre-commitscripts/pages currentrefusesa stale derive breaks the deploy for whoever lands next
pre-commitscripts/ci/providers-check --permissions-onlyrefusesthe owner-authorized SSH permissions of every native client

A reported finding prints one line on stderr, <hook>: <check> failed (exit <n>); reported, not refused: CI holds the verdict, after the check's own output. The hooks carry the report function themselves; there is no sourced helper.

Chování při selhání

A refusing check exits the hook with its own code, naming what failed. A reporting check never changes the hook's exit. There is no flag that skips any step, as there is no --no-verify.

Ověření

test/cases/1021_a_push_runs_what_ci_would_find_first.sh řídí krok nad plánem a trváními, které zapisuje. Dokazuje:

  • a cheap gate runs, and a cheap failing gate exits 1 with its output and a line that names it and says CI holds the verdict;
  • každý druh vynechané kontroly je jmenován s důvodem: síť, žádné zaznamenané trvání, přes limit na kontrolu a za rozpočtem;
  • a missing durations file, or a plan that cannot be computed (an unknown base), exits 12;
  • hook volá krok, politika deklaruje vynucování a plán nese síťový příznak modelu;
  • případ, který čte stdin v rouře, jež se nikdy nezavře, už runner nezablokuje.

test/cases/4008_a_push_that_only_deletes_plans_nothing.sh: a deletion-only push runs no finish, case-numbers or run-plan, and a mixed push still runs all three.

test/cases/3948_a_local_gate_reports_and_ci_decides.sh runs the real hooks in a fixture whose checks are stubs with chosen exit codes. It proves:

  • a push whose step exits 1 exits 0, with the gate's line and the hook's report line;
  • a push whose step exits 12, whose finish --check fails or whose case numbers collide is refused with that code;
  • a push that changes the crate and whose rustdoc fails exits 0 with a report line;
  • a commit whose doctor fails exits 0 with a report line, and one whose pages current, worktree guard or SSH permissions check fails is refused with that code;
  • each call is still on a line doctor's wiring check matches.

První běh kroku na vlastní branchi tu branch odmítl kvůli nepřipnutému sort (order-check), dřív než ji viděla jakákoli CI.

Odkud to pochází

kanonický soubor
.ai/repo/rules/project/a-push-runs-what-ci-would-find-first.v2.md
identity
project.a-push-runs-what-ci-would-find-first@2
dostupné také jako
Zdroj MCP majordomus://rule/project.a-push-runs-what-ci-would-find-first@2 · majordomus entity show rule/project-a-push-runs-what-ci-would-find-first-2 · GET /api/v1/entity?uri=majordomus://rule/project.a-push-runs-what-ci-would-find-first@2
v Cockpitu
/cockpit/objects/rule/project-a-push-runs-what-ci-would-find-first-2

Tato stránka je generována z výše uvedeného souboru pomocí scripts/generate-site-data; úprava stránky nic nemění, úprava souboru změní všechna rozhraní. Výše uvedené vztahy jsou hrany docs/generated/graph.json, které spustitelný program zapisuje ze stejného indexu.

Prohledává názvy a popisy všech stránek, které tento web publikuje.