From aeaedfcdcc2ff367c78605a71626f3082d953dd9 Mon Sep 17 00:00:00 2001 From: Anthony James Padavano Date: Thu, 30 Jul 2026 13:29:20 -0400 Subject: [PATCH] =?UTF-8?q?heal(verify):=20registry-declared=20gate=20dead?= =?UTF-8?q?lines=20=E2=80=94=20pytest=20gates=20outlive=20the=20300s=20wav?= =?UTF-8?q?e=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1666's parallel runner capped every gate at 300s; the 1,200-test pytest-cli suite cannot finish in five minutes, so every cli-touching PR became unmergeable (two merge groups + one PR head died on gate-command-timeout within the hour). A gate row may now declare timeout_seconds (GATES registry — one entry per fact); the row can only EXTEND the wave default, never shrink it. pytest-cli: 1500s, pytest-api: 900s. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VHjMkFUZJ1pK21oyv1ropN --- institutio/governance/gates.yaml | 2 ++ scripts/verify.py | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) 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, )