Skip to content

ci(pr-checklist): require new changelog entries to cite their PR - #104

Merged
astubbs merged 7 commits into
masterfrom
ci/enforce-changelog-pr-reference
Aug 3, 2026
Merged

ci(pr-checklist): require new changelog entries to cite their PR#104
astubbs merged 7 commits into
masterfrom
ci/enforce-changelog-pr-reference

Conversation

@astubbs

@astubbs astubbs commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Description

AGENTS.md already says changelog entries must link the PR ("a bare #NN refers to this fork ... and link the PR/issue"). It was being missed anyway — and for a structural reason rather than carelessness.

The entry is written before the PR exists. At authoring time there is no number to cite, and nothing afterwards prompts you to come back. PRs #100, #101, #102 and #103 each shipped an entry with no self-reference, and each was caught one at a time by a human reading the diff. That is exactly the kind of "you must remember" rule worth making mechanical.

What it checks

Extends the existing PR Checklist job with a second step: when a PR adds a new CHANGELOG.adoc entry, at least one added entry must reference this PR (pull/NN or #NN).

The logic lives in .github/scripts/changelog-ref-gate.js rather than inline in the workflow, and is unit tested (changelog-ref-gate.test.js, 28 tests, plain node, no runner). The workflow runs those tests before the gate, so a regression in the gate fails the job loudly instead of silently mis-judging PRs. That extraction was not gold-plating: this logic has already shipped two real misjudgements (an opt-out regex that a body merely quoting the syntax could trip, and positional add/remove pairing that mis-read a block containing both an edit and a new entry), which is exactly the profile of code that earns tests. It mirrors the existing copyright.yml self-test step.

Pairing is by content, not position: an added bullet is treated as an edit of a removed one when they share a (#NN) citation, or failing that when their wording overlaps enough. Position alone turns -A, -B, +A', +NEW, +B' into precisely the wrong answer — +NEW consumed as an edit and never checked.

Deliberately narrow, to avoid false failures:

  • Only added asciidoc bullet lines count. Reflows, or edits to an older entry, are ignored — so a typo fix on last release's notes doesn't demand a self-citation.
  • Word-bounded matching, so #100 doesn't match inside #1000. Verified against a real patch.
  • Opt-out for a PR that touches the changelog without adding an entry of its own: put changelog-ref: N/A - <reason> on its own line in the body (the reason is required), mirroring the checklist's existing N/A convention. Mentions of the syntax mid-prose or in quotes don't count.
  • Bots exempt, consistent with the checklist gate.
  • No changelog change in the PR at all → nothing to check. Whether an entry was needed is already covered by the checklist item.

Needs pull-requests: read to fetch the CHANGELOG.adoc patch, and an actions/checkout (with persist-credentials: false, since nothing in that step consumes secrets) so the gate module and its tests are on disk. AGENTS.md gains a pointer to the extracted module.

Known limitation (raised in review, confirmed, documented)

When neither bullet in a candidate pair carries a citation, pairing falls back to plain word overlap — and this changelog is full of same-template entries (build(deps): Bump <lib> to <version>). Two uncited bullets in one diff block can then pair on boilerplate alone.

I reproduced it rather than reasoning about it: given a removed Bump Testcontainers to 1.20.0, a genuinely new Bump Kafka to 3.9.0, and a reworded edit of the Testcontainers line, the gate pairs the new line as the edit — so it escapes the citation check, while the real edit is falsely flagged. Wrong in both directions.

Left as-is rather than tuned blind, but pinned by a regression test so any future change to the threshold surfaces here instead of silently, and documented next to EDIT_THRESHOLD with the direction I'd take if it ever bites: fail closed — raise the threshold so an uncertain pair is treated as a new entry needing a citation. That trades a silent miss for a visible false alarm, and the false alarm has an escape hatch (changelog-ref: N/A - ...) whereas the miss has nothing.

Notes

Checklist

  • Changelog entry added (CHANGELOG.adoc) - Build & CI, citing this PR; README.adoc regenerated
  • Docs updated - N/A - the rule it enforces is already documented in AGENTS.md; the workflow's inline comments carry the rationale
  • Tests added/updated - .github/scripts/changelog-ref-gate.test.js, 28 unit tests run by the job before the gate itself, including a pinned regression test for the known pairing limitation above
  • Title & body reflect the final content of this PR
  • Self-hosted runner / security implications considered - runs on ubuntu-latest, not the self-hosted box; adds only pull-requests: read, and reads the PR diff via the API without executing anything from it

🤖 Generated with Claude Code

AGENTS.md already says to link the PR/issue, but the rule was being
missed routinely for a structural reason rather than carelessness: the
changelog entry is written BEFORE the PR exists, so at authoring time
there is no number to cite, and nothing afterwards prompts you to come
back. PRs #100, #101, #102 and #103 each shipped an entry with no
self-reference until a human spotted it, one at a time.

So make it mechanical. When a PR adds a new CHANGELOG.adoc entry line,
at least one added entry must reference this PR (pull/NN or #NN, word-
bounded so #100 does not match inside #1000).

Deliberately narrow, to avoid false failures:
- only ADDED asciidoc bullet lines count, so reflows, or edits to an
  older entry, are ignored;
- a PR that touches the changelog without adding an entry of its own can
  opt out with 'changelog-ref: N/A - <reason>' in the body, mirroring
  the checklist's existing N/A convention;
- bots are exempt, as with the checklist gate.

Needs pull-requests: read, to fetch the CHANGELOG.adoc patch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 1 package(s) with unknown licenses.
See the Details below.

License Issues

.github/workflows/pr-checklist.yml

PackageVersionLicenseIssue Type
actions/checkout6.*.*NullUnknown License
Excluded from license check: pkg:githubactions/actions/github-script

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout 6.*.* 🟢 6.9
Details
CheckScoreReason
Binary-Artifacts🟢 10no binaries found in the repo
Code-Review🟢 10all changesets reviewed
Maintained🟢 1025 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
License🟢 10license file detected
Packaging⚠️ -1packaging workflow not detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
SAST🟢 10SAST tool is run on all commits

Scanned Files

  • .github/workflows/pr-checklist.yml

@claude

claude Bot commented Aug 1, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 1m 43s —— View job


Code Review

Finding: the new gate didn't actually run its check — it hit its own opt-out by accident

.github/workflows/pr-checklist.yml:96:

const optOut = body.match(/changelog-ref:\s*N\/?A\b[^\n]*/i);

This regex isn't anchored to a line start and isn't scoped to a dedicated declaration — it matches the literal string changelog-ref: N/A anywhere in the PR body, including inside prose that merely documents the syntax.

This PR's own body does exactly that, in the "What it checks" section:

changelog-ref: N/A - <reason> in the body, mirroring the checklist's existing N/A convention.

Look at the actual run for this PR (job 91310634762):

Opted out via PR body: "changelog-ref: N/A - <reason>` in the body, mirroring the checklist's existing `N/A` convention."

The new step took the opt-out branch and returned early — it never reached the "does the added entry cite this PR" check at all. That's a real problem beyond just this PR being a bad test case: the added CHANGELOG.adoc entry (line 29) doesn't reference #104 or pull/104 anywhere — the exact failure mode this gate exists to catch — and the gate reported success (PR Checklist run 30678533669, conclusion success).

Two consequences:

  1. False negative, proven live: any PR body that discusses or quotes the opt-out syntax (docs, code review replies, this PR itself) silently disables the check without an actual maintainer decision to skip it.
  2. Trivial intentional bypass: since the match isn't anchored to its own line, an author can defeat the gate entirely just by having the substring changelog-ref: N/A appear anywhere in the body — including inside an unrelated quoted block — with no real reason required ([^\n]* after it isn't validated as non-empty either).

Suggested fix: anchor the opt-out to its own line, e.g. with multiline mode and ^:

const optOut = body.match(/^changelog-ref:\s*N\/?A\b.*$/im);

and then this PR would need to either add that opt-out on its own line deliberately, or (better, since this PR does add a real entry) cite #104/pull/104 in the CHANGELOG.adoc line it added.

Other notes (not blocking)

  • permissions: pull-requests: read addition and bot-exemption logic are consistent with the existing checklist step and look correct.
  • Word-boundary matching (#${pr.number}\b) correctly avoids #104 matching inside #1040, etc. — this part of the logic is sound once the opt-out gate is fixed.
  • If changelog.patch is omitted by the GitHub API (can happen for very large diffs), the step silently treats it as "nothing to check" — an acceptable, narrow limitation given the stated design goals, just noting it's a gap rather than a hard failure.

Fix this →

@claude

claude Bot commented Aug 1, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 2m 51s —— View job


Claude finished the review

Summary

The mechanism (checking pulls.listFiles's patch for the CHANGELOG.adoc entry, requiring newly-added bullet lines to cite the PR, with a bot exemption and an N/A opt-out) is a solid, well-scoped idea, and the changelog/README entries correctly self-cite (#104). One finding below looks like a real gap between the stated design and the implementation.

Finding: editing an existing entry is treated as "adding" a new one

.github/workflows/pr-checklist.yml:114-124 builds addedEntries from every +-prefixed bullet line in the patch, with no check against the corresponding removed line:

const addedEntries = changelog.patch
  .split(/\r?\n/)
  .filter(l => /^\+\s*\*\s+\S/.test(l))
  .map(l => l.replace(/^\+/, ''));

The PR description states: "Reflows, or edits to an older entry, are ignored — so a typo fix on last release's notes doesn't demand a self-citation." That isn't what happens, though. Every entry in CHANGELOG.adoc is written as a single (very long) line — confirmed by scanning the file, there are no wrapped/multi-line bullets. Git therefore represents any edit to an existing entry (a typo fix, a version bump, a wording tweak) as a full -/+ pair on that line, e.g.:

-* Dependencies and build plugins refreshed ... JUnit 5.10.2 -> 5.14.4 ...(#73)
+* Dependencies and build plugins refreshed ... JUnit 5.10.2 -> 5.14.3 ...(#73)

The + line matches /^\+\s*\*\s+\S/, so it lands in addedEntries. Since it references #73 and not the current PR number, referencing comes back empty and the gate fails — demanding either a bogus self-citation added to someone else's old entry, or an N/A opt-out — for a plain edit to an existing line. That directly contradicts the "typo fix... doesn't demand a self-citation" claim in the PR body, and will produce false failures the first time this PR (or a future one) edits an existing entry rather than only appending new ones.

A fix could pair adjacent -/+ bullet lines (a single-line replacement of an existing entry) and exclude those from addedEntries, only treating a + bullet with no adjacent - bullet as genuinely new. Worth confirming with a synthetic patch before merging, since the PR's own validation was against PR #103's patch (a pure addition, not an edit case).

Minor / non-blocking observations

  • Large-diff truncation: GitHub omits patch when a file's diff is very large; !changelog.patch is treated identically to "no changelog change at all" (.github/workflows/pr-checklist.yml:108-112), so a giant CHANGELOG.adoc rewrite could silently skip the check. Unlikely in practice given entries are single lines and this file rarely gets huge diffs, but worth a one-line comment noting the tradeoff.
  • Wrapped bullet continuations: the added-entry regex only matches lines starting with * , so if an entry were ever written as a wrapped multi-line bullet, a citation added only on a continuation line wouldn't be detected. Not an issue today (no multi-line entries exist in the file), just a latent assumption worth a short comment for future maintainers.
  • The pr.user.type === "Bot" check is duplicated between the two steps rather than shared — reasonable given github-script steps don't share JS state, not worth changing.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

✅ Duplicate Code Report

Two engines run in parallel for cross-validation. Each has its own thresholds tuned to its baseline - the real safety net is the per-engine "max increase vs base" check.

✅ PMD CPD

PR Base Change
Clones 33 33 ➖ 0
Duplicated lines 1001 1001 ➖ 0
Duplication 3.03% 3.03% ➖ 0
Rule Limit Status
Max duplication 5% ✅ Pass (3.03%)
Max increase vs base +0.1% ✅ Pass (+0.00%)

No new clones introduced by this PR.

✅ jscpd (language-agnostic)

PR Base Change
Clones 82 82 ➖ 0
Duplicated lines 1175 1175 ➖ 0
Duplication 3.59% 3.59% ➖ 0
Rule Limit Status
Max duplication 5% ✅ Pass (3.59%)
Max increase vs base +0.1% ✅ Pass (+0.00%)

No new clones introduced by this PR.

Powered by astubbs/duplicate-code-cross-check

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

📌 Duplicate code detection tool report

The tool analyzed your source code and found the following degree of similarity between the files:

✅ No new or increased file similarities introduced by this PR.

Full similarity report
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java

📄 parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java 35.09
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java 33.0
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java

📄 parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java 39.27
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java 35.09
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 54.23 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 40.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 37.32
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java 37.16
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 35.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 35.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 35.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 34.62
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 30.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 60.34 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 54.2 ⚠️
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 40.07
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 36.58
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.17
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 31.13
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 60.34 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 50.02 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 36.27
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 32.02
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 31.12
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 37.16
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 33.13
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 54.23 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 53.71 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 45.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 35.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 34.12
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 31.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 31.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 30.58
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 30.11
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java 32.79
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java 31.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 54.2 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 50.02 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 45.17
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 33.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java 32.79
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java 30.69
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 45.17
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 36.58
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 36.27
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 32.29
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 35.45
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 33.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java 32.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java 32.59
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 32.17
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 31.12
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/RecordContextInternal.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContext.java 35.45
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PollContextInternal.java 32.59
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java 32.86
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 32.79
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/BrokerPollSystem.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/AbstractParallelEoSStreamProcessor.java 32.86
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 39.54
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 60.5 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 53.71 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 51.23 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 48.61
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 40.68
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 39.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.41
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 34.18
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 34.18
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/PCRetriableException.java 33.13
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 39.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 31.09
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 30.58
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java 32.81
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ProducerManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java 32.79
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 51.8 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 37.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 37.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 37.41
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 35.15
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 33.35
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 60.5 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 51.8 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 48.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 47.5
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 47.5
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 46.75
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 45.01
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 37.32
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalRuntimeException.java 31.09
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 48.61
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 46.75
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 45.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 38.69
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 38.69
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 30.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 30.11
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 51.23 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 48.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 45.48
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 34.62
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 34.12
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 33.35
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 32.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 32.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java 63.91 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 47.5
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 38.69
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 34.18
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 32.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 31.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV2EncodingNotSupported.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/RunLengthV1EncodingNotSupported.java 63.91 ⚠️
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/EncodingNotSupportedException.java 47.5
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/NoEncodingPossibleException.java 38.69
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/BitSetEncodingNotSupportedException.java 37.82
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ExceptionInUserFunctionException.java 35.6
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/InternalException.java 34.18
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/offsets/OffsetDecodingError.java 32.19
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerException.java 31.28
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelConsumerOptions.java 31.0
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java 30.74
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java 41.88
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionState.java 30.74
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java 38.33
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ShardManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/ProcessingShard.java 38.33
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java

📄 parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/WorkManager.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/state/PartitionStateManager.java 41.88
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java 30.31
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java 33.96
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 55.36 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 46.87
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 38.64
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 44.16
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 41.04
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 38.64
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java 36.78
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/RebalanceEoSDeadlockTest.java 36.78
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 60.71 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 46.87
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 41.04
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java 30.12
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 60.71 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceHighVolumeTest.java 55.36 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/MultiInstanceRebalanceTest.java 44.16
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java 39.38
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 48.62
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 35.35
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java 48.62
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java 37.72
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 32.55
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 50.82 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkCooperativeIT.java 50.82 ⚠️
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/AbstractRevokeUnderWorkScenario.java 35.35
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 32.55
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ProgressProbe.java 30.22
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosScenarioBase.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosChurnStormIT.java 37.72
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ProgressProbe.java

📄 parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ProgressProbe.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/chaostests/ChaosRevokeUnderWorkIT.java 30.22
parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java

📄 parallel-consumer-core/src/test/java/io/confluent/csid/utils/CollectionUtils.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/csid/utils/JavaUtils.java 39.27
parallel-consumer-core/src/main/java/io/confluent/csid/utils/Java8StreamUtils.java 33.0
parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/csid/utils/LoopingResumingIteratorTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/KafkaSanityTests.java 33.96
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java 30.24
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AmbientProbeExtensionTest.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/AmbientProbeExtension.java 30.31
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 30.36
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java 45.58
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java 43.89
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 52.02 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 50.71 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 44.8
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/BatchTestBase.java 30.36
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 70.44 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 56.78 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 49.77
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 70.44 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 55.75 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 52.98 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 52.98 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 49.77
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java 47.42
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerCommitTimeoutTest.java 56.78 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerEarlyCloseTest.java 55.75 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/MockConsumerSaslAuthenticationTest.java 47.42
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java 34.7
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessorTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/ParallelEoSSStreamProcessorRebalancedTest.java 34.7
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/AbstractParallelEoSStreamProcessorTestBase.java 30.24
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java 45.58
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java 33.46
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineRegistryScriptTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CheckQuarantineOwnersScriptTest.java 43.89
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/QuarantineLaneReportScriptTest.java 33.46
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 90.38 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 89.71 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 89.71 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java 30.12
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/InternalRuntimeExceptionTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/ExceptionConstructorsTest.java 30.12
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/PCModuleTestEnv.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/PCModule.java 32.81
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/internal/TestParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelEoSStreamProcessor.java 30.69
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java 40.07
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureUnitTest.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/offsets/OffsetEncodingBackPressureTest.java 40.07
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java 36.58
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java

📄 parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/LongPollingMockConsumerSubject.java

File Similarity (%)
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/truth/CommitHistorySubject.java 36.58
parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java

📄 parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java

File Similarity (%)
parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java 52.5 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 79.06 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 50.71 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 49.27
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java 69.61 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java 34.11
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java 32.9
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java

📄 parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 91.22 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 90.55 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 89.71 ⚠️
parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java

📄 parallel-consumer-reactor/src/main/java/io/confluent/parallelconsumer/reactor/ReactorProcessor.java

File Similarity (%)
parallel-consumer-mutiny/src/main/java/io/confluent/parallelconsumer/mutiny/MutinyProcessor.java 52.5 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 79.06 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 52.02 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java 50.53 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorPCTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyPCTest.java 69.61 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyTest.java 34.11
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorUnitTestBase.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyUnitTestBase.java 32.9
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java

📄 parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java 91.22 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 90.55 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 89.71 ⚠️
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 41.51
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 40.07
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 39.72
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 35.33
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelStreamProcessor.java 32.02
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 39.72
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 39.16
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/ParallelStreamProcessor.java 32.29
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/JStreamParallelEoSStreamProcessor.java 31.13
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java 41.75
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 41.51
parallel-consumer-core/src/main/java/io/confluent/parallelconsumer/internal/ExternalEngine.java 39.54
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java

📄 parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelStreamProcessor.java

File Similarity (%)
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/VertxParallelEoSStreamProcessor.java 41.75
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelStreamProcessor.java 39.16
parallel-consumer-vertx/src/main/java/io/confluent/parallelconsumer/vertx/JStreamVertxParallelEoSStreamProcessor.java 35.33
parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java

📄 parallel-consumer-vertx/src/test-integration/java/io/confluent/parallelconsumer/vertx/integrationTests/VertxConcurrencyIT.java

File Similarity (%)
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/VeryLargeMessageVolumeTest.java 39.38
parallel-consumer-core/src/test-integration/java/io/confluent/parallelconsumer/integrationTests/TransactionAndCommitModeTest.java 30.12
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java

📄 parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/TestConventionsArchTest.java

File Similarity (%)
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/TestConventionsArchTest.java 91.22 ⚠️
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/TestConventionsArchTest.java 91.22 ⚠️
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/TestConventionsArchTest.java 90.38 ⚠️
parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java

📄 parallel-consumer-vertx/src/test/java/io/confluent/parallelconsumer/vertx/VertxBatchTest.java

File Similarity (%)
parallel-consumer-reactor/src/test/java/io/confluent/parallelconsumer/reactor/ReactorBatchTest.java 50.53 ⚠️
parallel-consumer-mutiny/src/test/java/io/confluent/parallelconsumer/mutiny/MutinyBatchTest.java 49.27
parallel-consumer-core/src/test/java/io/confluent/parallelconsumer/CoreBatchTest.java 44.8

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

✅ SpotBugs Report

No bugs found (new bugs only — baseline from base branch excluded).

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

🧪🔒 Quarantine Lane Report

Quarantined test Outcome Owner Meaning
ChaosChurnStormIT.churnStormMeetsSlosAndBalancesLedger 🔴 failing (expected) #80 quarantine holding
PartitionStateCommittedOffsetIT.committedOffsetRemoved 🟡🎲 passed (flapper) #80 proves nothing - passes most runs by nature

🔴 expected while the owner PR is open · 🟡🎲 flapper, pass proves nothing · 🚨 a deterministic quarantined test passing means its fix landed: delete its @Quarantined annotation + docs/QUARANTINED_TESTS.md entry (a merge-blocking review thread has been opened). Lane: non-gating; rules: see the Quarantine Audit check.

…il in changelog gate

Review findings on #104, both confirmed against the live run:

- The changelog-ref: N/A opt-out regex matched anywhere in the PR body,
  so a body that merely documented the syntax (this PR's own) silently
  disabled the gate. Now anchored to its own line with a mandatory
  reason.
- Every '+' bullet in the patch was treated as a NEW entry, so a
  single-line edit to an old entry (rendered by git as a -/+ pair)
  demanded a bogus self-citation. '+' bullets now consume unmatched '-'
  bullets from the same change block; only leftovers count as new.

Verified with 13 synthetic-patch cases plus an end-to-end run against
this PR's real body and CHANGELOG.adoc patch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@astubbs

astubbs commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Both review findings addressed in 0fce24e - thanks, both were real and the first was proven live by this PR's own CI run.

This regex isn't anchored to a line start and isn't scoped to a dedicated declaration — it matches the literal string changelog-ref: N/A anywhere in the PR body [...] the added CHANGELOG.adoc entry (line 29) doesn't reference #104 or pull/104 anywhere

Fixed: the opt-out is now /^\s*changelog-ref:\s*N\/?A\b\s*-\s*\S[^\n]*/im - anchored to its own line and the - <reason> part is now mandatory (addressing the "[^\n]* isn't validated as non-empty" point too). Mid-prose mentions like this PR body's documentation, quoted > changelog-ref: N/A lines, and reason-less opt-outs no longer disable the gate. The missing #104 citation was already fixed in d954e9f; with the false opt-out gone, the gate now actually runs on this PR and passes on its own entry.

Every entry in CHANGELOG.adoc is written as a single (very long) line [...] Git therefore represents any edit to an existing entry (a typo fix, a version bump, a wording tweak) as a full -/+ pair on that line [...] the gate fails — demanding either a bogus self-citation added to someone else's old entry, or an N/A opt-out — for a plain edit

Fixed with the suggested pairing approach: each + bullet first consumes an unmatched - bullet from the same contiguous change block (that's an edit, exempt); only leftover + bullets are treated as genuinely new entries. A context line or hunk header resets the block. The "typo fix on last release's notes doesn't demand a self-citation" claim in the description is now true in the implementation.

Worth confirming with a synthetic patch before merging

Done - 13 synthetic-patch cases (pure addition, single-line edit, edit + new entry in either order, block resets across hunks, pure deletion, non-bullet header tweaks, and 6 opt-out regex variants) all pass, plus an end-to-end run of the fixed logic against this PR's real body and real CHANGELOG.adoc patch from the API: opt-out no longer matches, exactly 1 added entry detected, and it cites #104.

Large-diff truncation [...] worth a one-line comment noting the tradeoff. / Wrapped bullet continuations [...] a latent assumption worth a short comment

Both now have short comments in the workflow at the relevant spots.

Not changed (agreed non-blocking): the duplicated pr.user.type === "Bot" check stays as-is since github-script steps don't share JS state.

The PR body's opt-out bullet has been updated to state the opt-out must be on its own line with a required reason.

@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 3m 59s —— View job


Tasks

  • Gather context (read changed files, prior review rounds, author's fix commit 0fce24e)
  • Verify the two previously-reported findings (opt-out anchoring, edit-vs-add pairing) against the fixed code
  • Re-review the changelog-reference step for new issues
  • Post review feedback

Summary

Both previously-reported issues are fixed correctly:

  • Opt-out anchoring (.github/workflows/pr-checklist.yml:98): /^\s*changelog-ref:\s*N\/?A\b\s*-\s*\S[^\n]*/im is now anchored to line-start and requires a non-empty reason after the dash. Traced against this PR's own body: the "What it checks" prose that merely mentions changelog-ref: N/A - <reason> mid-sentence no longer matches (the line doesn't literally start with changelog-ref:), and a > -quoted line wouldn't match either. Good fix.
  • Edit-vs-add pairing (lines 123–137): the FIFO consume-a-removed-bullet-per-added-bullet approach correctly exempts simple -old/+new single-line edits from the citation requirement, matching the stated "typo fix... doesn't demand a self-citation" design goal.

Finding: the edit/add pairing is positional, so it can still misattribute in a mixed block

.github/workflows/pr-checklist.yml:123-137 pairs each + bullet with the Nth unmatched - bullet in the same contiguous block, purely by count/position — not by content. That breaks when a block contains more than one edit plus a genuinely new entry inserted between them, e.g.:

-* Entry A old text (#10)
-* Entry B old text (#20)
+* Entry A new text (#10)
+* NEW Entry C text (no ref yet)
+* Entry B new text (#20)

Traced through the loop: removedBullets reaches 2 after the two - lines, then each + line decrements it in order — so Entry A new and NEW Entry C both get consumed as "edits" (paired positionally, in that order), and Entry B new is the one left over and pushed to addedEntries. Two failure modes from one input:

  1. False negative: NEW Entry C — the actually-new entry with no citation — silently evades the check entirely (the exact gap this gate exists to close).
  2. False failure: Entry B new — a plain wording edit — gets flagged as needing a bogus citation, which is precisely the "avoid false failures" outcome the PR explicitly designs against for the single-edit case.

This is realistic: it just requires one PR to edit ≥2 existing entries' wording and insert a new entry between them in the same hunk — plausible since CHANGELOG.adoc entries are contiguous bullets with no blank lines between them (confirmed by reading the file), so git won't split such a block on a context line. The 13 synthetic cases mentioned in the fix (including "edit + new entry in either order") cover a single edit paired with a single addition before/after it, but not two-or-more edits with a new insertion sandwiched between them — the counting-by-position assumption only breaks in that specific configuration.

Given how much care already went into narrowing this gate to avoid false failures, this feels worth at least a documented limitation (alongside the two already-noted ones for large-diff truncation and wrapped continuations), if not a content-aware pairing fix (e.g. matching on a shared trailing (...#NN) citation token before falling back to position). Low urgency relative to the two already-fixed issues, since it needs a fairly specific PR shape to trigger, but it's the same failure class.

Fix this →

Other notes (not blocking)

  • permissions: pull-requests: read and the bot exemption are correctly scoped, unchanged from the earlier review.
  • The truncation and wrapped-continuation limitations flagged in the previous review round now have short explanatory comments in the workflow (lines 111-112, 121-122) as promised.

…gate

Third review finding on #104: the -/+ bullet pairing was positional, so a
block holding two edits with a new entry inserted between them
(-A, -B, +A', +NEW, +B') paired off by count into exactly the wrong
answer - +NEW consumed as an edit and never checked, +B' falsely flagged
as new. Both failure modes at once: the uncited new entry the gate exists
to catch sails through, and a plain wording edit is told to self-cite.

Pairing is now by CONTENT, strongest match first: a shared (#NN)
citation, else word overlap above a threshold. Position is no longer a
signal, so ordering and insertions can't misattribute. Writing the tests
turned up a fourth case the review didn't mention - a deletion plus an
unrelated addition in the same block also silently exempted the new
entry.

The logic moves to .github/scripts/changelog-ref-gate.js so it can be
tested rather than mirrored; the job runs those 25 tests before the gate,
matching the existing 'self-test the scanner' step in copyright.yml. The
three cases above fail against the old implementation, so they are real
regression tests. Net effect on the workflow is less inline JS, not more.

AGENTS.md now records that the reference convention is CI-enforced and
how to opt out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@astubbs

astubbs commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Third finding addressed in c6846b6. The trace was exactly right - I reproduced it before changing anything, and the old logic reported * Entry B new text (#20) as the new entry while NEW Entry C went unchecked.

.github/workflows/pr-checklist.yml:123-137 pairs each + bullet with the Nth unmatched - bullet in the same contiguous block, purely by count/position — not by content.

Rather than document it, I removed the positional assumption entirely. Pairing is now by content, strongest match first: a shared (#NN) citation is decisive (an entry keeps its link even when the prose is rewritten wholesale), otherwise Dice coefficient over word sets above a 0.5 threshold. Candidate pairs are scored globally and assigned greedily, so ordering and insertions can't misattribute - the -A, -B, +A', +NEW, +B' case now reports +NEW and only +NEW.

Writing the tests turned up a fourth case the review didn't call out, same failure class: a deletion plus an unrelated addition in one block (-* Dropped note (#50) / +* New entry (#104)) also had the new entry silently consumed as an "edit". Content pairing fixes that too, since the two bullets share neither citation nor vocabulary.

Worth at least a documented limitation ... if not a content-aware pairing fix

On testing: a mirrored copy of the logic in a throwaway script would drift from the workflow, so the gate's logic now lives in .github/scripts/changelog-ref-gate.js with changelog-ref-gate.test.js beside it, and the job runs the tests before the gate - a regression in the pairing fails PR Checklist rather than quietly misjudging changelogs. That mirrors the existing Self-test the scanner (fixture repos) step in copyright.yml, so it's an established pattern here rather than new infrastructure. Net effect on the workflow YAML is less inline JS than before.

25 tests, no dependencies, plain node. The three cases above were verified to fail against the old implementation, so they're genuine regression tests and not just green-by-construction. Also re-ran the whole thing end to end against this PR's real body and CHANGELOG.adoc patch from the API: opt-out correctly doesn't fire, 1 new entry detected, it cites #104, gate passes having actually run.

Two notes on the checkout this required: it's the PR's own tree with persist-credentials: false, and no secrets are consumed. The copyright scanner's .java-only scope means the new .js files need no licence header.

AGENTS.md now records that the reference convention is CI-enforced, that editing an existing entry doesn't count as adding one, and the opt-out syntax - previously it described the convention as advisory.

@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 3m 31s —— View job


Tasks

  • Gather context (read changed files, prior review rounds, diff since last review)
  • Review .github/scripts/changelog-ref-gate.js (new extracted gate logic)
  • Review .github/scripts/changelog-ref-gate.test.js (new tests)
  • Review .github/workflows/pr-checklist.yml diff (self-test step, gate usage)
  • Review AGENTS.md / changelog/README changes
  • Post review feedback

Summary

All three previously-reported issues (opt-out anchoring, positional edit/add mispairing, and the follow-up deletion-plus-unrelated-addition case) are fixed correctly in changelog-ref-gate.js, and the refactor into a tested, standalone module is a solid response to "logic subtle enough to have shipped two real misjudgements" — newEntriesInBlock (lines 51-67) now pairs by content (shared (#NN) citation first, then Dice-coefficient word overlap) rather than position, the self-test step runs before the gate and fails the job on a regression, and the 25 unit tests trace through the exact regression scenarios from earlier rounds (verified the -A,-B,+A',+NEW,+B' case and the deletion-plus-unrelated-addition case both resolve correctly per the code as written).

Finding: content-based pairing can still mispair when entries share boilerplate wording but no citation

.github/scripts/changelog-ref-gate.js:39-45 (editScore) falls back to plain Dice similarity (EDIT_THRESHOLD = 0.5, line 35) whenever neither bullet in a candidate pair carries a shared #NN citation. That fallback is exactly the scenario this changelog file already produces in practice — dependency-bump entries reuse near-identical phrasing across releases, e.g. line 58's "Dependencies and build plugins refreshed to their latest non-major versions..." or the repeated "build(deps): Bump <lib> to <version>" pattern at lines 116-117. Two different, uncited bullets built from the same template can score above 0.5 purely on shared boilerplate words (build, deps, bump, to, etc.) — no shared citation needed to reach the threshold.

Concretely, in a single contiguous diff block:

-* build(deps): Bump Kafka to 3.6.2
+* build(deps): Bump Testcontainers to 1.21.0
+* build(deps): Bump Kafka to 3.9.0

editScore("Bump Testcontainers...", "Bump Kafka to 3.6.2") and editScore("Bump Kafka to 3.9.0", "Bump Kafka to 3.6.2") are both computed with no citation to break the tie (neither line has one yet). If the wrong one scores higher — plausible given generic wording — the true edit (Kafka to 3.9.0) loses the pairing to the unrelated Testcontainers addition and gets reported as "new" (a false failure demanding a bogus citation on what's actually an edit), while the genuinely new Testcontainers line silently escapes the check as an "edit" (the false negative this whole gate exists to prevent). Which way it breaks depends only on relative word overlap, not on which pairing is semantically correct.

This is inherently a heuristic-matching limitation rather than a clear-cut bug, and it only bites when two uncited bullets in the same contiguous hunk are textually similar — narrower than the positional bug already fixed, but realistic for exactly this repo's own dependency-bump entries. Given the care already taken to document the other two known limitations (large-diff truncation at line ~111, wrapped continuations at line ~121), this seems worth the same treatment: either a short comment near EDIT_THRESHOLD/editScore noting that same-template, uncited bullets in one block can mispair, or a regression test using this repo's own recurring "Bump <lib> to <version>" phrasing to confirm current behavior is acceptable.

Fix this →

Other notes (not blocking)

  • .github/workflows/pr-checklist.yml: the new actions/checkout + self-test steps run unconditionally, including for bot PRs that skip the checklist/gate logic itself — negligible extra cost (a sub-second node run), not worth special-casing.
  • citesPr and findOptOut's word-boundary handling both correctly reject #1040/#104x-style false matches (digits and letters are both \w, so no boundary forms mid-token) — verified by tracing the regex rather than just trusting the tests.
  • The extraction to .github/scripts/ plus running changelog-ref-gate.test.js as a required pre-step is a good pattern match to the existing copyright.yml self-test step, as the author notes.

astubbs added a commit that referenced this pull request Aug 3, 2026
Four things #102 does not resolve, so they are not lost at merge:

- A green 'review' check can mean the reviewer never ran.
  claude-code-action refuses to run when the workflow file differs from
  the default branch's copy, and reports that skip as SUCCESS. Any PR
  editing a validated workflow therefore gets a green review check that
  verified nothing - it bit #102 and #104, both workflow changes. The
  control itself is correct (it stops a PR rewriting the reviewer's own
  grants and having that version execute), but it is invisible unless
  you read the job log, so it needs saying out loud.
- Credential exposure is unresolved, not cleared: the job runs
  PR-authored build code alongside CLAUDE_CODE_OAUTH_TOKEN, and #102
  widened the blast radius to pull-requests: write. Bounded by fork PRs
  not getting secrets and by the allowlist - neither of which answers
  the actual question about token scrubbing.
- The reviewer cannot lint workflows: actionlint is not granted, so on a
  workflow PR it can only eyeball YAML, as it said itself on #102
  ('trusted, not verified'). Cheap to grant, but it must land in a
  non-workflow PR or the validation skip means it is never exercised.
- bin/ci-integration-test.sh may not fit the 30-minute cap, and none of
  #102's setup (cache, Docker, the grants) has actually executed yet -
  same reason.

Filed under CI reliability / gate issues rather than refactoring.md:
these are in-flight gate concerns tied to open PRs, not deferred code
work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
astubbs and others added 2 commits August 3, 2026 14:39
…g-pr-reference

# Conflicts:
#	CHANGELOG.adoc
#	README.adoc
…tion

Review finding on #104, reproduced rather than taken on trust.

When neither bullet in a candidate pair carries a citation, pairing
falls back to plain word overlap - and this changelog is full of
same-template entries (build(deps): Bump <lib> to <version>). Two
uncited bullets in one diff block can then pair on boilerplate alone.

Constructed the failure: removed 'Bump Testcontainers to 1.20.0', added
a genuinely new 'Bump Kafka to 3.9.0' plus a reworded edit of the
Testcontainers line. The gate pairs the NEW line as the edit, so it
escapes the citation check, while the real edit is falsely flagged.
Wrong in both directions, and the escaping-new-entry half is exactly the
false negative this gate exists to prevent.

Not tuned blind - the threshold is someone's considered choice and a
guessed number could easily be worse. Instead:

- pinned by a regression test, so any future change to EDIT_THRESHOLD or
  editScore surfaces here rather than silently. The test says outright
  that it records accepted behaviour, not desired behaviour, and that a
  failure caused by the gate getting stricter is an improvement.
- documented next to EDIT_THRESHOLD with the direction to take if it
  ever bites: FAIL CLOSED, raising the threshold so an uncertain pair is
  treated as a new entry needing a citation. That trades a silent miss
  for a visible false alarm - and the false alarm has an escape hatch
  (changelog-ref: N/A - ...) whereas the miss has nothing.

Also adds two positive pairing tests (shared citation survives a total
rewording; distinct bumps pair correctly when the library name breaks
the tie), taking the suite to 28.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 1m 51s —— View job


Tasks

  • Gather context (prior review rounds, commits since last review)
  • Review latest commit 1ee5493e addressing the "same-template pairing" limitation
  • Re-check .github/scripts/changelog-ref-gate.js and tests for regressions/new issues
  • Post review feedback

Summary

This round only adds one commit (1ee5493e) on top of the previously-reviewed c6846b66, touching just changelog-ref-gate.js and its test file (confirmed via git diff c6846b66..HEAD -- .github/workflows/pr-checklist.yml AGENTS.md — no changes to the workflow or docs since the last full review pass). It responds to the 4th finding from the previous round (same-template boilerplate bullets can mispair when neither carries a citation).

Verified by manual trace (couldn't execute node in this sandboxed run — approval for it wasn't available — so I hand-traced the Dice-coefficient math instead of trusting the assertions):

  • "distinct bumps pair correctly when the library name breaks the tie" (changelog-ref-gate.test.js:194-201): editScore("Bump Testcontainers...", "Bump Kafka to 3.6.2") = 0.5, editScore("Bump Kafka to 3.9.0", "Bump Kafka to 3.6.2") = 0.75 (shared words build,deps,bump,kafka,to,3 = 6 of 8+8). Greedy pairing takes the higher-scoring Kafka/Kafka pair first, correctly leaving Testcontainers as the reported new entry. Matches the asserted expectation.
  • "mispairs same-template uncited bullets" (changelog-ref-gate.test.js:209-216, the pinned regression): editScore("Bump Kafka to 3.9.0", "Bump Testcontainers to 1.20.0") = 0.625 (boilerplate + coincidental shared 0) beats editScore("Upgraded the Testcontainers dependency...", "Bump Testcontainers to 1.20.0") = 0.133. The unrelated Kafka addition wins the pairing and is treated as the "edit," while the real (reworded) Testcontainers edit is reported as new — exactly the limitation the commit message describes, and exactly what the test asserts.

Both traces match the committed expectations, so the test isn't accidentally green-by-construction.

This is a reasonable resolution to the finding: rather than tuning the threshold blind (which the author correctly notes could easily make things worse without evidence), it's documented in-place next to EDIT_THRESHOLD (changelog-ref-gate.js:33-46) with a concrete fail-closed direction if it ever bites in practice, and pinned by a regression test so a future change to the threshold or editScore surfaces here rather than silently drifting. The test count (28, confirmed via grep -c '^test(') matches what's claimed in the commit message and PR description.

No new issues found in this round. Combined with the three earlier fixed findings (opt-out anchoring, positional edit/add mispairing, deletion-plus-unrelated-addition), the gate's logic and its self-documented limitations look solid and consistent with AGENTS.md's updated convention text (AGENTS.md:167, confirmed it accurately describes the edit-vs-add distinction and opt-out requirements as implemented).

Note on tooling: I was not able to actually execute node .github/scripts/changelog-ref-gate.test.js in this environment (the command required approval that wasn't available), so the verification above is a manual trace of the scoring math rather than a live test run — worth an independent node run before merge if that matters for confidence, though the trace gives me high confidence the logic is correct as committed.

…g-pr-reference

# Conflicts:
#	CHANGELOG.adoc
#	README.adoc
@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @astubbs's task in 1m 23s —— View job


Tasks

  • Gather context (prior review rounds, current branch state)
  • Determine what changed since the last reviewed commit (1ee5493e)
  • Review any new changes to the changelog-ref gate
  • Post review feedback

Summary

No functional changes since the last full review round (commit 1ee5493e, which resolved the "same-template pairing" limitation). The only diff since then (git diff 1ee5493e..HEAD --stat) is a clean merge of origin/master into this branch, bringing in PR #103 (docs: index every TODO/FIXME/XXX marker...) — it touches bin/todo-index.sh, docs/TODO_INDEX.md, docs/inflight.md, docs/refactoring.md, and adds a "Where things live" section to AGENTS.md. None of that overlaps with this PR's actual feature.

Confirmed nothing relevant to the changelog-ref gate changed in the merge:

  • .github/scripts/changelog-ref-gate.js, .github/scripts/changelog-ref-gate.test.js, and .github/workflows/pr-checklist.yml are all byte-identical to the versions reviewed at 1ee5493e.
  • AGENTS.md's changelog-reference-convention section (the part this PR added/edited) is unchanged — the new content from the merge is a separate, unrelated "Where things live" table.
  • CHANGELOG.adoc/README.adoc picked up PR docs: index every TODO/FIXME/XXX marker, triage into the existing refactoring backlog #103's entry (already merged into origin/master) alongside this PR's own #104 entry, which is untouched and still correctly self-cites.

I was not able to execute node .github/scripts/changelog-ref-gate.test.js in this run either (same sandboxing restriction noted in the prior round), so I didn't attempt to re-verify the test results — but since the file is unchanged from the version already traced/verified in the previous review round, there's nothing new here to re-check.

No new findings. All previously-reported issues (opt-out anchoring, positional edit/add mispairing, deletion-plus-unrelated-addition, same-template pairing) remain fixed and documented as of 1ee5493e. This PR looks ready from a review standpoint.

@astubbs
astubbs merged commit f3d38b1 into master Aug 3, 2026
26 of 29 checks passed
@astubbs
astubbs deleted the ci/enforce-changelog-pr-reference branch August 3, 2026 02:54
astubbs added a commit that referenced this pull request Aug 3, 2026
* ci(review): one review per PR at a time, newest wins

PR #107 got two bot reviews 23 seconds apart. claude-code-review.yml had
no concurrency group at all - unlike maven.yml, pr-checklist.yml,
copyright.yml and the highcpu lane - so the run started by opening the
PR was never superseded by the run started by the next push. Both
completed, both posted.

The triggering sequence is not unusual, it is what this repo's own rules
produce: #104's changelog gate requires the entry to cite the PR number,
and that number does not exist until the PR is opened. So opening a PR
is routinely followed within seconds by a push to add the reference -
which is exactly the double-trigger.

Keyed on the PR number rather than the ref, so it also covers reopened
PRs and cannot collide with anything else keyed on a branch name.

Deliberately a separate PR rather than folded into #107: touching
claude-code-review.yml makes a PR unreviewable by the bot
(claude-code-action refuses to run when the workflow differs from the
default branch's copy), and #107's fork-repo and default-branch guards
are worth having reviewed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn

* docs(changelog): cite this PR (#109)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn

* ci(changelog-gate): cite the issue, not this PR

Requiring the entry to cite its own PR was a nuisance by construction:
the number does not exist until the PR is opened, so every PR needed a
second push purely to add the reference. That push is also what
double-triggered the review workflow, which is the other half of this
PR.

An issue number is known before the work starts, and 'which reported
problem does this address' is what a changelog reader actually wants -
the PR is an implementation detail they can reach from the issue.

Two deliberate constraints:

- The citation must be an explicit /issues/ link. A bare #NN cannot be
  told apart from a PR reference without an API call, since GitHub
  numbers issues and pull requests from one sequence - and 'cite the
  issue' is the entire point. Fork and upstream issues both count.

- Only user-visible sections require one: Breaking, Improvements, Fixes,
  Examples. Build & CI is exempt, and that is not laziness - of the 12
  Build & CI entries predating any of this, 7 cite nothing at all and
  the rest cite a PR. This project's tooling work is self-directed and
  has no issue behind it, so requiring one would mean inventing issues
  or writing changelog-ref: N/A on every CI PR - the same paperwork this
  change removes, pointing the other way.

Existing entries without an issue are left alone. Only newly ADDED
entries are checked, so nothing needs backfilling.

The opt-out is unchanged for the genuine no-issue case. AGENTS.md's
reference convention is updated to match, since it documented the old
rule. 34 unit tests, including that a pull link and a bare #NN both
correctly fail to count as issue citations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn

* ci(changelog-gate): read the changelog, and drop the clever half

Review on #109 found the section detection was inert, and proved it
against this PR's own diff: git has no funcname pattern for asciidoc, so
a hunk header for CHANGELOG.adoc reads '@@ ... @@ endif::[]' rather than
the heading, and entries are one long line each so three lines of
context never reach one either. Section resolved to null for
essentially every real entry - and since an unknown section counted as
exempt, the gate passed everything silently. It was decoration.

Fixed by reading the CHANGELOG itself rather than inferring from the
patch. The job already checks the repo out, so the file is right there:
find the added line, walk back to the nearest '=== ' heading. Verified
end to end against the real changelog - a real Build & CI entry resolves
to Build & CI and passes, a real 'fix:' entry with no issue link is
flagged.

Also took the chance to cut this down, per feedback that it had got too
complex for what it is. Gone: Dice-coefficient similarity, edit scoring,
content-based pairing of removed against added bullets, EDIT_THRESHOLD
and its pinned mispairing limitation. 176 -> 96 lines of logic, 269 ->
147 of tests.

What that costs, stated in the code rather than discovered later:
editing an old uncited entry now asks for a citation it never had.
Telling edits from additions needs the fuzzy matching that was just
removed - which was the largest and subtlest part of the file and still
mispaired same-template entries. The changelog-ref: N/A opt-out covers
the rare case. That is a better trade than machinery nobody can follow,
for a check that exists to remind us, not to withstand an adversary.

The test suite now models a realistic patch - no heading anywhere in the
visible context - which is exactly the case the old tests all avoided by
putting '=== Fixes' in the synthetic hunk header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
astubbs added a commit that referenced this pull request Aug 4, 2026
…tinc#893 names itself

The changelog-issue gate that master gained in #104 flags two entries on this
branch. One is a real omission: upstream PR confluentinc#893 says "issue confluentinc#894" in its own
body, and confluentinc#894 is "Offset reset when frequent rebalancing" - precisely the
problem the entry describes. It now cites it.

upstream-map.yaml recorded issues: [] for this cherry-pick, so the map was
wrong rather than merely thin. Corrected to [894], with a note saying what it
used to say, and last_checked moved to today.

The other flagged entry, the shards.max.size metric, genuinely has no issue:
upstream confluentinc#905 opens "I want to add a metric..." and cites nothing. Its
related: [71] is "Health-checks", far too general to claim as the request.
That one takes the gate's changelog-ref opt-out in the PR body rather than an
invented citation - which is the trade the gate's own comments call for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqHpNSXC39ANv9kG1ZvUzn
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