diff --git a/institutio/governance/gates.yaml b/institutio/governance/gates.yaml index 4db93ae3c..e5db4b3fb 100644 --- a/institutio/governance/gates.yaml +++ b/institutio/governance/gates.yaml @@ -473,6 +473,7 @@ gates: paths: ["cli/**"] tier: heavy serialize: true + timeout_seconds: 1500 ci_job: "pr-gate.yml:pr-gate" owner: verify note: "Env-scrubbed and no-modal: ambient persona tokens and editor configuration must not leak into test behavior. Serialized machine-wide (2026-07-15 host-thrash: two concurrent lawful verify.py runs each launched this full suite in parallel with the Backblaze crawl — the 1,200-test suite is a host-exhausting gate like the node/web estate; queueing is strictly cheaper than thrashing). -n auto is WITHIN-run xdist fan-out and orthogonal to that cross-run flock: one run at a time, that run uses the cores." @@ -481,6 +482,7 @@ gates: paths: ["web/api/**", "cli/**"] tier: heavy serialize: true + timeout_seconds: 900 ci_job: "pr-gate.yml:pr-gate" owner: verify note: "web/api imports limen — a cli change implicates the API suite too. Serialized machine-wide with pytest-cli (same 2026-07-15 rationale)." diff --git a/scripts/verify.py b/scripts/verify.py index 06e827c01..97ad65a49 100755 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -519,6 +519,12 @@ def run_gate_wave( def execute(gate_id: str) -> tuple[bool, float]: started = time.monotonic() + # A gate row may declare its own deadline (GATES registry `timeout_seconds`) — heavy + # serialized suites like pytest-cli cannot finish inside the wave default (the + # 2026-07-30 300s regression made every cli-touching PR unmergeable). The row can + # only EXTEND the wave default, never shrink it. + row_timeout = (gates[gate_id] or {}).get("timeout_seconds") + gate_deadline = max(timeout_seconds, float(row_timeout)) if row_timeout else timeout_seconds print(f"WAVE {wave_name}: START gate={gate_id}", flush=True) with output_paths[gate_id].open("w+b") as output: try: @@ -528,7 +534,7 @@ def execute(gate_id: str) -> tuple[bool, float]: registry, changed, output=output, - deadline=started + timeout_seconds, + deadline=started + gate_deadline, output_limit_bytes=output_limit_bytes, cancel_event=cancel_event, )