Skip to content

fix(ci): stop the live vNEXT gate turning main and every PR red - #678

Merged
padak merged 2 commits into
mainfrom
fix/vnext-live-gate-false-red
Aug 23, 2026
Merged

fix(ci): stop the live vNEXT gate turning main and every PR red#678
padak merged 2 commits into
mainfrom
fix/vnext-live-gate-false-red

Conversation

@padak

@padak padak commented Aug 23, 2026

Copy link
Copy Markdown
Member

Symptom

main is red, and so is every open PR (a PR run tests the merge commit):

FAILED tests/test_check_version_gates.py::TestLiveRepositoryVnext::test_no_unresolved_placeholder_survives_a_release
AssertionError: unresolved vNEXT gate(s) shipped -- an agent cannot satisfy them:
  [('plugins/kbagent/skills/kbagent/references/gotchas.md', 4438)]

Verified directly against origin/main:

unresolved vNEXT placeholders on origin/main: 1
   plugins/kbagent/skills/kbagent/references/gotchas.md:4438
   ## Multi-project `job list` now merges chronologically, not grouped by project (since vNEXT)

Why it fires

The test asserts the live tree carries no (since vNEXT) placeholder. That is the opposite of the documented process.

Since #648, a feature PR that documents version-gated behaviour writes the literal vNEXT placeholder, and only the release PR rewrites it. CLAUDE.md states it outright:

make version-gate-check ignores the placeholder … Writing vNEXT in a feature PR is correct and stays green — the placeholder only becomes fatal in a version-raising PR.

And TestReleaseModeSelection, added by the very same PR as this assertion, spells out the reasoning:

arming there would demand a contributor delete a placeholder the process requires them to write

So main legitimately carries placeholders for most of a release cycle. The assertion was a time bomb: #670 landed a few days after 0.90.0 had rewritten every placeholder, so it passed on an empty tree. #675 added the first placeholder of the next cycle and detonated it.

The CI step is correctly gated — it passes --release-if-newer-than "$base" and arms only on a version-raising PR. Only the pytest mirror is ungated, because a unit test cannot see the base branch's version.

The change

Drop the false invariant; keep the enforcement where it can actually see the base version (the ci.yml step and make vnext-check).

Replaced with the half that does have a stable answer: every gate the live scanner reports must point at a real line that really contains the placeholder. Zero hits and ten hits are both valid depending on where in the release cycle the tree sits. The neighbouring test_prose_mentions_are_still_present_and_ignored already guards against the globs silently matching nothing.

Verification

  • make check green on this branch — 6077 passed, 12 skipped
  • The replacement test exercises a non-empty result today (main carries one placeholder), so it is not passing vacuously

Scope

Found while working on #676 (CI cost). Split out deliberately: this is unrelated to that change, blocks every open PR, and should merge on its own.


Open in Devin Review

`TestLiveRepositoryVnext::test_no_unresolved_placeholder_survives_a_release`
asserted that the live tree carries no `(since vNEXT)` placeholder. That
is not an invariant of this repo -- it is the opposite of the documented
process.

Since #648, a feature PR that documents version-gated behaviour writes
the literal `vNEXT` placeholder and only the release PR rewrites it.
CLAUDE.md says so directly ("Writing `vNEXT` in a feature PR is correct
and stays green"), and TestReleaseModeSelection, added by the same PR as
this assertion, explains that arming the gate outside a release PR
"would demand a contributor delete a placeholder the process requires
them to write".

So main legitimately carries placeholders for most of a release cycle.
The assertion was green only because #670 landed days after 0.90.0 had
just rewritten every one of them. #675 added the first placeholder of
the next cycle and the assertion went red -- on main, and on every open
PR, since a PR run tests the merge commit.

The release-time requirement itself is real and stays enforced where it
can see the base branch's version: the "Unresolved vNEXT placeholder
check" step in ci.yml (`--release-if-newer-than`) and its local twin
`make vnext-check`. A unit test cannot see that version, so it cannot
make this call.

What a test CAN assert is that the live scan works, and that replaces
it: every gate the scanner reports must point at a real line that really
contains the placeholder. Zero hits and ten hits are both valid answers
depending on where in the cycle the tree sits. The neighbouring
"guards the guard" test already covers the globs resolving at all.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread tests/test_check_version_gates.py Outdated
`VnextResidue.path` is repo-root-relative -- find_vnext_residue stores
`path.relative_to(REPO_ROOT).as_posix()` -- so reading it back as a bare
`Path(gate.path)` resolves against the current working directory. The
loop body only executes when the tree actually carries a placeholder,
which is precisely the state main is in now, so running pytest from
anywhere but the repo root raised FileNotFoundError.

Reproduced from tests/ before the change and confirmed green after, from
both the repo root and a subdirectory.

`REPO_ROOT / gate.path` also covers the one fallback branch, where a path
outside the repo is stored absolute: joining an absolute right-hand side
discards the left, yielding that path unchanged.

Raised by Devin review on #678.
@padak
padak merged commit 763c303 into main Aug 23, 2026
4 checks passed
@padak
padak deleted the fix/vnext-live-gate-false-red branch August 23, 2026 23:10
@padak padak mentioned this pull request Aug 23, 2026
13 tasks
padak added a commit that referenced this pull request Aug 23, 2026
Batches the nine PRs merged since v0.90.0 (#670, #671, #672, #673, #674, #675, #676, #677, #678) into one version bump and one changelog entry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant