Rust layout gate: main is one line from red (two files at exactly 750, one legacy pin at 0), no warning band, and two gaps in the gate
Summary
Two files under crates/openhuman-core/src sit at exactly 750 lines on main 2d582bdea, and one LEGACY_LIMITS file is at zero margin. The gate fails on > limit, so any PR that adds a single line to one of those files turns main red. The gate also has no warning band — it only ever fails — so an author learns about a breach at merge time, which is exactly how main went red twice on 2026-09-15 (#6301, #6307, and the enforcement gap in #6308).
Counting method, so the numbers are reproducible: git grep -c '' 2d582bdea -- 'crates/openhuman-core/src/*.rs'. This matches the gate's own expression at line 54, source.split("\n").length - (source.endsWith("\n") ? 1 : 0), for newline-terminated files; every file listed here ends with a newline, and I re-counted the top entries with git show <rev>:<path> | wc -l as a second method. The threshold at line 57 is lineCount > (legacyLimit ?? LINE_LIMIT), i.e. 750 passes and 751 fails.
1. The margin: main is one line from red
Files under crates/openhuman-core/src at 740+ lines, at 2d582bdea:
| lines | file | headroom |
|---|---|---|
| 750 | flows/ops_agent_binding_tests.rs |
0 |
| 750 | agent/multimodal.rs |
0 |
| 749 | agent/prompts/sections.rs |
1 |
| 746 | agent/harness/session/turn/core_turn.rs |
4 |
| 742 | integrations/test_support_backend.rs |
8 |
| 742 | agent/tinyagents/middleware_wrap_up_toc_tests.rs |
8 |
| 741 | inference/provider/factory_crate_native_tests.rs |
9 |
| 741 | agent/harness/subagent_runner/ops/graph_tests.rs |
9 |
| 740 | agent/orchestration/tools/spawn_async_subagent_execute.rs |
10 |
The four LEGACY_LIMITS files are tighter still (current / pinned):
| file | current | pinned | headroom |
|---|---|---|---|
tools/ops.rs |
1502 | 1502 | 0 |
agent/harness/subagent_runner/ops/runner.rs |
1768 | 1769 | 1 |
agent/harness/session/builder/factory.rs |
1549 | 1552 | 3 |
web_chat/progress_bridge.rs |
1542 | 1547 | 5 |
Any PR touching one of these — including adding a test to a *_tests.rs sibling — breaks main for everyone until it is fixed. That is not hypothetical: it happened twice on 2026-09-15, and each red main blocked every open PR rebased onto it.
2. No warning band: an author only finds out at merge time
The script has exactly two outcomes: it pushes to failures and exits 1, or it prints "passed". There is no output for a file approaching the limit, so a PR that takes a file from 740 to 750 is indistinguishable from one that leaves it at 100. The author gets no signal, and the next person to add a line inherits a red main they did not cause.
Both breaches that night were files that crossed while nobody was watching the margin:
harness_assembly.rsreached 751 when #6288 (730) and #6298 (734) merged next to each other, neither over on its own head — fixed in #6301.skills/catalog/ops.rswent 740 → 752 on #6292's final push — fixed in #6307.
A warn band (say, at 725) is a few lines in scripts/ci/check-openhuman-rust-layout.mjs: collect near-limit files into a separate list and console.warn them without failing. That turns the class of failure from "discovered on main" into "visible in your own PR's log".
3. Two gaps in the gate itself
Scope. The line-limit loop runs only over ROOT = crates/openhuman-core/src, and its skip list ["api", "bin", "core", "lib.rs", "main.rs", "rpc"] is guarded by directory === ROOT, so those names are pruned only at the top level. Consequence: crates/openhuman-core/src/core/observability.rs is 3714 lines and entirely unenforced, as are everything else under src/core/, src/api/ and src/rpc/, plus every other crate (openhuman-app/src/lib.rs is 3731). The naming and inline-test-module checks do run repo-wide over crates/, so the asymmetry is in the line limit alone. Either the skip list should shrink or the exemption should be explicit and pinned like LEGACY_LIMITS, rather than being a side effect of directory position.
No ratchet. The only check on LEGACY_LIMITS is:
for (const file of LEGACY_LIMITS.keys()) {
if (!fs.existsSync(file))
failures.push(`${file}: stale legacy exception; remove it from the gate`);
}
It flags an entry only when its file no longer exists. The gate's own comment says these files "cannot grow, no new exception can appear, and deleting an entry is the only way to relax it" — but nothing lowers a pin when a file shrinks, so a file that drops well below its pin silently regains headroom the comment says it should not have.
Deliberately not proposed
Tightening the four legacy pins to their current sizes. tools/ops.rs is already at 0 and factory.rs at 3, so it would buy almost nothing while making those files unmodifiable. The real fix there is extraction, as in #6301 and #6307, when that work is scheduled.
Related
- #6301 —
harness_assembly.rs751 → 611 by extracting the context ladder - #6307 —
skills/catalog/ops.rs752 → 633 by extracting the URL-derivation family - #6308 — the required check
PR CI Gatenot blocking merges, which let both breaches reachmain
Source: tinyhumansai/openhuman