> go back later and add logic to getting and setting
Which, realistically, you're virtually never going to do - at least not often enough to justify the boilerplate and especially in the case of things like "records" which were probably auto-generated from a schema (with obligatory getters and setters) anyway. If you did, you'd end up confusing all of your callers who probably wrote client code presuming that what they provided in the setter was going to be exactly what they get back in the getter.
This is true, until you're writing a library that's pulled from a repository and used in several projects.
If you can't guarantee you're not going to break someone else's code by changing:
foo.x to foo.getX();
then you should stick with properties. Now, for staying inside a single package, or a single compiled unit, then what you say is reasonable enough. I'd still prefer to write the getters and setters, though, especially in cases where it's free, like Kotlin.
It would be better if the default were to not write setters or getters for any properties by default, but instead to write a logical interface that properly encapsulates the properties. Unfortunately, that ship sailed a long time ago for Java.
Which, realistically, you're virtually never going to do - at least not often enough to justify the boilerplate and especially in the case of things like "records" which were probably auto-generated from a schema (with obligatory getters and setters) anyway. If you did, you'd end up confusing all of your callers who probably wrote client code presuming that what they provided in the setter was going to be exactly what they get back in the getter.