docs(gate): land corpus lessons and add non-blocking rewrite report - #200
docs(gate): land corpus lessons and add non-blocking rewrite report#200cuioss-oliver wants to merge 10 commits into
Conversation
Create doc/development/build-gate-discipline.adoc as a peer of the Sonar quality-gate policy. It records the three mechanisms in this repository that mutate the working tree while the gate exits 0 -- OpenRewrite's import-group churn (and its poisoning of the change-ledger freshness stamp), the pre-commit formatter's non-idempotency, and the SimplifyTestThrows reversion reached via JUnit5BestPractices -- the three consequences a contributor acts on, the revert rule with the objection to it and the standing fixed-point debt, the recipe-scoping trap, the non-gating rewrite-report job that reports all of it, the incremental-build rule, and the recorded discard of the fully-qualified-refspec fix. Add the matching row to the contributor guide's Contents table. Co-Authored-By: Claude <noreply@anthropic.com>
Add one section to the declared-limit assertion-coverage note carrying the three rules that motivate the matrix: the deletion discriminator (a parsed, schema-validated key with no production consumer is a silent security no-op, tested by asking whether deleting the key would turn anything red, with the note's own inert TLS protocol-floor row as the worked instance); that wiring an inert key is a behavioural flip for every consumer, so the first failing test is a sample of the dependant set rather than the whole of it, and a new assertion extends SingleSourceTlsContractTest instead of splitting the contract across a second file; and that an opt-in runtime feature needs a deployment-activation test, with TlsEdgeActivationWiringTest as the reference shape. The three marked blocks DescriptorInventoryWiringTest parses as its expected inventory are untouched; the integration-tests module suite is green. Co-Authored-By: Claude <noreply@anthropic.com>
Add one section to the Sonar quality-gate policy stating the two rules that answer the same question from opposite ends. A cosmetic sweep must stay out of the interior of uncovered branches, because Sonar's new-code window is the diff rather than its semantics -- a pure rename inside an uncovered catch block drags pre-existing uncovered lines into the pull request's coverage measurement. A finding inside the scanned surface but outside the declared write-boundary is dispositioned taken_into_account and reported as a named follow-up, never silently absorbed, because the widening is invisible in a gate result that only ever gets greener. Close with the page's own hygiene rule: cross-references here name documents and rules, never file:line anchors. The four-anchor deferral table that belongs here by subject is deliberately not landed -- its anchors no longer resolve and one now points at a comment recording the finding as fixed, so it is recorded as an omission with its reason rather than restored as a stale list. Co-Authored-By: Claude <noreply@anthropic.com>
… pointers The Playwright doc already carries the browser-policy rule and its generalisation; only the enumerated class was short. Add the two members it omitted -- cookie partitioning, and the navigation context a response arrives in (top-level redirect GET versus cross-site form POST) -- and state that this suite is the only gate in the repository covering that class. The navigation member is the one the page's own worked defect turned on, so the list now matches the story it sits under. Give the run-integration-tests skill the two cross-references it was missing: that a green RestAssured run here is not evidence about that class, and that a trimmed bring-up already has a working script rather than needing a Compose profile. Both are pointers -- each rule stays in the document that owns it. Co-Authored-By: Claude <noreply@anthropic.com>
CLAUDE.md is the scarcest surface in the repository, so only statements that apply to most work earn a line here. Three do, and each cross-references its detail page rather than restating it. Beside the -Werror prose in the Pre-Commit Process, where a reader already has the build gate in mind: a successful build is not evidence that work happened, and a gate that exits 0 can still have changed your files -- so a review-bot suggestion is verified by surviving the gate rather than by being implemented, and unrelated churn is reverted rather than committed. The mechanisms, the operational consequences and the recipe-scoping trap stay in doc/development/build-gate-discipline.adoc. With the testing standards: a configuration key that parses is not a configuration key that acts, discriminated by asking whether deleting the key would turn any test red. The worked instance stays in doc/development/declared-limit-assertion-coverage.adoc. Co-Authored-By: Claude <noreply@anthropic.com>
Three mechanisms in this repository mutate the working tree while the gate exits 0, and all three are invisible in the build result by construction. Add a rewrite-report job to the Maven workflow that runs the rewriting gate and prints, into the job summary, the post-gate git status --porcelain listing and every "Changes have been made to <file> by:" block with its recipe chain. The job is patterned on supply-chain-scan: no needs:, hardened runner, checkout without persisted credentials, and deliberately non-gating on its own verdict. It carries no continue-on-error, so a genuine Maven or tooling failure still turns the check red; only the dirty verdict is suppressed, and it is suppressed structurally -- no step asserts cleanliness, so there is no failing path to mask. shell: bash is load-bearing on both run steps: it selects pipefail, and without it the tee would swallow a Maven failure. -Ppre-commit is load-bearing too, and the leading comment says so: the recipe list that reaches all three mechanisms is the pre-commit profile's activeRecipes override, and without the profile the goal reports "Using active recipe(s) []" and exonerates OpenRewrite for free. The same comment records why this lane is deliberately not the positively-phrased fitness function ADR-0030 prescribes, and the condition under which it could become one. The job commits nothing and pushes nothing; the mutated tree lives only in the runner. Co-Authored-By: Claude <noreply@anthropic.com>
The page asserted that main is not at the OpenRewrite recipes' fixed point and recorded reaching it as unpaid debt. A whole-reactor verify -Ppre-commit run drives rewrite:run with the full pre-commit recipe list in every module, produces zero 'Changes have been made to' attributions and leaves the tree clean, so the premise was false. Restate every fixed-point passage as the current observed state plus the drift risk: the fixed point is a property of the tree at a point in time, lost silently the moment a change the recipes want to rewrite lands. The three mechanisms, the three operational consequences and the revert rule are unchanged; the revert rule's reasoning is re-grounded on that drift risk rather than on standing debt.
The job stays a report, not a gate; only its leading comment changes. The old rationale claimed a fail-on-dirty assertion would be red on every run for as long as main is not the formatter's fixed point, which is false - the tree is observed clean at the active recipes' fixed point. The real reason to stay non-gating is that the observation is not a guarantee: a hard gate would block every pull request from the moment any drift lands, including the ones that did not cause it. The comment now also names the condition under which the ADR-0030 fitness-function shape becomes the right call.
The rewrite-report job's ADR-0030 divergence comment restated, near-verbatim, the argument already carried by doc/development/build-gate-discipline.adoc while its own header comment declares that adoc as the home for the story. Collapse it to what is genuinely site-unique: the ADR-0030 summary, the divergence flag, the one-clause reason, the pointer, and the prohibition against converting the job into a hard gate. Comments only, no behaviour change. Also correct doc/development/README.adoc's "twelve-file descriptor surface" to thirteen. The page it describes states thirteen and that count is machine-checked by DescriptorInventoryWiringTest, so the README line was provably stale. Co-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe pull request documents browser-control coverage, adds non-gating OpenRewrite reporting to Maven CI, and expands contributor guidance for build gates, configuration assertions, and SonarCloud scope. ChangesBrowser-Control Test Coverage
Build-Gate Reporting and Discipline
Coverage and Scope Policies
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Reviewer Guide 🔍
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The awk-based extraction of recipe attribution from
rewrite-run.login therewrite-reportjob is tightly coupled to the current OpenRewrite/Maven log format; consider making the parsing more robust (e.g., anchoring on explicit markers or using a machine-readable output mode if available) to avoid breakage on minor log format changes. - The new
rewrite-reportjob runsrewrite:runon every workflow invocation, adding a non-trivial Maven execution; consider scoping this job to specific branches or events (e.g.,pull_requestonly, or main-protected branches) to keep CI time under control while still getting the intended visibility.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The awk-based extraction of recipe attribution from `rewrite-run.log` in the `rewrite-report` job is tightly coupled to the current OpenRewrite/Maven log format; consider making the parsing more robust (e.g., anchoring on explicit markers or using a machine-readable output mode if available) to avoid breakage on minor log format changes.
- The new `rewrite-report` job runs `rewrite:run` on every workflow invocation, adding a non-trivial Maven execution; consider scoping this job to specific branches or events (e.g., `pull_request` only, or main-protected branches) to keep CI time under control while still getting the intended visibility.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
The rewrite-report job died on its first CI run with
No plugin found for prefix 'rewrite'
after Maven Central answered 429 for org.openrewrite.maven/maven-metadata.xml.
Resolving a goal PREFIX requires that metadata fetch even though the plugin is
declared in the pre-commit profile, so the job carried a network dependency it
does not otherwise need and never reached the gate at all.
Invoke org.openrewrite.maven:rewrite-maven-plugin:run by full coordinates
instead. The version still resolves from the profile's own plugin declaration,
and no prefix metadata is fetched.
Verified locally: the run reports the full 19-recipe active list (not the
empty-recipe false negative the profile omission produces), exits 0, and leaves
the tree clean.
The job stays non-gating for the DIRTY VERDICT only; a genuine tooling failure
turning it red is the designed behaviour, and this run was exactly that.
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 7
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: cuioss/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 346a03d1-fdb4-44b1-abe1-8519148ecdb6
📒 Files selected for processing (8)
.claude/skills/run-integration-tests/SKILL.md.github/workflows/maven.ymlCLAUDE.mddemo-client/doc/playwright-suite.adocdoc/development/README.adocdoc/development/build-gate-discipline.adocdoc/development/declared-limit-assertion-coverage.adocdoc/development/sonar-quality-gate.adoc
Summary
Lands the twelve
repository sourcelessons drained from theapi-sheriff-roadmapcorpus into thenarrowest document or gate whose reader is the person about to make the mistake. One new
operator-approved page receives the build-gate cluster, five existing documents receive the rest,
and the one mechanism that can be enforced rather than merely stated becomes a non-gating
OpenRewrite dirty-tree report job in CI.
The change is subtractive as well as additive: lessons found already present in repository source at
HEAD are recorded as already-covered rather than restated, and where a rule was substantially
present already, only the missing members of its enumerated class were added — not a second copy of
the rule.
Changes
New page (the one approved new document)
doc/development/build-gate-discipline.adoc— the build-gate cluster: the quality gate'srewriting behaviour and its operational consequences, the single build-invocation rule, and the
two surviving halves of the fixed-point lesson together with the recorded discard verdict for the
half that did not survive verification.
doc/development/README.adoc— one row in the== Contentstable for the new page. The tableindexes every page in the directory, so omitting the row would silently misrepresent the set.
Existing documents
CLAUDE.md— three always-on statements only, integrated into the Pre-Commit Process sectionbeside the existing
-Werrorprose rather than appended blind: the general gate-mutation rule,the class statement it belongs to, and the one-line declared-versus-asserted discriminator.
doc/development/declared-limit-assertion-coverage.adoc— the declared-versus-asserted rulesbehind the coverage matrix, folded into the page that already owns that subject.
doc/development/sonar-quality-gate.adoc— the unowned-duplicated-state rule about line-numbercross-references.
demo-client/doc/playwright-suite.adoc— the browser-policy rule completed to its full enumeratedclass.
.claude/skills/run-integration-tests/SKILL.md— the two owed pointers: the compose--no-depscross-reference, and a pointer to the browser-policy boundary (the rule itself stays in the
Playwright doc, since this skill's subject is the
integration-testsstack, not demo-client).CI
.github/workflows/maven.yml— a newrewrite-reportjob that runs the rewriting gate andreports the resulting dirty tree plus the OpenRewrite recipe attribution. It is deliberately
non-gating, patterned on the existing
supply-chain-scanjob, including theexit-code: 0-not-continue-on-errordistinction that keeps a broken tool red while suppressingthe verdict. No CI lane ran the rewriting gate before this PR, so this job is what first brings
the OpenRewrite mutation under CI observation.
Test Plan
verify -Ppre-commit) green at6a8100a, tree clean post-gaterewrite-reportjob observed on this PR's first CI run (the job is new and has never executed)Related Issues
None.
Generated by plan-finalize skill
Intent
The problem. Twelve hard-won lessons lived only in a drained lessons corpus. A lesson nobody
reads changes no behaviour: the person about to re-make the mistake reads
CLAUDE.md, adoc/development/page, or a CI failure — never the corpus. Landing them is what turns recordedexperience into something that actually intercepts the next occurrence.
The chosen approach. Each rule goes into the narrowest document whose reader is the person at
risk, and nowhere else — stated once, cross-referenced elsewhere, never restated. Where a lesson can
be enforced rather than merely written down, it is enforced: the OpenRewrite dirty-tree finding
becomes a real CI job instead of a paragraph. Every premise was re-probed at HEAD before landing, so
two lessons already satisfied by repository source are recorded as already-covered instead of
duplicated, one refuted claim is discarded with the verdict recorded, and no landed text carries a
file:lineanchor — that anchor style is itself one of the lessons being landed, and this planfound a live instance of it going stale mid-flight.
The new CI job is deliberately non-gating.
mainis not the formatter's fixed point today, so ablocking form would be red on every run and would be disabled within a week; a report that is always
visible and never blocks is the form that survives. It follows the existing
[Intent truncated — 1373 of 2155 characters shown; full outline in the plan workspace]
Summary by CodeRabbit
Documentation
CI