Skip to content

fix(source-control): accept Refs: markers and block negated closers in PR-body gates (#4183) - #4636

Merged
cursor[bot] merged 4 commits into
mainfrom
cursor/4183-linkage-refs-negated-37e9
Sep 27, 2026
Merged

cursor[bot] merged 4 commits into
mainfrom
cursor/4183-linkage-refs-negated-37e9

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Closes #4183

Summary

Local PR-body linkage gates drifted from pr-contract (ci-workflows#544). They blocked Refs: #N (CI accepts) and passed negated closers like does not close #N (CI fails; GitHub still closes). Gates now match CI both ways.

Fix

  • pr-linkage-validator.sh: per-line scan_linkage matching CI; tab/t mask fix.
  • Gate headers name Refs: #<issue> and the negated-closer rule.
  • source-control → 0.61.3 (renumbered above main’s 0.61.1 / 0.61.2 after merges).

Verification

  • ci-workflows pr-contract/run.sh at pin; body-gate / MCP-gate / spawn-budget / differential oracle (see /opt/cursor/artifacts/pr-4183.md).

Related

Open in Web Open in Cursor 

cursoragent and others added 3 commits September 27, 2026 20:54
…n the PR-body linkage gates

The local linkage validator recognized two linkage states while the
pr-contract step it mirrors (melodic-software/ci-workflows#544) recognizes
three, and fails negated closing references that the local gates passed.

- pr-linkage-validator.sh: per-line scan transcribed from pr-contract's
  scan_line and negation_trigger. A `Refs:`/`Relates to:` marker on its own
  line counts as linkage; a closing keyword with a disclaimer word among the
  five words before it is a negated closing reference and blocks even
  beside valid linkage. Messages use CI's wording.
- mask_markdown_code_to: `\t` in a bash regex is a literal `t`, so lines
  starting with `t` were masked as code and tab-indented lines were not.
- Both gates' header and remedy text name the Refs: marker.
- source-control 0.61.0 -> 0.61.1.

Closes #4183

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
#4622

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
# Conflicts:
#	plugins/source-control/.claude-plugin/plugin.json
#	plugins/source-control/CHANGELOG.md

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
@cursor
cursor Bot marked this pull request as ready for review September 27, 2026 21:10
…r source-control to 0.61.3

# Conflicts:
#	plugins/source-control/CHANGELOG.md

Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
@cursor
cursor Bot merged commit 354c67d into main Sep 27, 2026
23 checks passed
@cursor
cursor Bot deleted the cursor/4183-linkage-refs-negated-37e9 branch September 27, 2026 22:01
kyle-sexton added a commit to melodic-software/standards that referenced this pull request Sep 28, 2026
…ockstep-drift (#634)

Closes #633

## Summary

`pr-convention-lockstep` failed on every open PR with `drift: hook
validator: KEYWORD_ERE / NO_ISSUE_ERE declarations not found`.
melodic-software/claude-code-plugins#4636 rewrote the hook validator
around a per-line `scan_linkage` and renamed its closing pattern to
`CLOSING_ERE`, so `parseValidatorPatterns` could not find it. The
validator and the ci-workflows `pr-contract` composite still agree, so
this was a parse failure, not drift.

## Fix

- `parseValidatorPatterns` reads `CLOSING_ERE` (plus the unchanged
`NO_ISSUE_ERE`) and translates `[[:blank:]]` as well as `[[:space:]]`.
- The new EREs are lowercase with no `i` flag, matched against
`${line,,}`. The parser now asserts that lowercasing is present and the
probes lowercase their input, the same way the composite check already
asserts `lower = tolower(line)`.
- The test fixture takes the new validator shape; a new test fails when
the validator stops lowercasing.
- `policy.json` is unchanged. Every closing keyword and no-issue marker
it lists is still accepted by both the composite (`run.sh` `scan_line`
and the `no-issue` test) and the validator. The new `Refs:` / `Relates
to:` acceptance and negated-closer rejection are enforced by both, but
`policy.json` has no field for them and `pr-convention-policy.mjs` and
the pinned reusables do not implement them, so recording them would be a
separate change.

## Verification

- `npm run test:pr-convention-lockstep`: 40/40 pass.
- `npm run test:pr-convention-policy`: 11/11 pass.
- `npm run lint:pr-convention-lockstep` against live sources with a
token: `pr-convention lockstep: all copies and consumer pins match
policy.json`, exit 0.
- `biome check` on both touched files: clean.

## Related

- melodic-software/claude-code-plugins#4636 (the validator rewrite)
- melodic-software/ci-workflows#544 (the `pr-contract` negation and
`Refs:` change the validator mirrors)
- Unblocks #628, #630, #631, #632

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01LCEBhuXxZAT8K619tC6T5f

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

fix(source-control): PR-body linkage gates reject Refs: #N that CI accepts, and pass negated closers CI rejects (post ci-workflows#544 drift)

2 participants