Repository navigation
core: write every number in the report in its plain form - #158
Merged
Merged
Conversation
OPA keeps a number as it was written, so `1.50` in the input came out as `1.50` in the report, while JavaScript or Rust write `1.5`. The same policy and input could give different bytes depending on how a number was typed, and a repeated id like `1.0` and `1e0` was listed with whichever spelling came first. ergo now writes every number in the report the way expressions already do: `1.50`, `-0.0` and `1e2` come out as `1.5`, `0` and `100`. A number a 64-bit float can't hold, like `1e400`, is kept as written, since #89 is still open. A report holding something JSON can't, like a set from a Rego input, is left as built, so its rows still name their requirement. Changes the report: numbers in checks, `$refs`, `inputs`, subject ids, `failed_items` and violations are written in their plain form. Fixes #152 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Most reports have no number written in another form, so ergo now looks for one in the JSON first and only rewrites the numbers when it finds one. Values JSON can't hold are spotted from the input, the params and the policy rather than by comparing the whole report after the rewrite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jbpros
marked this pull request as ready for review
October 7, 2026 21:01
jbpros
added a commit
that referenced
this pull request
Oct 7, 2026
Extracts the cases again after #155, #156 and #158, leaving out policies that aren't objects, since their reports use numbers as keys. The Rust port now writes every number in its plain form, as #158 does, and its runner compares number text exactly to check it. generate.sh lets OPA write each file's text, because jq rewrote numbers like 0.000000123 as 1.23E-7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OPA keeps a number as it was written, so the same policy and input could give different report bytes depending on how a number was typed, or on which implementation ran it. Fixes #152.
With this input:
{"items": [{"id": 1.0, "n": 1.50, "xs": [2.0, 3e0, 2.5e-3]}, {"id": 1e0, "n": -0.0, "xs": []}]}params
{"p": 2.50}, and checksn == 1.50,nin range-0.0to1e1,n == $$params.pandevery xs[] == 9.0, main writes1.50,1.0,1e0,3e0,2.5e-3,-0.0and2.50across the checks,$refs,inputs, subject ids,failed_itemsand$unique_ids. The branch writes1.5,1,3,0.0025,0,2.5and10, and$unique_idsgives[1]whichever spelling comes first.How: after building the report, ergo writes it with
json.marshaland looks for a number written in another form. Most reports have none, and they're returned as they are. Otherwise each number is rewritten with the same printer expressions use, and the text is read back. Two exceptions:1e400, stays as written. core: say how a number from the input or params that a 64-bit float can't hold is reported #89 is still open, and writing1e1000000out in full would make a million-character string.Changes the report: numbers in checks,
$refs,inputs, subject ids,failed_itemsand violations are written in their plain form.What I ran
Every check in
AGENTS.md, plus Wasm (Docker, OPA 1.19.0) and the JS runtime script: 898/898 each. OPA 1.20.2 in Docker passesfmtand the tests.Three of the six new tests fail on main. The others pin what stays the same:
1e400copied as written, and reports built from values JSON can't hold. Each guard in the new code has a test that fails when it's removed.One gotcha: comparing
json.marshalof two reports whose inputs differ only in number spelling doesn't work as a test, because OPA caches function calls by value and1.50 == 1.5. Both calls return the same cached report. The tests compare against literal JSON instead.All 1,683 conformance cases from the
core/conformance-suitebranch give the same report by value on main and on this branch. About 20 of them have a non-plain number in the expected report, so they'll need regenerating after this lands.sdlc-policies, pr-reviewer and the server's npm-bump tests: the same 9 failures on main and on this branch (from earlier PRs), nothing new. npm-bump passes on both.
Speed, best of 5 runs on 3,000 subjects: 1.93s on main and 2.04s here when every row has a number to respell, 1.96s and 2.00s when none does. The whole test suite takes 11.4s against 11.2s on main.
Tests cover the change, and the checks in
AGENTS.mdpassREFERENCE.mdandREADME.mdare updated if behaviour changedIf the report changes for an existing policy, the description has a line starting with
Changes the report:🤖 Generated with Claude Code