Remove linked-issue gate from commitperclip (#7423)

## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - The `commitperclip` PR quality gates enforce hygiene on every PR
before merge
> - One of those gates required PRs to link to a tracking issue, which
adds friction for small/internal changes that don't need a tracker entry
> - The repository owner decided the linked-issue requirement is no
longer the right default
> - This pull request removes the linked-issue gate (the script, its
tests, and the orchestrator wiring)
> - The benefit is fewer false-failing PR checks and one less mandatory
authoring step

## What Changed

- Deleted `.github/scripts/check-pr-linked-issue.mjs`
- Deleted `.github/scripts/tests/check-pr-linked-issue.test.mjs`
- Removed the `checkLinkedIssue` import, the
`Promise.resolve(checkLinkedIssue(...))` entry in the `Promise.all`
block, the `issueResult` destructured binding, and the
`...issueResult.failures` spread from
`.github/scripts/run-quality-gates.mjs`

## Verification

- `node --test .github/scripts/tests/*.test.mjs` — 72/72 tests pass
across the remaining 4 gate suites
- `git grep -n
'check-pr-linked-issue\|checkLinkedIssue\|check-pr-linked'` — no matches
- Inspected `run-quality-gates.mjs` — no orphaned `issueResult`
references

## Risks

- Low risk. Pure removal of one optional gate; the
`.github/workflows/commitperclip-review.yml` workflow only invokes the
orchestrator and needs no changes. PR template and `CONTRIBUTING.md` do
not mention linked issues, so no docs change is required.

## Model Used

- Claude (Anthropic), `claude-opus-4-7`, extended-thinking mode, tool
use enabled

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable (existing
gate-suite tests still pass; removed gate's tests deleted with it)
- [x] If this change affects the UI, I have included before/after
screenshots (n/a — CI script change)
- [x] I have updated relevant documentation to reflect my changes (no
docs reference the removed gate)
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin Foley 2026-06-02 17:12:41 -07:00 committed by GitHub
parent d58a862549
commit 68401f82f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 1 additions and 168 deletions

View file

@ -1,111 +0,0 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { checkLinkedIssue } from '../check-pr-linked-issue.mjs';
// Existing tests with title parameter added (defaults to no prefix, so still required)
test('passes with bare #NNN reference', () => {
assert.equal(checkLinkedIssue('This fixes the bug in #123', 'fix: something').passed, true);
});
test('passes with "Fixes #NNN"', () => {
assert.equal(checkLinkedIssue('Fixes #456\n\nSome description', 'fix: something').passed, true);
});
test('passes with "Closes #NNN" (case-insensitive)', () => {
assert.equal(checkLinkedIssue('closes #789', 'fix: something').passed, true);
});
test('passes with "Resolves #NNN"', () => {
assert.equal(checkLinkedIssue('Resolves #101', 'fix: something').passed, true);
});
test('passes with full github.com URL', () => {
assert.equal(
checkLinkedIssue('See https://github.com/paperclipai/paperclip/issues/202', 'fix: bug').passed,
true
);
});
test('passes with a full github.com URL followed by punctuation', () => {
assert.equal(
checkLinkedIssue('See (https://github.com/paperclipai/paperclip/issues/202).', 'fix: bug').passed,
true
);
});
test('fails with empty body when no skip prefix', () => {
const result = checkLinkedIssue('', 'fix: bug');
assert.equal(result.passed, false);
assert.ok(result.failures.length > 0);
});
test('fails with no issue reference when no skip prefix', () => {
const result = checkLinkedIssue('Added a cool feature, no issue linked', 'feat: something');
assert.equal(result.passed, false);
assert.ok(result.failures[0].includes('Fixes #NNN'));
});
test('fails with cross-repo issue reference', () => {
const result = checkLinkedIssue('See https://github.com/other/repo/issues/123', 'fix: bug');
assert.equal(result.passed, false);
});
test('fails when the Paperclip issue URL is embedded inside another host', () => {
const result = checkLinkedIssue(
'See https://evil.example/https://github.com/paperclipai/paperclip/issues/123',
'fix: bug'
);
assert.equal(result.passed, false);
});
test('fails when the Paperclip issue URL continues into another host', () => {
const result = checkLinkedIssue(
'See https://github.com/paperclipai/paperclip/issues/123.evil.example',
'fix: bug'
);
assert.equal(result.passed, false);
});
test('fails when #NNN is part of a word (no space before)', () => {
const result = checkLinkedIssue('This is version#123 not an issue link', 'fix: bug');
assert.equal(result.passed, false);
});
// New tests for prefix-aware skip behavior
test('skips check for docs: prefix', () => {
assert.equal(checkLinkedIssue('', 'docs: update README').passed, true);
});
test('skips check for chore: prefix', () => {
assert.equal(checkLinkedIssue('', 'chore: bump deps').passed, true);
});
test('skips check for build: prefix', () => {
assert.equal(checkLinkedIssue('', 'build: update Dockerfile').passed, true);
});
test('skips check for ci: prefix', () => {
assert.equal(checkLinkedIssue('', 'ci: add workflow').passed, true);
});
test('skips check for test: prefix', () => {
assert.equal(checkLinkedIssue('', 'test: add coverage').passed, true);
});
test('skips check with scoped prefix like docs(api):', () => {
assert.equal(checkLinkedIssue('', 'docs(api): document endpoint').passed, true);
});
test('requires issue for feat: prefix', () => {
assert.equal(checkLinkedIssue('Some description without issue', 'feat: new thing').passed, false);
});
test('requires issue for refactor: prefix', () => {
assert.equal(checkLinkedIssue('Some refactor', 'refactor: rewrite thing').passed, false);
});
test('requires issue when no prefix (encourages prefix usage)', () => {
assert.equal(checkLinkedIssue('No prefix here', 'Add some feature').passed, false);
});