feat(gts-macros): added const_values, new_instance_with_defaults(), and parent metadata#64
feat(gts-macros): added const_values, new_instance_with_defaults(), and parent metadata#64Artifizer wants to merge 0 commit intoGlobalTypeSystem:mainfrom
Conversation
📝 WalkthroughWalkthroughThis PR introduces Changes
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (1)
gts-macros/src/lib.rs (1)
1686-1688: Redundantis_unit_structredefinition.This variable is already computed earlier (line 1017 as
struct_fields.is_none()), and this line shadows it with an equivalent check. Consider reusing the existing variable instead of recomputing.♻️ Suggested simplification
- // Check if this is a unit struct - we need to add an allow attribute for clippy - // because quote! may emit {} instead of ; for unit structs - let is_unit_struct = matches!(&input.data, Data::Struct(data_struct) if matches!(&data_struct.fields, Fields::Unit)); + // is_unit_struct was already computed above (line 1017)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gts-macros/src/lib.rs` around lines 1686 - 1688, Remove the redundant shadowing definition of is_unit_struct and reuse the earlier computed value based on struct_fields (i.e., struct_fields.is_none()) instead of re-checking matches!(&input.data, Data::Struct(...) if matches!(&data_struct.fields, Fields::Unit)); delete the let is_unit_struct = ... line and update any subsequent references to use the existing struct_fields.is_none() (or the previously defined is_unit_struct) so you don't recompute/mask the value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@gts-cli/src/gen_schemas.rs`:
- Around line 460-471: After parsing attributes with
parse_macro_attrs(attr_body) you must validate that base structs do not have
const_values: after let Some(attrs) = parse_macro_attrs(attr_body) else { ... }
add a check that if attrs.base == BaseAttr::IsBase and
attrs.const_values.is_some() then return or emit a CLI error (matching the macro
behavior) instead of silently ignoring; update the error path to include context
(struct name from the parsed item) so the CLI rejects the input consistently
with the macro.
- Around line 438-449: The current Pass 1 loop that builds gts_schema_id_field
(in gen_schemas.rs) blindly maps struct_name -> field_name and overwrites when
multiple GtsSchemaId fields exist; change the logic inside the for cap in
re.captures_iter(content) / for field_cap in field_re.captures_iter(struct_body)
block to detect duplicates: maintain either a HashMap<String, Vec<String>> or a
HashMap<String, String> plus a HashSet<String> ambiguous set; when you encounter
a second GtsSchemaId for the same struct_name, mark that struct_name as
ambiguous (add to the ambiguous set or store multiple names) and ensure you do
not inject an auto const for any ambiguous struct_name later (skip or emit an
error/warning), so the gts_schema_id_field map only contains unambiguous
single-field entries and ambiguous structs are skipped/handled explicitly.
In `@gts-macros/README.md`:
- Line 37: The italicized parenthetical in the README table cell for
`new_instance_with_defaults(segment)` contains extra spaces inside the emphasis
markers (the text `*(only if struct has exactly one `GtsInstanceId` field)*`),
triggering markdownlint MD037; fix it by removing the space after the opening
`*` and before the closing `*` so the emphasis is `*(only if struct has exactly
one `GtsInstanceId` field)*` becomes `*(only if struct has exactly one
`GtsInstanceId` field)*` (or remove the emphasis entirely) to eliminate the
inner spacing issue.
In `@gts-macros/tests/compile_fail/const_values_malformed.rs`:
- Around line 5-15: The struct attribute uses base=true on MalformedConstV1 so
the const_values error is raised before malformed parsing; split into two
structs: keep a base struct (e.g., MalformedConstBase) annotated with
#[struct_to_gts_schema(... base = true ...)] and move the fields there (no
const_values), then add a derived struct (e.g., MalformedConstV1) annotated with
#[struct_to_gts_schema(... base = false, schema_id =
"gts.x.test.const.malformed.v1~", const_values = "value_without_equals",
properties = "value" ...)] that references/extends the base so the malformed
const_values path on the derived struct is reached and tested.
In `@gts-macros/tests/compile_fail/two_instance_id_fields.rs`:
- Line 5: The test uses the non-canonical import path "use
gts::gts::{GtsInstanceId, GtsSchemaId};" — replace it with the crate-root
re-exports by importing "GtsInstanceId" and "GtsSchemaId" from "gts" directly
(i.e., use gts::GtsInstanceId; use gts::GtsSchemaId;) so the file follows the
same canonical import style as other compile-fail tests and references the same
symbols GtsInstanceId and GtsSchemaId.
In
`@gts-macros/tests/schemas/gts.x.core.events.type.v1`~x.core.simple.event.v1~.schema.json:
- Around line 9-23: The schema is missing event_type in its required array, so
add the "event_type" property name to the local "required" list in this JSON
Schema (the block defining properties with "event_type": { "const":
"gts.x.core.events.type.v1~x.core.simple.event.v1~" }), ensuring the schema
requires the event_type field in addition to "message" and "severity".
In `@gts-macros/tests/schemas/gts.x.test.alert.base.v1`~.schema.json:
- Line 5: Update the JSON schema "description" text to accurately reflect the
defined properties: replace the reference to "kind" with the actual property
names present (channel, data, recipient, severity, type) or add the missing
"kind" property if that was intended; locate the schema's top-level
"description" string and make it consistent with the properties array (channel,
data, recipient, severity, type) or adjust the properties to include "kind" and
its schema if needed.
In
`@gts-macros/tests/schemas/gts.x.test.alert.base.v1`~x.test.three.sms.v1~.schema.json:
- Around line 13-15: The derived schema places the "kind" const at top-level in
allOf[1].properties which violates the base schema's additionalProperties:false;
move the "kind" const into the "data" object's properties (i.e., under
data.properties.kind with the same const value) inside the derived schema so the
top-level only contains the allowed keys (channel, data, recipient, severity,
type); update the allOf entry that currently defines "kind" to nest it under
"data.properties" to satisfy the base schema and the expectation in
const_fields_tests.rs::test_three_event_l3_sms_has_conflicting_severity_const.
In
`@gts-macros/tests/schemas/gts.x.test.three.event.v1`~x.test.three.alert.v1~.schema.json:
- Around line 10-18: The base schema's additionalProperties: false blocks the
derived schema's top-level properties channel, data, and recipient (present in
the derived schema file) causing validation failures; fix by updating the base
schema to use "unevaluatedProperties": false instead of "additionalProperties":
false (JSON Schema 2019-09+) so derived schemas can add properties via
$ref/allOf, or alternatively move channel, data, and recipient under the
existing payload object in the derived schema so they are nested rather than
top-level — update the base schema's constraint or refactor the derived schema
(properties: channel, data, recipient) accordingly.
---
Nitpick comments:
In `@gts-macros/src/lib.rs`:
- Around line 1686-1688: Remove the redundant shadowing definition of
is_unit_struct and reuse the earlier computed value based on struct_fields
(i.e., struct_fields.is_none()) instead of re-checking matches!(&input.data,
Data::Struct(...) if matches!(&data_struct.fields, Fields::Unit)); delete the
let is_unit_struct = ... line and update any subsequent references to use the
existing struct_fields.is_none() (or the previously defined is_unit_struct) so
you don't recompute/mask the value.
| // Pass 1: build a map of struct_name -> name of the GtsSchemaId field (for auto const injection) | ||
| let mut gts_schema_id_field: HashMap<String, String> = HashMap::new(); | ||
| for cap in re.captures_iter(content) { | ||
| let struct_name = cap[2].to_owned(); | ||
| let struct_body = cap.get(4).map_or("", |m| m.as_str()); | ||
| for field_cap in field_re.captures_iter(struct_body) { | ||
| let field_name = &field_cap[2]; | ||
| let field_type = field_cap[3].trim().trim_end_matches(','); | ||
| if field_type == "GtsSchemaId" { | ||
| gts_schema_id_field.insert(struct_name.clone(), field_name.to_owned()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Avoid ambiguous parent schema-id auto‑injection.
If a parent has multiple GtsSchemaId fields, the current map overwrites and still injects, which conflicts with the macro’s ambiguity rules. Track duplicates and skip/err to avoid silently picking one.
Suggested fix (track ambiguity and skip injection)
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
@@
-let mut gts_schema_id_field: HashMap<String, String> = HashMap::new();
+let mut gts_schema_id_field: HashMap<String, String> = HashMap::new();
+let mut ambiguous_schema_id_structs: HashSet<String> = HashSet::new();
@@
- if field_type == "GtsSchemaId" {
- gts_schema_id_field.insert(struct_name.clone(), field_name.to_owned());
- }
+ if field_type == "GtsSchemaId" {
+ if gts_schema_id_field
+ .insert(struct_name.clone(), field_name.to_owned())
+ .is_some()
+ {
+ ambiguous_schema_id_structs.insert(struct_name.clone());
+ }
+ }
@@
- let parent_schema_id_field: Option<&str> = match &attrs.base {
- BaseAttr::Parent(parent_name) => {
- gts_schema_id_field.get(parent_name).map(String::as_str)
- }
+ let parent_schema_id_field: Option<&str> = match &attrs.base {
+ BaseAttr::Parent(parent_name) => {
+ if ambiguous_schema_id_structs.contains(parent_name) {
+ None
+ } else {
+ gts_schema_id_field.get(parent_name).map(String::as_str)
+ }
+ }
BaseAttr::IsBase => None,
};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-cli/src/gen_schemas.rs` around lines 438 - 449, The current Pass 1 loop
that builds gts_schema_id_field (in gen_schemas.rs) blindly maps struct_name ->
field_name and overwrites when multiple GtsSchemaId fields exist; change the
logic inside the for cap in re.captures_iter(content) / for field_cap in
field_re.captures_iter(struct_body) block to detect duplicates: maintain either
a HashMap<String, Vec<String>> or a HashMap<String, String> plus a
HashSet<String> ambiguous set; when you encounter a second GtsSchemaId for the
same struct_name, mark that struct_name as ambiguous (add to the ambiguous set
or store multiple names) and ensure you do not inject an auto const for any
ambiguous struct_name later (skip or emit an error/warning), so the
gts_schema_id_field map only contains unambiguous single-field entries and
ambiguous structs are skipped/handled explicitly.
| // Parse macro attributes | ||
| let Some(attrs) = parse_macro_attrs(attr_body) else { | ||
| continue; | ||
| }; | ||
|
|
||
| // Determine parent's GtsSchemaId field name for auto const injection | ||
| let parent_schema_id_field: Option<&str> = match &attrs.base { | ||
| BaseAttr::Parent(parent_name) => { | ||
| gts_schema_id_field.get(parent_name).map(String::as_str) | ||
| } | ||
| BaseAttr::IsBase => None, | ||
| }; |
There was a problem hiding this comment.
CLI should reject const_values on base structs (currently ignored).
The macro explicitly errors on base = true + const_values, but the CLI accepts and silently drops them in the base branch. That can mask misconfigurations and diverge from macro behavior.
Suggested fix (validate after parsing)
- let Some(attrs) = parse_macro_attrs(attr_body) else {
+ let Some(attrs) = parse_macro_attrs(attr_body) else {
continue;
};
+ if matches!(attrs.base, BaseAttr::IsBase) && !attrs.const_values.is_empty() {
+ bail!(
+ "const_values is not allowed on base structs (base = true): {}",
+ struct_name
+ );
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Parse macro attributes | |
| let Some(attrs) = parse_macro_attrs(attr_body) else { | |
| continue; | |
| }; | |
| // Determine parent's GtsSchemaId field name for auto const injection | |
| let parent_schema_id_field: Option<&str> = match &attrs.base { | |
| BaseAttr::Parent(parent_name) => { | |
| gts_schema_id_field.get(parent_name).map(String::as_str) | |
| } | |
| BaseAttr::IsBase => None, | |
| }; | |
| // Parse macro attributes | |
| let Some(attrs) = parse_macro_attrs(attr_body) else { | |
| continue; | |
| }; | |
| if matches!(attrs.base, BaseAttr::IsBase) && !attrs.const_values.is_empty() { | |
| bail!( | |
| "const_values is not allowed on base structs (base = true): {}", | |
| struct_name | |
| ); | |
| } | |
| // Determine parent's GtsSchemaId field name for auto const injection | |
| let parent_schema_id_field: Option<&str> = match &attrs.base { | |
| BaseAttr::Parent(parent_name) => { | |
| gts_schema_id_field.get(parent_name).map(String::as_str) | |
| } | |
| BaseAttr::IsBase => None, | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-cli/src/gen_schemas.rs` around lines 460 - 471, After parsing attributes
with parse_macro_attrs(attr_body) you must validate that base structs do not
have const_values: after let Some(attrs) = parse_macro_attrs(attr_body) else {
... } add a check that if attrs.base == BaseAttr::IsBase and
attrs.const_values.is_some() then return or emit a CLI error (matching the macro
behavior) instead of silently ignoring; update the error path to include context
(struct name from the parsed item) so the CLI rejects the input consistently
with the macro.
| | Generated Item | Kind | Description | | ||
| |---|---|---| | ||
| | `new_instance_with_defaults()` | `fn -> Self` | Create instance with all fields defaulted; `GtsSchemaId` fields set to `M::SCHEMA_ID` | | ||
| | `new_instance_with_defaults(segment)` | `fn(&str) -> Self` | *(only if struct has exactly one `GtsInstanceId` field)* Same as above, plus builds the instance ID from `M::SCHEMA_ID` + segment | |
There was a problem hiding this comment.
Fix markdown emphasis spacing.
Static analysis (markdownlint MD037) flags spaces inside emphasis markers. The italicized text *(only if struct has exactly one GtsInstanceId field)* has a space after the opening *.
📝 Proposed fix
-| `new_instance_with_defaults(segment)` | `fn(&str) -> Self` | *(only if struct has exactly one `GtsInstanceId` field)* Same as above, plus builds the instance ID from `M::SCHEMA_ID` + segment |
+| `new_instance_with_defaults(segment)` | `fn(&str) -> Self` | *(only if struct has exactly one `GtsInstanceId` field)* Same as above, plus builds the instance ID from `M::SCHEMA_ID` + segment |Alternatively, remove the emphasis or ensure no spaces directly after *:
-*(only if struct has exactly one `GtsInstanceId` field)*
+*only if struct has exactly one `GtsInstanceId` field*🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 37-37: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-macros/README.md` at line 37, The italicized parenthetical in the README
table cell for `new_instance_with_defaults(segment)` contains extra spaces
inside the emphasis markers (the text `*(only if struct has exactly one
`GtsInstanceId` field)*`), triggering markdownlint MD037; fix it by removing the
space after the opening `*` and before the closing `*` so the emphasis is
`*(only if struct has exactly one `GtsInstanceId` field)*` becomes `*(only if
struct has exactly one `GtsInstanceId` field)*` (or remove the emphasis
entirely) to eliminate the inner spacing issue.
| #[struct_to_gts_schema( | ||
| dir_path = "schemas", | ||
| base = true, | ||
| schema_id = "gts.x.test.const.malformed.v1~", | ||
| description = "Malformed const_values test", | ||
| properties = "value", | ||
| const_values = "value_without_equals" | ||
| )] | ||
| pub struct MalformedConstV1 { | ||
| pub value: String, | ||
| } |
There was a problem hiding this comment.
Malformed const_values is never reached due to base=true.
Line 7 makes this a base struct, and Line 11 then triggers the “const_values not allowed on base” error before malformed parsing is exercised. Consider splitting into a base struct plus a derived struct that carries the malformed const_values.
💡 Suggested restructure to exercise malformed parsing
#[struct_to_gts_schema(
dir_path = "schemas",
base = true,
- schema_id = "gts.x.test.const.malformed.v1~",
- description = "Malformed const_values test",
- properties = "value",
- const_values = "value_without_equals"
+ schema_id = "gts.x.test.const.malformed.base.v1~",
+ description = "Malformed const_values test base",
+ properties = "value"
)]
-pub struct MalformedConstV1 {
+pub struct MalformedConstBaseV1 {
pub value: String,
}
+#[struct_to_gts_schema(
+ dir_path = "schemas",
+ base = MalformedConstBaseV1,
+ schema_id = "gts.x.test.const.malformed.base.v1~x.test.const.malformed.v1~",
+ description = "Malformed const_values test",
+ properties = "",
+ const_values = "value_without_equals"
+)]
+pub struct MalformedConstV1;
+
fn main() {}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #[struct_to_gts_schema( | |
| dir_path = "schemas", | |
| base = true, | |
| schema_id = "gts.x.test.const.malformed.v1~", | |
| description = "Malformed const_values test", | |
| properties = "value", | |
| const_values = "value_without_equals" | |
| )] | |
| pub struct MalformedConstV1 { | |
| pub value: String, | |
| } | |
| #[struct_to_gts_schema( | |
| dir_path = "schemas", | |
| base = true, | |
| schema_id = "gts.x.test.const.malformed.base.v1~", | |
| description = "Malformed const_values test base", | |
| properties = "value" | |
| )] | |
| pub struct MalformedConstBaseV1 { | |
| pub value: String, | |
| } | |
| #[struct_to_gts_schema( | |
| dir_path = "schemas", | |
| base = MalformedConstBaseV1, | |
| schema_id = "gts.x.test.const.malformed.base.v1~x.test.const.malformed.v1~", | |
| description = "Malformed const_values test", | |
| properties = "", | |
| const_values = "value_without_equals" | |
| )] | |
| pub struct MalformedConstV1; | |
| fn main() {} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-macros/tests/compile_fail/const_values_malformed.rs` around lines 5 - 15,
The struct attribute uses base=true on MalformedConstV1 so the const_values
error is raised before malformed parsing; split into two structs: keep a base
struct (e.g., MalformedConstBase) annotated with #[struct_to_gts_schema(... base
= true ...)] and move the fields there (no const_values), then add a derived
struct (e.g., MalformedConstV1) annotated with #[struct_to_gts_schema(... base =
false, schema_id = "gts.x.test.const.malformed.v1~", const_values =
"value_without_equals", properties = "value" ...)] that references/extends the
base so the malformed const_values path on the derived struct is reached and
tested.
| //! new_instance_with_defaults() is NOT generated — it would be ambiguous | ||
| //! which field to populate. Calling it must produce a compile error. | ||
|
|
||
| use gts::gts::{GtsInstanceId, GtsSchemaId}; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check import patterns in compile_fail tests
echo "=== Import patterns in compile_fail tests ==="
rg -n "use gts::" gts-macros/tests/compile_fail/ -A 1
echo ""
echo "=== Check if GtsSchemaId is re-exported ==="
rg -n "pub use.*GtsSchemaId" --type rust
echo ""
echo "=== Check gts crate lib.rs structure ==="
find . -name "lib.rs" -path "*/gts/*" | head -5Repository: GlobalTypeSystem/gts-rust
Length of output: 5219
Use the canonical import path for consistency.
Both gts::gts::{GtsInstanceId, GtsSchemaId} and gts::GtsSchemaId work because GtsSchemaId and GtsInstanceId are re-exported at the crate root in gts/src/lib.rs. However, the majority of compile-fail tests use the shorter canonical path use gts::GtsSchemaId; and use gts::GtsInstanceId;. Align this file with that convention:
-use gts::gts::{GtsInstanceId, GtsSchemaId};
+use gts::{GtsInstanceId, GtsSchemaId};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| use gts::gts::{GtsInstanceId, GtsSchemaId}; | |
| use gts::{GtsInstanceId, GtsSchemaId}; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-macros/tests/compile_fail/two_instance_id_fields.rs` at line 5, The test
uses the non-canonical import path "use gts::gts::{GtsInstanceId, GtsSchemaId};"
— replace it with the crate-root re-exports by importing "GtsInstanceId" and
"GtsSchemaId" from "gts" directly (i.e., use gts::GtsInstanceId; use
gts::GtsSchemaId;) so the file follows the same canonical import style as other
compile-fail tests and references the same symbols GtsInstanceId and
GtsSchemaId.
| "properties": { | ||
| "event_type": { | ||
| "const": "gts.x.core.events.type.v1~x.core.simple.event.v1~" | ||
| }, | ||
| "message": { | ||
| "type": "string" | ||
| }, | ||
| "severity": { | ||
| "type": "integer" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "message", | ||
| "severity" | ||
| ] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd 'gts.x.core.events.type.v1~' gts-macros/tests/schemas --type fRepository: GlobalTypeSystem/gts-rust
Length of output: 424
🏁 Script executed:
cat gts-macros/tests/schemas/gts.x.core.events.type.v1~.schema.jsonRepository: GlobalTypeSystem/gts-rust
Length of output: 803
🏁 Script executed:
cat gts-macros/tests/schemas/gts.x.core.events.type.v1~x.core.simple.event.v1~.schema.jsonRepository: GlobalTypeSystem/gts-rust
Length of output: 742
Add event_type to the required list.
The base schema gts.x.core.events.type.v1~ does not define or require event_type. Since const alone doesn't enforce property presence in JSON Schema, payloads without event_type would still validate. Include it in the local required list:
"required": [
+ "event_type",
"message",
"severity"
]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "properties": { | |
| "event_type": { | |
| "const": "gts.x.core.events.type.v1~x.core.simple.event.v1~" | |
| }, | |
| "message": { | |
| "type": "string" | |
| }, | |
| "severity": { | |
| "type": "integer" | |
| } | |
| }, | |
| "required": [ | |
| "message", | |
| "severity" | |
| ] | |
| "properties": { | |
| "event_type": { | |
| "const": "gts.x.core.events.type.v1~x.core.simple.event.v1~" | |
| }, | |
| "message": { | |
| "type": "string" | |
| }, | |
| "severity": { | |
| "type": "integer" | |
| } | |
| }, | |
| "required": [ | |
| "event_type", | |
| "message", | |
| "severity" | |
| ] |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@gts-macros/tests/schemas/gts.x.core.events.type.v1`~x.core.simple.event.v1~.schema.json
around lines 9 - 23, The schema is missing event_type in its required array, so
add the "event_type" property name to the local "required" list in this JSON
Schema (the block defining properties with "event_type": { "const":
"gts.x.core.events.type.v1~x.core.simple.event.v1~" }), ensuring the schema
requires the event_type field in addition to "message" and "severity".
| "$id": "gts://gts.x.test.alert.base.v1~", | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "additionalProperties": false, | ||
| "description": "Alert payload base with channel, severity, kind, data fields", |
There was a problem hiding this comment.
Description mentions "kind" field that doesn't exist in properties.
The description states "Alert payload base with channel, severity, kind, data fields" but the schema defines channel, data, recipient, severity, and type — no kind property. Consider updating the description to match the actual fields.
📝 Suggested fix
- "description": "Alert payload base with channel, severity, kind, data fields",
+ "description": "Alert payload base with channel, data, recipient, severity, type fields",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "description": "Alert payload base with channel, severity, kind, data fields", | |
| "description": "Alert payload base with channel, data, recipient, severity, type fields", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gts-macros/tests/schemas/gts.x.test.alert.base.v1`~.schema.json at line 5,
Update the JSON schema "description" text to accurately reflect the defined
properties: replace the reference to "kind" with the actual property names
present (channel, data, recipient, severity, type) or add the missing "kind"
property if that was intended; locate the schema's top-level "description"
string and make it consistent with the properties array (channel, data,
recipient, severity, type) or adjust the properties to include "kind" and its
schema if needed.
| "kind": { | ||
| "const": "traffic" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate the base schema file
find . -name "*gts.x.test.alert.base.v1~*" -type f | head -20Repository: GlobalTypeSystem/gts-rust
Length of output: 218
🏁 Script executed:
# Also check the derived schema file being reviewed
find . -name "*gts.x.test.alert.base.v1~x.test.three.sms.v1~*" -type fRepository: GlobalTypeSystem/gts-rust
Length of output: 153
🏁 Script executed:
# Read the base schema file
echo "=== BASE SCHEMA ==="
cat ./gts-macros/tests/schemas/gts.x.test.alert.base.v1~.schema.jsonRepository: GlobalTypeSystem/gts-rust
Length of output: 842
🏁 Script executed:
# Read the derived schema file
echo "=== DERIVED SCHEMA ==="
cat ./gts-macros/tests/schemas/gts.x.test.alert.base.v1~x.test.three.sms.v1~.schema.jsonRepository: GlobalTypeSystem/gts-rust
Length of output: 766
🏁 Script executed:
# Check if there are any test files or examples using these schemas
find . -type f -name "*.json" -o -name "*.rs" | xargs grep -l "gts.x.test.alert.base.v1~x.test.three.sms.v1~" 2>/dev/null | head -10Repository: GlobalTypeSystem/gts-rust
Length of output: 194
🏁 Script executed:
# Also check for any test data or examples in the test schemas directory
ls -la ./gts-macros/tests/schemas/ | grep -i alertRepository: GlobalTypeSystem/gts-rust
Length of output: 500
🏁 Script executed:
# Examine the test file that references this schema
cat ./gts-macros/tests/const_fields_tests.rsRepository: GlobalTypeSystem/gts-rust
Length of output: 50381
🏁 Script executed:
# Check the structure of the SMS alert schema more carefully
cat ./gts-macros/tests/schemas/gts.x.test.alert.base.v1~x.test.three.sms.v1~.schema.json | jq '.allOf[1].properties | keys'Repository: GlobalTypeSystem/gts-rust
Length of output: 118
🏁 Script executed:
# Verify if "data" has nested properties in the schema
cat ./gts-macros/tests/schemas/gts.x.test.alert.base.v1~x.test.three.sms.v1~.schema.json | jq '.allOf[1].properties.data'Repository: GlobalTypeSystem/gts-rust
Length of output: 73
🏁 Script executed:
# Check if there are any test cases that try to validate instances against this schema
grep -r "gts.x.test.alert.base.v1~x.test.three.sms.v1~" . --include="*.rs" -A 5 -B 5Repository: GlobalTypeSystem/gts-rust
Length of output: 3690
🏁 Script executed:
# Let's run the test that validates this schema to see if it actually fails
cd ./gts-macros && cargo test test_sms_schema_chain_child_valid -- --nocapture 2>&1 | tail -100Repository: GlobalTypeSystem/gts-rust
Length of output: 315
Fix schema constraint violation: kind property must be nested under data, not flat in allOf.
The base schema gts.x.test.alert.base.v1~ has additionalProperties: false and defines only channel, data, recipient, severity, and type. The derived schema adds kind as a flat property in allOf[1].properties, which violates the base schema's additionalProperties constraint during validation.
The test expectations in const_fields_tests.rs (specifically test_three_event_l3_sms_has_conflicting_severity_const) document that kind should be nested under data.properties rather than placed flat at the top level. Move the kind const constraint into the data object structure to align with the base schema's property definitions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@gts-macros/tests/schemas/gts.x.test.alert.base.v1`~x.test.three.sms.v1~.schema.json
around lines 13 - 15, The derived schema places the "kind" const at top-level in
allOf[1].properties which violates the base schema's additionalProperties:false;
move the "kind" const into the "data" object's properties (i.e., under
data.properties.kind with the same const value) inside the derived schema so the
top-level only contains the allowed keys (channel, data, recipient, severity,
type); update the allOf entry that currently defines "kind" to nest it under
"data.properties" to satisfy the base schema and the expectation in
const_fields_tests.rs::test_three_event_l3_sms_has_conflicting_severity_const.
| "channel": { | ||
| "type": "string" | ||
| }, | ||
| "data": { | ||
| "type": "object" | ||
| }, | ||
| "recipient": { | ||
| "type": "string" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find and examine the base schema file
find . -name "*gts.x.test.three.event.v1~*.schema.json" -type f | head -20Repository: GlobalTypeSystem/gts-rust
Length of output: 332
🏁 Script executed:
# Examine the base schema
echo "=== BASE SCHEMA ==="
cat ./gts-macros/tests/schemas/gts.x.test.three.event.v1~.schema.json | jq .
echo ""
echo "=== DERIVED SCHEMA ==="
cat ./gts-macros/tests/schemas/gts.x.test.three.event.v1~x.test.three.alert.v1~.schema.json | jq .Repository: GlobalTypeSystem/gts-rust
Length of output: 1680
🏁 Script executed:
# Let's check if there are any other schema files or test files that might indicate
# whether this is actually used with strict validation or if it's documented
find . -name "*.rs" -path "*/tests/*" | xargs grep -l "gts.x.test.three.event.v1" | head -5Repository: GlobalTypeSystem/gts-rust
Length of output: 109
🏁 Script executed:
# Examine the test file to see how schemas are validated
cat ./gts-macros/tests/const_fields_tests.rsRepository: GlobalTypeSystem/gts-rust
Length of output: 50381
Schema validation fails due to additionalProperties: false conflict in base.
The derived schema adds channel, data, and recipient properties, but the base schema has additionalProperties: false with only payload, severity, source, and type. This causes validation failures when instances include the derived properties—a known limitation documented in the test suite where schema chain validation explicitly rejects this structure with an "additionalProperties" error.
To resolve, consider:
- Using
unevaluatedProperties: false(JSON Schema Draft 2019-09+) instead ofadditionalProperties: falsein the base, or - Nesting derived properties under the generic field (e.g., under
payload) instead of placing them flat at the top level.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@gts-macros/tests/schemas/gts.x.test.three.event.v1`~x.test.three.alert.v1~.schema.json
around lines 10 - 18, The base schema's additionalProperties: false blocks the
derived schema's top-level properties channel, data, and recipient (present in
the derived schema file) causing validation failures; fix by updating the base
schema to use "unevaluatedProperties": false instead of "additionalProperties":
false (JSON Schema 2019-09+) so derived schemas can add properties via
$ref/allOf, or alternatively move channel, data, and recipient under the
existing payload object in the derived schema so they are nested rather than
top-level — update the base schema's constraint or refactor the derived schema
(properties: channel, data, recipient) accordingly.
feat(gts-macros): const_values, new_instance_with_defaults, and parent metadata
chore(gts-macros-cli): fix json schema generatio for 3rd level GTS structs
Summary by CodeRabbit
Release Notes v0.8.2
New Features
const_valuesparameter to the#[struct_to_gts_schema]macro for defining fixed constant values on struct fields in generated JSON schemas.new_instance_with_defaults()constructor for base and derived structs with const values.GTS_SCHEMA_ID_FIELD_NAMEandGTS_INSTANCE_ID_FIELD_NAMEpublic constants.Documentation