Skip to content

Agent-runtime boundary gate keys violations on line number, so unrelated line shifts redden it — main is stale 6h after #6462 re-baselined, with zero change to the violation set #6525

Description

@M3gA-Mind

Summary

The agent-runtime ownership boundary gate keys each baselined violation on its line number, so an edit that merely shifts lines in a file containing a violation reddens the gate — reporting the same code as both a new "unbaselined violation" and a "stale baseline entry". Main is red on this right now, one day after #6462 re-baselined it, with zero actual change to the set of violations.

Proof: the violation set is identical, only lines moved

Regenerating the baseline from current main (2c579afc6) and comparing against the committed one:

baseline entries: 213   current findings: 213
differ when line INCLUDED : 5 pairs
differ when line EXCLUDED : 0

Zero difference once the line number is excluded. Same rules, same paths, same source text, same occurrence counts. Examples of entries whose only change is the line:

lifecycle.rs:        210 -> 70    let inherited_origin = crate::agent::turn_origin::capture();
runtime_session.rs: 1420 -> 1383  request_id: crate::agent::turn_origin::current_request_id(),
agent_chat.rs:       212 -> 197   if let Some(tx) = crate::agent::progress_sink::current_progress_sink() {
system_turn.rs:       88 -> 87    let result = with_origin(origin, agent.run_single(prompt))
factory.rs:         1198 -> 1206  let root = crate::agent::turn_workspace::current()?;

That is why the failure output lists the same lines on both sides — every "unbaselined violation" is also a "stale baseline entry".

Mechanism

scripts/ci/check-agent-runtime-boundary.mjs:341:

// Physical source locations are part of the temporary debt contract: a
// moved violation is stale debt, not a silently accepted occurrence.
const base = `${rule}\0${path}\0${line}\0${text}`;

Membership is then exact-JSON set comparison (:365-367), so a one-line shift is indistinguishable from "old violation deleted + new violation added".

The comment shows this is deliberate, and the intent is sound — a violation that moved should not be waved through unexamined. The cost may not have been weighed: the trigger is not "the violation changed", it is "any line above it changed". A PR that adds an import to agent_chat.rs inherits a red gate for seven violations it never touched.

Why this is worth fixing rather than re-baselining again

Re-baselining is not durable, and the history shows the treadmill:

commit date
180bec2f0 2026-09-22 ci: refresh agent runtime boundary baseline
656c80e58 2026-09-23 07:09Z ci: re-baseline the agent-runtime ownership boundary (#6462)
2026-09-23 13:00Z stale again

Under six hours. Each refresh is a commit that reviews as "no functional change" and is therefore rubber-stamped, which is the review posture you least want on the file that defines a boundary.

It is currently invisible on main, which makes it worse

Rust Quality (fmt, clippy) is skipped on main's own pushes (changed-area gating). CI Lite on 2c579afc6: 4 success, 9 skipped, one unrelated frontend failure. So the gate is red but unexercised on main, and the next Rust-touching PR is the one that wears it — it looks like that PR's fault. This is the same dynamic as #6451 and #6486: breakage that accumulates behind a lane that does not run.

Two further gates are in the same state on 2c579afc6 and are worth separating from this one:

Solution (optional)

Keep the intent, drop the line from the identity. Options, cheapest first:

  1. Key on rule\0path\0text\0occurrence and carry line as advisory metadata, refreshed silently. A genuinely new violation still fails; a pure move does not. The "moved violation" concern is largely served by occurrence already.
  2. Key on line but report a move as a distinct, non-failing class ("N violations moved; baseline refreshed"), failing only on added/removed.
  3. If physical location must stay load-bearing, add --refresh-lines that rewrites only line numbers for otherwise-identical entries, so the routine case is mechanical and a real change still needs review.

I'd take (1): it makes the gate fail on what it is named for — the ownership boundary changing — rather than on unrelated churn.

Acceptance criteria

  • A pure line shift, with the violation set otherwise unchanged, does not fail the gate.
  • A newly added violation still fails, and a removed one is still reported as stale — covered by a test that would pass today and must keep passing.
  • main green on the boundary gate without a fresh re-baseline commit.
  • A note on whether the gate should run on main's pushes at all, given it is currently gated off there.

Related

#6462 (the re-baseline this outlived by six hours), #6451 (failing step hides later steps), #6486 (same lane, same invisibility), #6310 (the layout gate's pinned limits).

Found while separating inherited red from my own on #6517/#6488 — both are comment-only or test-only and reproduce this failure byte-identically against a pristine main tree.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p1Next. Wrong behaviour a user will hit, or a security weakness behind a condition.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions