Skip to content

I3242 — The pull-request critical path has a committed GitHub baseline and a budget per required job, and a run's summary names its critical path and every cache state

First commit a GitHub baseline window of validate runs through scripts/ci-baseline, warm, partial and cold apart, and derive from it a budget per required pull-request job that sums to 300 s on the critical path, naming every job over its share. Extend integration.timings to p50, p90 and p95 over a declared window of past runs with queue wait reported apart, and have the /ui CI/CD timings panel draw the same values. Extend scripts/ci/summary with sccache statistics, the docker-image job's cache state and the run's critical path across jobs, each value read from the run and none typed in.

BLOCKED wave 5 · p2 · implementation profile · parallel safe

Part of a-change-is-judged-in-minutes — A change is derived in under a second and judged in minutes, and nothing that could have changed is skipped.

Blocked. This issue cannot start until I2350 is done. The status is derived from that, not declared.

Objective

First commit a GitHub baseline window of validate runs through scripts/ci-baseline, warm, partial and cold apart, and derive from it a budget per required pull-request job that sums to 300 s on the critical path, naming every job over its share. Extend integration.timings to p50, p90 and p95 over a declared window of past runs with queue wait reported apart, and have the /ui CI/CD timings panel draw the same values. Extend scripts/ci/summary with sccache statistics, the docker-image job's cache state and the run's critical path across jobs, each value read from the run and none typed in.

Why

c195#2: warm, partial and cold must be reported apart, with GitHub timings, not local ones, as the evidence. It extends milestone ci-critical-path. Proposed in ADR 0186 (A pull request's required verdict is the feedback lane, a gate whose inputs did not change is reused as inputs_unchanged, and the proof lane judges the combined top before it lands) (proposed; it carries no authority until the owner accepts it). Sources: chatgpt-majordomus:c195#2.

Current state

Verified on master 707a04c, 2026-10-18: scripts/ci/summary records `rust cache hit` and `npm cache hit` facts. integration.timings reports, per check, the median, 90th percentile and longest run over the open pull requests' last recorded observation; it has no p95, no window of past runs, and counts queued runs as unmeasured. The image's builder stages run `sccache --show-stats` (deploy/Dockerfile, rendered by deploy/render.rs). .ai/repo/ci/baseline.json exists but no per-job budget is derived from it.

Desired state

Every run says warm, partial or cold per cache; a regression of the critical path past its budget fails a gate that names the job and step; and the CI/CD screen draws the same window integration.timings reports.

Scope

  • scripts/ci/summary
  • .github/workflows/validate.yml
  • .github/workflows/docker-image.yml
  • scripts/ci-baseline
  • .ai/repo/ci/baseline.json
  • apps/majordomus-cli/src/capability/builtin/integration.rs
  • apps/majordomus-cli/src/ui/timings.rs
  • test/cases/1077_ci_timings_are_measured.sh
  • test/cases/413_a_skipped_case_is_not_a_proof.sh
  • .ai/repo/project/intents
  • apps/majordomus-cli/src/integration/timings.rs
  • apps/majordomus-cli/src/integration/forge.rs
  • apps/majordomus-cli/src/integration/model.rs
  • apps/majordomus-cli/src/integration/tests.rs

Out of scope

  • A second observability store (c255#6 forbids a parallel platform)
  • Changing which checks a pull request requires: the required set is I2350's gate model, and the full suite still proves a combined top and a release
  • Excluding queue wait from the owner's figure before the owner answers the 300 s target question

Dependencies

What waits on this

Acceptance criteria

  • A run with no sccache stats reports 'unknown', never zero
  • The critical path names the jobs that made it
  • A GitHub baseline window of validate runs, warm, partial and cold apart, is committed through scripts/ci-baseline before I3238, I3239, I3240 or I3241 changes the workflow
  • A budget for each required pull-request job is derived from the baseline and sums to 300 s on the critical path. Every required job over its share is named, and an issue is filed for it from the measurement
  • A pull-request critical path that regresses past its noise-aware budget fails a gate that names the job and step
  • integration.timings reports p50, p90 and p95 over a declared window of past runs, with queue wait measured and reported apart instead of counted as unmeasured, and the /ui CI/CD timings panel draws the same values
  • Validation runs 1077_ci_timings_are_measured, 413_a_skipped_case_is_not_a_proof and the run_summary_cache_states case this issue adds, replacing the placeholder
  • Criterion pr-verdict-within-five-minutes of intent a-change-is-judged-in-minutes becomes evidence: test with a ref to this issue's window case

Validation

  • bash test/run.sh 1077_ci_timings_are_measured 413_a_skipped_case_is_not_a_proof

Evidence required

  • run_summary_cache_states_case
  • ci_timings_window_case
  • per_job_budget_gate_case
  • github_baseline_window_committed

Evidence

None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.

Timeline

started
—
verified
—
completed
—

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I3242.yaml. Read it back with majordomus plan show I3242.

Searches the titles and descriptions of every page this site publishes.