Commit ced9cb6
Say what the container-equality fix actually changed, and pin a hash that can move
Review of the fix commit found it correct and under-described, which for a
change that widens what matches is most of the way to being a defect. The
explanation was entirely about decimal scale -- the commit message, the Javadoc,
the spec amendment and all six tests -- and decimal scale is only part of what
moved.
Jackson's node equality is representation equality: it separates IntNode from
DoubleNode from DecimalNode, and from Jackson 3 one DecimalNode scale from
another. Section 2.6.1 puts all of them in one {number} class. So delegating
container equality to Jackson was never the same predicate, and three things
changed when it stopped:
{a: 100.00} vs {a: 100.0} unequal -> equal (Jackson 3 regression)
{a: 1} vs {a: 1.0} unequal -> equal (Jackson 2 did this too)
{a: NaN} vs {a: NaN} equal -> unequal (went the other way)
Only the first was caused by the migration. The second is older and needs no
BigDecimal to reach -- readTree on ordinary JSON produces it -- so the blast
radius is wider than the money example implied, and the previous commit's claim
that DecimalNodes do not come from readTree was true of the reported bug and
misleading about the fix. The third is a narrowing, and it is what the scalar
path always did. All three now answer the way the scalar path answers, which is
the point; the amendment tabulates them rather than leaving a reader to infer
the second from a sentence about money.
That direction matters enough to state twice. This widens what matches, and
section 2.6.1's design exists largely to stop rules quietly matching more than
they say. Correct behaviour arriving unannounced is still unannounced.
Three tests added for the three cases the old set could not have caught:
cross-representation equality from readTree, NaN, and IN/NOT_IN -- the last
because section 2.6.1 defines IN as EQ against each element, so it inherits all
of this through one comparator. It cannot drift, but "cannot drift" is a claim
about today's call graph and IN is the operator an author actually reaches for.
The pinned version hash was also too narrow to do its job. It covered strings
and integers, which are exactly the node kinds whose rendering will not move,
and omitted decimals, escaped and non-ASCII strings, containers, and tags --
tags being the one canonicalisation bug this project has actually shipped, since
canonicalise sorts them through a TreeSet to keep Set.copyOf's per-JVM salt out
of the hash. A pin that cannot catch what it was built to catch reads like
coverage while providing none. The fixture now carries all of them, and
perturbing a decimal's scale or a tag's spelling moves the hash as it should.
Also from the review: nodesEqual documents why it has no `left == right` fast
path, which looks free and is not -- with two NaNs unequal, a reference check
would make a node equal to itself while unequal to a structurally identical
twin, an identity-dependent answer worse than the depth exposure it saves; the
two spellings of the numeric predicate, compareTo() == 0 for containers and
stripTrailingZeros().equals() for scalars, now point at each other, since the
whole fix rests on them agreeing and no test compares them directly; the
performance note no longer implies the walk is free at the leaf, because a
numeric comparison allocates where IntNode.equals was a primitive compare; two
duplicate imports left by the previous commit's re-sort are gone, the sort now
deduplicating as well as ordering; and three comment lines it pushed past the
hundred-column limit are rewrapped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbNTKG6shEcXad7hpeUBkN1 parent 1813457 commit ced9cb6
5 files changed
Lines changed: 126 additions & 21 deletions
File tree
- docs
- rule-engine-core/src/main/java/com/codeheadsystems/rules/value
- rule-engine-dsl/src/main/java/com/codeheadsystems/rules/dsl
- rule-engine-testkit/src/test/java/com/codeheadsystems/rules/testkit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
451 | 451 | | |
452 | 452 | | |
453 | 453 | | |
454 | | - | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
455 | 467 | | |
456 | 468 | | |
457 | 469 | | |
| |||
Lines changed: 44 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
128 | 140 | | |
129 | 141 | | |
130 | 142 | | |
131 | | - | |
132 | | - | |
133 | | - | |
| 143 | + | |
| 144 | + | |
134 | 145 | | |
135 | | - | |
136 | | - | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
137 | 151 | | |
138 | 152 | | |
139 | 153 | | |
| |||
168 | 182 | | |
169 | 183 | | |
170 | 184 | | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
171 | 194 | | |
172 | | - | |
173 | | - | |
174 | | - | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
175 | 204 | | |
176 | 205 | | |
177 | 206 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
139 | | - | |
| 139 | + | |
| 140 | + | |
140 | 141 | | |
141 | 142 | | |
142 | 143 | | |
| |||
Lines changed: 18 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
346 | 346 | | |
347 | 347 | | |
348 | 348 | | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
349 | 359 | | |
350 | 360 | | |
| 361 | + | |
| 362 | + | |
351 | 363 | | |
352 | | - | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
353 | 368 | | |
| 369 | + | |
354 | 370 | | |
355 | 371 | | |
356 | 372 | | |
357 | 373 | | |
358 | 374 | | |
359 | 375 | | |
360 | 376 | | |
361 | | - | |
| 377 | + | |
362 | 378 | | |
363 | 379 | | |
364 | 380 | | |
| |||
Lines changed: 49 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
19 | | - | |
20 | 18 | | |
21 | 19 | | |
22 | 20 | | |
| |||
282 | 280 | | |
283 | 281 | | |
284 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
285 | 332 | | |
286 | 333 | | |
287 | 334 | | |
| |||
0 commit comments