Files
agiledancers/specs/refined/S8_palentir-formatting-be
Wanja Krah b0c2f28e13
All checks were successful
Build, test and publish / verify (push) Successful in 1m21s
specs
2026-10-29 19:35:10 +01:00

199 lines
9.7 KiB
Plaintext

# S8 — Palantir formatting for Java
Status: REFINED
Agreed after the grill-me review; shared understanding confirmed.
## User story
As a developer, I want maintained Java code formatted using Palantir Java Format
through the Maven workflow, so that local development and CI use consistent,
reproducible formatting without unnecessary build overhead.
## Scope
### In scope
- Backend Java production code and Java tests.
- Maintained Java CI/source-launcher helpers under `ci/`, despite those files
being outside ordinary Maven source roots.
- Integration with local Maven builds, CI checking and standalone format/check
commands.
- A separate initial formatting commit, performance measurements and README
instructions.
### Out of scope
- Generated code and build output.
- Frontend formatting, which remains under Prettier.
- Additional coding conventions, naming rules, structural checks or refactorings.
Those belong in S7.
## Formatter and integration
- Use the **actual Palantir Java Format engine** and its Palantir style.
- OpenRewrite is the preferred integration route. S8 includes the custom
Palantir adapter/recipe and bootstrap required to make that route work.
- OpenRewrite's own `AutoFormat` is not an equivalent replacement for Palantir
and must not be substituted silently.
- Spotless is not the agreed default: the maintainer has experienced unacceptable
slowness with it. Do not choose it merely because a native integration exists.
- Pin the formatter, plugin and adapter dependencies to explicit versions in
Maven configuration. Local development and CI use the same pinned engine.
- Formatter/integration updates are reviewed through PRs and include any resulting
formatting changes. Do not implicitly resolve the newest formatter at build time.
- Include Palantir's import ordering and unused-import removal. Do not add
separate import policies or unrelated code transformations.
- Leave optional extra Javadoc reformatting disabled for the initial adoption.
## Maven behavior
### Local builds
Local builds apply formatting before compilation, so the compiled and tested
sources are the formatted sources. Early lifecycle integration means ordinary
`mvn compile`, `mvn test`, `mvn verify` and `mvn install` may format maintained
Java files.
Binding only to `install` does not satisfy this specification: the existing CI
verification uses `mvn clean verify` and would not reach that phase.
Provide standalone commands to:
- Apply formatting without performing the complete application build.
- Check formatting without modifying maintained sources or performing the complete
application build.
The concrete commands/profile names are implementation work and must be documented.
### CI
- CI runs the check-only mode before compilation and fails if formatting differs
from the committed source.
- CI must not repair or rewrite maintained Java source files automatically.
- Use the same pinned Palantir engine, configuration and file scope locally and
in CI; only apply versus check behavior differs.
- Integrate the checking invocation into the existing Java-based CI orchestration.
- Show actionable diagnostics identifying the files that need formatting and how
to apply the formatter locally.
- A formatting failure prevents successful verification and image publication.
Demonstrate that the check leaves maintained source files unchanged on failure.
## Clean-checkout bootstrap
Normal Maven commands from the repository root must work from a clean checkout
without first requiring a developer to compile or install a custom recipe artifact
by hand.
The custom recipe/adapter must be available before it is needed to format the
application sources. Placing it in ordinary backend source code and assuming that
it has already been compiled is not a valid bootstrap solution.
Prove bootstrap behavior with no previously installed project-specific recipe
artifact. Normal dependency resolution is allowed; any extra tooling module or
bootstrap must be included in the implementation and documentation.
## Correctness and Java 25
- Demonstrate support for every Java construct actually used in the maintained
backend, tests and CI helpers on the project's JDK 25.
- Running the formatter on JDK 25 is not, by itself, proof that its parser supports
every possible Java 25 construct. Record relevant limitations of the chosen
pinned version.
- An unprocessable file or formatter error fails the operation/build with its
path and a concrete cause. Do not silently skip it or exclude it merely to
obtain a successful build or faster measurement.
- The adapter must preserve source paths and encoding and avoid corrupting files.
- Formatting is deterministic and idempotent: applying it again produces no
further source differences. Check-only and apply mode agree on the result.
- Application behavior remains unchanged; builds and tests must pass after the
initial formatting and subsequent formatter changes.
## Initial adoption and commit separation
Apply the chosen formatting to all existing maintained Java files in scope.
Record this initial mass formatting in a separate **formatting-only commit**,
without functional changes. Keep integration/configuration changes separate so
reviewers can distinguish tooling changes from the mechanical source rewrite.
Native import ordering/removal is part of that formatting commit. Do not combine
it with unrelated cleanup or refactoring.
## Performance requirements
The integration must be measured rather than selected on an unverified claim that
one wrapper is faster than another.
- A repeated ordinary build with no Java-source changes may incur at most
**three seconds of additional formatting-related overhead**.
- Include the required integration/recipe/bootstrap overhead in that comparison;
do not report only time spent inside the Palantir formatting function.
- Compare otherwise equivalent builds with and without the formatting integration
under the same environment/cache conditions.
- Also measure a build after changing a maintained Java file and a `clean verify`
run. Record these timings; the agreed three-second threshold specifically
applies to the repeated unchanged-build case.
- Report one-time dependency downloads separately, rather than disguising ongoing
overhead as first-time setup or counting downloads as formatter execution.
- Record the machine, JDK/Maven/tool versions, commands, file scope, cache state
and results with the implementation evidence.
The time threshold is an acceptance criterion, not a hard interrupt that kills a
formatter while it is writing source files. If the selected integration cannot
meet the threshold, report the measurements and obtain agreement before choosing
an alternative integration or relaxing the bound. Do not silently skip formatting,
switch engines, choose Spotless or weaken the criterion.
## README and editor integration
Explain in the root `README.md`:
- The formatter, pinned versions/configuration and maintained file scope.
- The standalone apply and check commands.
- Which local Maven lifecycle commands can rewrite files and when that occurs.
- The CI check-only invocation and how to reproduce and resolve a failure locally.
- Clean-checkout bootstrap behavior and any included tooling artifact/module.
- Available supported IDE integration and how to keep its result consistent with
the project's pinned formatter.
- The performance evidence and any relevant Java 25 syntax limitations.
Maven is the authoritative formatting path regardless of editor. Do not require
format-on-save or an IDE plugin. An IDE integration must not redefine the agreed
style or silently take precedence over the Maven result.
## Acceptance criteria
- [ ] The actual Palantir engine formats all maintained backend Java sources,
Java tests and `ci/*.java`; generated code is excluded.
- [ ] OpenRewrite integration, custom adapter/recipe and bootstrap are implemented
and reproducible from a clean checkout without manual recipe installation.
- [ ] Plugin, formatter and adapter dependencies are pinned, with matching local
and CI configuration.
- [ ] Local Maven builds apply formatting before compilation; `compile`, `test`,
`verify` and `install` reach the intended integration.
- [ ] Standalone apply and check commands work without the full application build.
- [ ] CI checks only, leaves maintained sources unchanged, reports formatting
differences and fails before image publication.
- [ ] Import ordering and unused-import removal follow Palantir; optional extra
Javadoc reformatting remains disabled and no unrelated refactoring is added.
- [ ] All currently used Java 25 syntax is handled, or causes an explicit failure
requiring resolution rather than silent exclusion.
- [ ] Apply/check results agree and a second apply produces no differences.
- [ ] Initial formatting is isolated in a formatting-only commit; application
builds and tests remain green.
- [ ] Equivalent repeated unchanged-build measurements demonstrate at most three
seconds of additional integration overhead. Changed-file and clean-build
measurements and one-time downloads are reported separately.
- [ ] Failure to meet the performance bound is reported before changing the route
or bound; a writing formatter is not killed to force compliance.
- [ ] README instructions cover local and CI commands, bootstrap, optional IDE
use, authoritative Maven formatting and verification evidence.
## Implementation handoff
This specification records agreed behavior. It does not install a formatter,
create an adapter, change Maven/CI behavior or reformat source files. Recipe loading,
Java 25 compatibility and performance must be demonstrated during implementation;
there is no pre-existing project benchmark establishing the preferred route's
performance.