Skip to content

Integrate official Draft 2020-12 Basic output tests and preserve annotation value shapes - #978

Open
HarshPopat23 wants to merge 1 commit into
sourcemeta:mainfrom
HarshPopat23:feat-draft2020-12-basic-output-tests
Open

Integrate official Draft 2020-12 Basic output tests and preserve annotation value shapes#978
HarshPopat23 wants to merge 1 commit into
sourcemeta:mainfrom
HarshPopat23:feat-draft2020-12-basic-output-tests

Conversation

@HarshPopat23

@HarshPopat23 HarshPopat23 commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR integrates the official JSON Schema Draft 2020-12 Basic output test suite into Blaze and fixes an annotation value shaping issue in Standard Basic output.

Changes

  1. Unmask Official Output Tests:
    • Updated vendor/jsonschema-test-suite.mask to unmask output-tests/draft2020-12/ (escape.json, general.json, readOnly.json, type.json, and output-schema.json), while keeping other drafts and formats masked.
  2. Preserve Annotation Shapes:
    • Added is_array_aggregated_keyword() helper in src/output/output_standard.cc and ports/javascript/index.mjs.
    • Collection/aggregation keywords (properties, patternProperties, additionalProperties, unevaluatedProperties, contains) continue to emit array annotations (unknown[]).
    • Scalar / metadata keywords (readOnly, title, description, default, etc.) now emit their scalar / JSON value shape (annotation.second.back()) rather than wrapping them into arrays.
  3. Official Test Suite Runner:
    • Added test/output/output_official_draft2020_12_suite.cc registered in test/output/CMakeLists.txt to execute all official Draft 2020-12 content output tests against output-schema.json.
  4. TypeScript Definitions & JavaScript Port:
    • Updated StandardOutputAnnotationEntry.annotation type from unknown[] to unknown in ports/javascript/index.d.mts.
    • Updated SimpleOutput.toBasic in ports/javascript/index.mjs to match the C++ output shaping.
  5. Fixtures & Cleanups:
    • Updated test/output/output_standard_basic.json for scalar title annotations.
    • Removed the resolved TODO for official output tests in src/output/include/sourcemeta/blaze/output_standard.h while keeping Detailed/Verbose TODOs.

Verification

  • Official Draft 2020-12 Output Suite: 4/4 passed (100%)
  • Local Basic & Flag Output Suites: 58/58 passed, 28/28 passed
  • Output Unit Suite: 673/673 passed
  • Evaluator Annotation & Trace Suites: 6/6 passed
  • JavaScript Output Tests: Passed

Review in cubic

@augmentcode

augmentcode Bot commented Aug 22, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR integrates the Draft 2020-12 Basic-output conformance fixtures and aligns annotation values with the JSON Schema output model.

Changes:

  • Unmasks the Draft 2020-12 output-test assets while keeping unrelated suites masked.
  • Adds a C++ runner that validates Blaze Basic output against each official expected output schema.
  • Changes standard-output formatting so scalar annotations retain their JSON value instead of becoming singleton arrays.
  • Preserves array-valued annotations for property- and contains-style aggregation keywords.
  • Mirrors the shaping logic in the JavaScript port and widens its TypeScript declaration to unknown.
  • Updates shared Basic-output fixtures for scalar title annotations.
  • Adds a Windows UCRT build candidate for the JavaScript compiler wrapper.
Technical notes: The official runner resolves the output schema locally and exercises the suite in exhaustive mode; existing Basic fixtures continue to cover C++ and JavaScript output parity.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 14 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread test/output/output_official_draft2020_12_suite.cc Outdated
Comment thread ports/javascript/compile.mjs Outdated
@HarshPopat23
HarshPopat23 force-pushed the feat-draft2020-12-basic-output-tests branch from bd88e32 to 63a88ab Compare August 22, 2026 13:58
@HarshPopat23

Copy link
Copy Markdown
Collaborator Author

Hi @jviotti,

All CI checks (Linux, macOS, Windows, ASan, DCO, CLA) are now passing green.

Summary of Changes:

  • Official Test Suite Integration: Unmasked and integrated the official Draft 2020-12 Basic output tests (vendor/jsonschema-test-suite/output-tests/draft2020-12) with a dedicated C++ test runner in test/output/output_official_draft2020_12_suite.cc.
  • Annotation Serialization Alignment: Fixed annotation serialization in Standard Basic output to preserve scalar JSON values (e.g. title, description, default, readOnly) while maintaining array aggregation for collection keywords (properties, patternProperties, additionalProperties, unevaluatedProperties, contains).
  • JS / TS Port Sync: Updated the TypeScript definitions and JavaScript port accordingly to match the standardized output shape.

Whenever you have a moment, could you please take a look? Thanks!

Comment thread test/output/output_official_suite.cc
Comment thread vendor/jsonschema-test-suite.mask Outdated
bin
output-tests
output-tests/README.md
output-tests/draft2019-09

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do this one too? Or is it different?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unmasked output-tests/draft2019-09 as well! Both 2019-09 and 2020-12 follow the same Basic output format specification. Both official suites are now unmasked and passing in output_official_suite.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep the JS port outside of this to begin with, as we are not running those in the suite? i.e. we can focus on pinning this down for C++ first, and then doing the JS changes?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We noticed that CI executes node --test "ports/javascript/*.test.mjs" on Linux and macOS, where ports/javascript/output.test.mjs directly runs test/output/output_standard_basic.json.

Because output_standard_basic.json was updated to reflect standard scalar annotations, keeping ports/javascript/index.mjs in sync with the C++ engine's annotation format is required for output.test.mjs and the CI matrix to pass.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by these changes. Does the schema say annotation cannot be an array?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the JSON Schema Specification (Section 12.3 Basic format & official output-schema.json), annotation is defined without restricting its value type (it can be any valid JSON value, depending on what the keyword produces):

  • Collection keywords that aggregate multiple evaluated items (e.g. properties, patternProperties, additionalProperties, unevaluatedProperties, contains) produce a JSON array of values (e.g. array of evaluated property names or item indices).
  • Scalar / leaf keywords with a single value (such as title, description, default, readOnly: true, etc.) produce their raw scalar value directly (true, "foo", 42), not wrapped in a single-element array (["foo"], [true]).

Previously, Blaze was wrapping all scalar annotations into single-element arrays [annotation], which caused official tests such as readOnly.json to fail schema validation (since the test expects "annotation": true, not "annotation": [true]). The fix preserves raw scalar values for non-collection keywords while retaining array aggregation for keywords that produce collections.

@HarshPopat23
HarshPopat23 force-pushed the feat-draft2020-12-basic-output-tests branch 3 times, most recently from 276fc1c to 40f1409 Compare August 24, 2026 15:59
@HarshPopat23

Copy link
Copy Markdown
Collaborator Author

Hey @jviotti ,
I have tried to solve suggestions.
waiting for further guidelines.

Comment thread ports/javascript/compile.mjs Outdated
resolve(PROJECT_ROOT, 'build/bin/Release', BINARY_NAME + '.exe'),
resolve(PROJECT_ROOT, 'build/bin/Debug', BINARY_NAME + '.exe')
resolve(PROJECT_ROOT, 'build/bin/Debug', BINARY_NAME + '.exe'),
resolve(PROJECT_ROOT, 'build-ucrt/bin', BINARY_NAME + '.exe')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unrelated?

return false;
}
const auto &keyword{evaluate_path.back().to_property()};
return keyword == "properties" || keyword == "patternProperties" ||

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read your explanation on https://github.com/sourcemeta/blaze/pull/978/changes#r3845621857. Interesting finding....

The main problem I'm considering now is that:

  • Doing these string checks for EVERY annotation can be catastrophic on some larger validation pipelines in terms of performance
  • Checking against names is also not 100% correct. For example, what if you have a custom 2020-12 dialect without the unevaluated vocabulary? An annotation would be emitted for i.e. unevaluatedProperties even though it would be an "unknown" annotation and not the legit one from this keyword. Essentially, vocabularies can make this check wrong

Here is what I propose we try:

Can you try to modify this file so that it ALWAYS stores whatever value directly. If we try to store another one to the SAME place, then it gets converted into an array? Would that be a way out of this?

@jviotti jviotti Aug 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the vocabulary cases I just talked about could make good new tests for the standard basic tests. I bet we are not covering those edge cases, though we should

@HarshPopat23
HarshPopat23 force-pushed the feat-draft2020-12-basic-output-tests branch from 40f1409 to e8f8e30 Compare August 27, 2026 16:48

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 19 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="test/output/output_standard_basic_test.cc">

<violation number="1" location="test/output/output_standard_basic_test.cc:39">
P1: This test encodes a shape that violates the official Draft 2020-12 Basic output format. The `properties` keyword's annotation is defined as an array of matching property names, so a single matched property must emit `["foo"]`, not the scalar `"foo"` asserted here. The actual `handle_standard` in src/output/output_standard.cc uses a size heuristic (`size() == 1 ? front() : array`), and the `is_array_aggregated_keyword()` function described in the PR was never added, so aggregated keywords with one value unwrap to a scalar and the output no longer matches the spec (and single scalar keywords such as readOnly with repeated values would inflate into arrays). Correct the implementation to emit the aggregation-array shape for properties/patternProperties/additionalProperties/unevaluatedProperties/contains and update these fixture expectations to match the official suite.</violation>
</file>

<file name="test/output/output_standard_basic.json">

<violation number="1" location="test/output/output_standard_basic.json:18">
P2: This fixture now expects the `/properties` annotation to be the scalar `"foo"` instead of `[ "foo" ]`, which contradicts the PR's stated goal that aggregation keywords such as `properties` continue emitting array annotations, and the 2020-12 spec where the `properties` annotation is a set (array) of matched property names. A single matching property must produce `[ "foo" ]`, not `"foo"`; only scalar/metadata keywords (title, readOnly, default, etc.) should be flattened. Please confirm the intended shape — if `properties` should remain an array, this expectation (and the size==1 flattening in output_standard.cc that drives it) is wrong.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

"absoluteKeywordLocation": "#/properties",
"instanceLocation": "",
"annotation": [ "foo" ]
"annotation": "foo"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This test encodes a shape that violates the official Draft 2020-12 Basic output format. The properties keyword's annotation is defined as an array of matching property names, so a single matched property must emit ["foo"], not the scalar "foo" asserted here. The actual handle_standard in src/output/output_standard.cc uses a size heuristic (size() == 1 ? front() : array), and the is_array_aggregated_keyword() function described in the PR was never added, so aggregated keywords with one value unwrap to a scalar and the output no longer matches the spec (and single scalar keywords such as readOnly with repeated values would inflate into arrays). Correct the implementation to emit the aggregation-array shape for properties/patternProperties/additionalProperties/unevaluatedProperties/contains and update these fixture expectations to match the official suite.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/output/output_standard_basic_test.cc, line 39:

<comment>This test encodes a shape that violates the official Draft 2020-12 Basic output format. The `properties` keyword's annotation is defined as an array of matching property names, so a single matched property must emit `["foo"]`, not the scalar `"foo"` asserted here. The actual `handle_standard` in src/output/output_standard.cc uses a size heuristic (`size() == 1 ? front() : array`), and the `is_array_aggregated_keyword()` function described in the PR was never added, so aggregated keywords with one value unwrap to a scalar and the output no longer matches the spec (and single scalar keywords such as readOnly with repeated values would inflate into arrays). Correct the implementation to emit the aggregation-array shape for properties/patternProperties/additionalProperties/unevaluatedProperties/contains and update these fixture expectations to match the official suite.</comment>

<file context>
@@ -36,7 +36,50 @@ TEST(prettify_annotations) {
       "absoluteKeywordLocation": "#/properties",
       "instanceLocation": "",
-      "annotation": [ "foo" ]
+      "annotation": "foo"
+    }
+  ]
</file context>

Comment thread ports/javascript/index.mjs Outdated
Comment thread test/output/output_standard_basic.json Outdated
"absoluteKeywordLocation": "#/properties",
"instanceLocation": "",
"annotation": [ "foo" ]
"annotation": "foo"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This fixture now expects the /properties annotation to be the scalar "foo" instead of [ "foo" ], which contradicts the PR's stated goal that aggregation keywords such as properties continue emitting array annotations, and the 2020-12 spec where the properties annotation is a set (array) of matched property names. A single matching property must produce [ "foo" ], not "foo"; only scalar/metadata keywords (title, readOnly, default, etc.) should be flattened. Please confirm the intended shape — if properties should remain an array, this expectation (and the size==1 flattening in output_standard.cc that drives it) is wrong.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/output/output_standard_basic.json, line 18:

<comment>This fixture now expects the `/properties` annotation to be the scalar `"foo"` instead of `[ "foo" ]`, which contradicts the PR's stated goal that aggregation keywords such as `properties` continue emitting array annotations, and the 2020-12 spec where the `properties` annotation is a set (array) of matched property names. A single matching property must produce `[ "foo" ]`, not `"foo"`; only scalar/metadata keywords (title, readOnly, default, etc.) should be flattened. Please confirm the intended shape — if `properties` should remain an array, this expectation (and the size==1 flattening in output_standard.cc that drives it) is wrong.</comment>

<file context>
@@ -15,7 +15,31 @@
           "absoluteKeywordLocation": "#/properties",
           "instanceLocation": "",
-          "annotation": [ "foo" ]
+          "annotation": "foo"
+        }
+      ]
</file context>
Suggested change
"annotation": "foo"
"annotation": [ "foo" ]

Comment thread src/output/output_standard.cc Outdated
Signed-off-by: HarshPopat23 <musichk61@gmail.com>
@HarshPopat23
HarshPopat23 force-pushed the feat-draft2020-12-basic-output-tests branch from e8f8e30 to 481dc7a Compare August 27, 2026 19:04
@HarshPopat23

Copy link
Copy Markdown
Collaborator Author

Hi @jviotti,

Here is a summary of the updates in the latest commit:

  1. Deterministic Annotation Shapes (Spec Compliance):
    • Collection/aggregation keywords (properties, patternProperties, additionalProperties, unevaluatedProperties, contains) now consistently emit JSON array annotations (e.g. ["foo"], [2]), adhering strictly to the Draft 2019-09 & 2020-12 Basic Output specifications.
    • Scalar/metadata keywords (readOnly, title, description, default, etc.) emit their raw JSON values directly (e.g. true, "My Title") without array wrapping.
  2. Synchronized JavaScript Port:
    • Mirrored the same annotation shaping logic in ports/javascript/index.mjs (SimpleOutput.toBasic()).
  3. Cleaned Candidate Paths:
    • Removed the unrelated build-ucrt/bin path candidate from ports/javascript/compile.mjs.
  4. Test Fixtures & Suite Coverage:
    • Updated test fixtures (output_standard_basic.json) and unit tests (output_standard_basic_test.cc) to cover both single-item collections (["foo"], [2]), multi-item collections (["bar", "foo"]), and scalar annotations (readOnly: true).

All test suites (Official Draft 2019-09 & 2020-12 output suites, standard basic/flag suites, all 674 C++ output unit tests, and the JS test suite) are passing green.

PTAL and i was busy with meets since 2 days sorry for delay and guide me if i have missed somthing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants