From a3e51f87685f44b171e2ea586729ecd35ff98ac0 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 03:20:54 +0800 Subject: [PATCH 1/6] fix(catalog): accept entity ids in texture setup contracts Refs wrightkit/opy-rs#330 --- crates/workshop-rs/src/catalog/data/catalog.json | 8 ++++---- crates/workshop-rs/tests/contextual_semantics.rs | 11 +++++++++++ crates/workshop-rs/tests/identity.rs | 2 +- crates/workshop-rs/tests/language_conformance.rs | 6 ++++-- docs/language-support/actions.md | 2 +- docs/language-support/values.md | 4 ++-- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index a82c04bc..6e59fa87 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -366,7 +366,7 @@ "name" ], "paramTypes": [ - "Player|Array", + "Player|Array|EntityId", "String" ], "params": [ @@ -5256,7 +5256,7 @@ ] } ], - "digest": "f02d441ed46d66f43b2145b6702a653c8f824b130a39a467a70bef17017cc1d0", + "digest": "5959d86b118caa90b3dca9345614d2c798a56b6b66f0adba129803a8a227258e", "enums": [ { "domain": "Impulse", @@ -12361,7 +12361,7 @@ "array" ], "paramTypes": [ - "Array" + "Array|EntityId" ], "params": [ "Array" @@ -12423,7 +12423,7 @@ "paramTypes": [ "String", "Number", - "Number" + "Number|Boolean" ], "params": [ "String", diff --git a/crates/workshop-rs/tests/contextual_semantics.rs b/crates/workshop-rs/tests/contextual_semantics.rs index f56a34be..c6842d66 100644 --- a/crates/workshop-rs/tests/contextual_semantics.rs +++ b/crates/workshop-rs/tests/contextual_semantics.rs @@ -99,6 +99,17 @@ fn one_sided_contextual_aliases_reject_the_other_boolean() { assert!(format!("{error:?}").contains("semantic type")); } +#[test] +fn entity_ids_and_boolean_string_slice_counts_match_workshop_contract() { + let setup = program("Start Forcing Dummy Bot Name(Last Created Entity, Custom String(\"x\"));"); + validate_program(&setup); + + let derived = program( + "Set Global Variable(probe, String Slice(String Replace(Custom String(\"x\"), First Of(Last Created Entity), First Of(Last Created Entity)), 126, True));", + ); + validate_program(&derived); +} + #[test] fn wait_until_keeps_numeric_exception_without_global_truthiness() { let numeric = program("Wait Until(1, 2);"); diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index 523bf8ec..895bdf6f 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "f02d441ed46d66f43b2145b6702a653c8f824b130a39a467a70bef17017cc1d0"; + "5959d86b118caa90b3dca9345614d2c798a56b6b66f0adba129803a8a227258e"; #[test] fn committed_catalog_digest_is_pinned() { diff --git a/crates/workshop-rs/tests/language_conformance.rs b/crates/workshop-rs/tests/language_conformance.rs index 303ac491..a3b885cd 100644 --- a/crates/workshop-rs/tests/language_conformance.rs +++ b/crates/workshop-rs/tests/language_conformance.rs @@ -728,8 +728,10 @@ fn sample_argument(catalog: &Catalog, parameter_type: &str) -> String { "Number" | "Number|Boolean" | "Boolean|Number" | "Boolean|Number|Vector" => "1".to_string(), "Vector" | "Vector|Player" | "Vector|Player|Array" => "Vector(0, 0, 0)".to_string(), "String" | "String|Array" | "Object|String" => "Custom String(\"probe\")".to_string(), - "Array" => "All Players(All Teams)".to_string(), - "Player" | "Player|Array" | "Player|EntityId" => "Event Player".to_string(), + "Array" | "Array|EntityId" => "All Players(All Teams)".to_string(), + "Player" | "Player|Array" | "Player|Array|EntityId" | "Player|EntityId" => { + "Event Player".to_string() + } "Object" | "Object|Array" | "Boolean|Number|Object|Array" => "Event Player".to_string(), "Hero|Array" => "D.Va".to_string(), "Operation" => "Add".to_string(), diff --git a/docs/language-support/actions.md b/docs/language-support/actions.md index b9c1c81d..55c93e07 100644 --- a/docs/language-support/actions.md +++ b/docs/language-support/actions.md @@ -176,7 +176,7 @@ This document inventories the canonical Workshop actions supported by `workshop- | `Start Damage Modification` | ✅ Supported | Parameters: (Object: Player|Array, Object: Player|Array, Number: Number, DamageReeval: DamageReeval). | | `Start Damage Over Time` | ✅ Supported | Parameters: (Object: Player|Array, Player: Player, Number: Number, Number: Number). | | `Start Facing` | ✅ Supported | Parameters: (Player: Player|Array, Direction: Vector, Turn Rate: Number, Relativity: Relativity, Reevaluation: FacingReeval). | -| `Start Forcing Dummy Bot Name` | ✅ Supported | Parameters: (Object: Player|Array, String: String). | +| `Start Forcing Dummy Bot Name` | ✅ Supported | Parameters: (Object: Player|Array|EntityId, String: String). | | `Start Forcing Player Outlines` | ✅ Supported | Parameters: (ViewedPlayers: Player|Array, ViewingPlayers: Player|Array, Visible: Boolean, Color: Color, Visibility: OutlineVisibility). | | `Start Forcing Player Position` | ✅ Supported | Parameters: (Player: Player, Position: Vector, Boolean: Boolean). | | `Start Forcing Player To Be Hero` | ✅ Supported | Parameters: (Object: Player|Array, Hero: Hero). | diff --git a/docs/language-support/values.md b/docs/language-support/values.md index e78e0e57..a59e35b8 100644 --- a/docs/language-support/values.md +++ b/docs/language-support/values.md @@ -80,7 +80,7 @@ This document inventories canonical Workshop values and expressions in `workshop | `Farthest Player From` | ✅ Supported | Returns: `Player`; Parameters: (Position: Vector, Team: Team). | | `False` | ✅ Supported | Returns: `BoolLiteral`. | | `Filtered Array` | ✅ Supported | Returns: `Array`; Parameters: (Array: Array, Condition: Boolean). | -| `First Of` | ✅ Supported | Returns: `Object|Array`; Parameters: (Array: Array). | +| `First Of` | ✅ Supported | Returns: `Object|Array`; Parameters: (Array: Array|EntityId). | | `Flag Position` | ✅ Supported | Returns: `Vector`; Parameters: (Team: Team). | | `Forward` | ✅ Supported | Returns: `Array`. | | `Game Mode` | ✅ Supported | Returns: `Gamemode`; Parameters: (Gamemode: Gamemode). | @@ -233,7 +233,7 @@ This document inventories canonical Workshop values and expressions in `workshop | `String Contains` | ✅ Supported | Returns: `Boolean`; Parameters: (String: String, String: String). | | `String Length` | ✅ Supported | Returns: `Number`; Parameters: (String: String). | | `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array, Replacement: String|Array). | -| `String Slice` | ✅ Supported | Returns: `String`; Parameters: (String: String, Start Index: Number, Count: Number). | +| `String Slice` | ✅ Supported | Returns: `String`; Parameters: (String: String, Start Index: Number, Count: Number|Boolean). | | `String Split` | ✅ Supported | Returns: `Array`; Parameters: (String: String|Array, Separator: String|Array). | | `Subtract` | ✅ Supported | Returns: `Number|Vector`; Parameters: (a: Number|Boolean|Vector, b: Number|Boolean|Vector). | | `Tangent From Degrees` | ✅ Supported | Returns: `Number`; Parameters: (Number: Number). | From b878c9b813816e1ef46b21ca1aa87320ed786cf0 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 03:24:56 +0800 Subject: [PATCH 2/6] fix(catalog): accept entity ids in string split Refs wrightkit/opy-rs#330 --- crates/workshop-rs/src/catalog/data/catalog.json | 4 ++-- crates/workshop-rs/tests/contextual_semantics.rs | 2 +- crates/workshop-rs/tests/identity.rs | 2 +- crates/workshop-rs/tests/language_conformance.rs | 4 +++- docs/language-support/values.md | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index 6e59fa87..95789a3f 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -5256,7 +5256,7 @@ ] } ], - "digest": "5959d86b118caa90b3dca9345614d2c798a56b6b66f0adba129803a8a227258e", + "digest": "c2be0dc91f940ea911e0db3ca2c5304b328a3e0d93c8c1ec5d461dde16e9fcfc", "enums": [ { "domain": "Impulse", @@ -12451,7 +12451,7 @@ "separator" ], "paramTypes": [ - "String|Array", + "String|Array|EntityId", "String|Array" ], "params": [ diff --git a/crates/workshop-rs/tests/contextual_semantics.rs b/crates/workshop-rs/tests/contextual_semantics.rs index c6842d66..5200698a 100644 --- a/crates/workshop-rs/tests/contextual_semantics.rs +++ b/crates/workshop-rs/tests/contextual_semantics.rs @@ -105,7 +105,7 @@ fn entity_ids_and_boolean_string_slice_counts_match_workshop_contract() { validate_program(&setup); let derived = program( - "Set Global Variable(probe, String Slice(String Replace(Custom String(\"x\"), First Of(Last Created Entity), First Of(Last Created Entity)), 126, True));", + "Set Global Variable(probe, String Slice(String Replace(Custom String(\"x\"), First Of(Last Created Entity), First Of(Last Created Entity)), 126, True)); Set Global Variable(parts, String Split(First Of(Last Created Entity), Empty Array));", ); validate_program(&derived); } diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index 895bdf6f..0873f3cd 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "5959d86b118caa90b3dca9345614d2c798a56b6b66f0adba129803a8a227258e"; + "c2be0dc91f940ea911e0db3ca2c5304b328a3e0d93c8c1ec5d461dde16e9fcfc"; #[test] fn committed_catalog_digest_is_pinned() { diff --git a/crates/workshop-rs/tests/language_conformance.rs b/crates/workshop-rs/tests/language_conformance.rs index a3b885cd..3c041e46 100644 --- a/crates/workshop-rs/tests/language_conformance.rs +++ b/crates/workshop-rs/tests/language_conformance.rs @@ -727,7 +727,9 @@ fn sample_argument(catalog: &Catalog, parameter_type: &str) -> String { "Boolean" => "True".to_string(), "Number" | "Number|Boolean" | "Boolean|Number" | "Boolean|Number|Vector" => "1".to_string(), "Vector" | "Vector|Player" | "Vector|Player|Array" => "Vector(0, 0, 0)".to_string(), - "String" | "String|Array" | "Object|String" => "Custom String(\"probe\")".to_string(), + "String" | "String|Array" | "String|Array|EntityId" | "Object|String" => { + "Custom String(\"probe\")".to_string() + } "Array" | "Array|EntityId" => "All Players(All Teams)".to_string(), "Player" | "Player|Array" | "Player|Array|EntityId" | "Player|EntityId" => { "Event Player".to_string() diff --git a/docs/language-support/values.md b/docs/language-support/values.md index a59e35b8..33412824 100644 --- a/docs/language-support/values.md +++ b/docs/language-support/values.md @@ -234,7 +234,7 @@ This document inventories canonical Workshop values and expressions in `workshop | `String Length` | ✅ Supported | Returns: `Number`; Parameters: (String: String). | | `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array, Replacement: String|Array). | | `String Slice` | ✅ Supported | Returns: `String`; Parameters: (String: String, Start Index: Number, Count: Number|Boolean). | -| `String Split` | ✅ Supported | Returns: `Array`; Parameters: (String: String|Array, Separator: String|Array). | +| `String Split` | ✅ Supported | Returns: `Array`; Parameters: (String: String|Array|EntityId, Separator: String|Array). | | `Subtract` | ✅ Supported | Returns: `Number|Vector`; Parameters: (a: Number|Boolean|Vector, b: Number|Boolean|Vector). | | `Tangent From Degrees` | ✅ Supported | Returns: `Number`; Parameters: (Number: Number). | | `Tangent From Radians` | ✅ Supported | Returns: `Number`; Parameters: (Number: Number). | From dd7249c4ac2ad1e0d48bbe00bc1fbff19530147a Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 03:27:24 +0800 Subject: [PATCH 3/6] fix(catalog): accept entity ids in string replacement Refs wrightkit/opy-rs#330 --- crates/workshop-rs/src/catalog/data/catalog.json | 6 +++--- crates/workshop-rs/tests/identity.rs | 2 +- docs/language-support/values.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index 95789a3f..d871f828 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -5256,7 +5256,7 @@ ] } ], - "digest": "c2be0dc91f940ea911e0db3ca2c5304b328a3e0d93c8c1ec5d461dde16e9fcfc", + "digest": "7117f8875e0bf64df702b14dbb77173ed3de9a04a9c15dc1b9a83d01cd3114d7", "enums": [ { "domain": "Impulse", @@ -12392,8 +12392,8 @@ ], "paramTypes": [ "String|Array", - "String|Array", - "String|Array" + "String|Array|EntityId", + "String|Array|EntityId" ], "params": [ "String", diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index 0873f3cd..7845b93d 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "c2be0dc91f940ea911e0db3ca2c5304b328a3e0d93c8c1ec5d461dde16e9fcfc"; + "7117f8875e0bf64df702b14dbb77173ed3de9a04a9c15dc1b9a83d01cd3114d7"; #[test] fn committed_catalog_digest_is_pinned() { diff --git a/docs/language-support/values.md b/docs/language-support/values.md index 33412824..66ee4005 100644 --- a/docs/language-support/values.md +++ b/docs/language-support/values.md @@ -232,7 +232,7 @@ This document inventories canonical Workshop values and expressions in `workshop | `String` | ✅ Supported | Returns: `String`; Parameters: (String: String, {0}: Object|Array, {1}: Object|Array, {2}: Object|Array). `Custom String` remains supported. | | `String Contains` | ✅ Supported | Returns: `Boolean`; Parameters: (String: String, String: String). | | `String Length` | ✅ Supported | Returns: `Number`; Parameters: (String: String). | -| `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array, Replacement: String|Array). | +| `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array|EntityId, Replacement: String|Array|EntityId). | | `String Slice` | ✅ Supported | Returns: `String`; Parameters: (String: String, Start Index: Number, Count: Number|Boolean). | | `String Split` | ✅ Supported | Returns: `Array`; Parameters: (String: String|Array|EntityId, Separator: String|Array). | | `Subtract` | ✅ Supported | Returns: `Number|Vector`; Parameters: (a: Number|Boolean|Vector, b: Number|Boolean|Vector). | From 5851c54cb74e53c8ff722c9f68fc4aa2666e8ec4 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 03:36:42 +0800 Subject: [PATCH 4/6] fix(catalog): preserve texture boolean and empty array forms Refs wrightkit/opy-rs#330 --- crates/workshop-rs/src/catalog/data/catalog.json | 13 ++++--------- crates/workshop-rs/tests/contextual_semantics.rs | 4 +++- crates/workshop-rs/tests/identity.rs | 2 +- docs/language-support/actions.md | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index d871f828..36fb5c53 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -1987,10 +1987,7 @@ "paramCoercions": [ null, null, - { - "falseAsNumber": true, - "trueAsNumber": true - }, + null, { "nullVectorAsNull": true }, @@ -2008,7 +2005,7 @@ "paramTypes": [ "Hero|Array", "Team", - "Number", + "Number|Boolean", "Vector", "Vector" ], @@ -5256,7 +5253,7 @@ ] } ], - "digest": "7117f8875e0bf64df702b14dbb77173ed3de9a04a9c15dc1b9a83d01cd3114d7", + "digest": "3b66b40ad924a74384ae826614ef7296dd34f1785291b0e94739c560b878a01e", "enums": [ { "domain": "Impulse", @@ -11652,9 +11649,7 @@ { "emptyArrayAsString": true }, - { - "emptyArrayAsString": true - } + null ], "paramNames": [ "string", diff --git a/crates/workshop-rs/tests/contextual_semantics.rs b/crates/workshop-rs/tests/contextual_semantics.rs index 5200698a..863d6b50 100644 --- a/crates/workshop-rs/tests/contextual_semantics.rs +++ b/crates/workshop-rs/tests/contextual_semantics.rs @@ -101,7 +101,9 @@ fn one_sided_contextual_aliases_reject_the_other_boolean() { #[test] fn entity_ids_and_boolean_string_slice_counts_match_workshop_contract() { - let setup = program("Start Forcing Dummy Bot Name(Last Created Entity, Custom String(\"x\"));"); + let setup = program( + "Create Dummy Bot(All Heroes, Team 1, False, Null, Null); Start Forcing Dummy Bot Name(Last Created Entity, Custom String(\"x\"));", + ); validate_program(&setup); let derived = program( diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index 7845b93d..6f09e6ae 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "7117f8875e0bf64df702b14dbb77173ed3de9a04a9c15dc1b9a83d01cd3114d7"; + "3b66b40ad924a74384ae826614ef7296dd34f1785291b0e94739c560b878a01e"; #[test] fn committed_catalog_digest_is_pinned() { diff --git a/docs/language-support/actions.md b/docs/language-support/actions.md index 55c93e07..af666666 100644 --- a/docs/language-support/actions.md +++ b/docs/language-support/actions.md @@ -25,7 +25,7 @@ This document inventories the canonical Workshop actions supported by `workshop- | `Communicate` | ✅ Supported | Parameters: (Object: Player|Array, Comms: Comms). | | `Continue` | ✅ Supported | No parameters. | | `Create Beam Effect` | ✅ Supported | Parameters: (VisibleTo: Player|Array, Type: Beam, StartPosition: Vector, EndPosition: Vector, Color: Color, Reevaluation: EffectReeval). | -| `Create Dummy Bot` | ✅ Supported | Parameters: (Hero: Hero|Array, Team: Team, Slot: Number, Position: Vector, Direction: Vector). | +| `Create Dummy Bot` | ✅ Supported | Parameters: (Hero: Hero|Array, Team: Team, Slot: Number|Boolean, Position: Vector, Direction: Vector). | | `Create Effect` | ✅ Supported | Parameters: (VisibleTo: Player|Array, Type: Effect, Color: Color, Position: Vector|Player, Radius: Number, Reevaluation: EffectReeval). | | `Create HUD Text` | ✅ Supported | Parameters: (VisibleTo: Player|Array, Header: Object|String, Subheader: Object|String, Text: Object|String, Location: HudPosition, SortOrder: Number|Boolean, HeaderColor: Color, SubheaderColor: Color, TextColor: Color, Reevaluation: HudReeval, Spectators: SpecVisibility). | | `Create Homing Projectile` | ✅ Supported | Parameters: (Projectile: Projectile, Object: Player|Array, Position: Vector, Direction: Vector, Relativity: Relativity, ModifyHealth: ModifyHealth, Team: Team, Number: Number, Number: Number, Number: Number, DynamicEffect: DynamicEffect, DynamicEffect: DynamicEffect, Number: Number, Number: Number, Number: Number, Number: Number, Player: Player, Number: Number). | From 8493e8adea9846a1b368ffe15c787ef694b89169 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 03:39:57 +0800 Subject: [PATCH 5/6] fix(catalog): preserve empty split separators Refs wrightkit/opy-rs#330 --- crates/workshop-rs/src/catalog/data/catalog.json | 10 +++++----- crates/workshop-rs/tests/identity.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index 36fb5c53..29b4d64d 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -5253,7 +5253,7 @@ ] } ], - "digest": "3b66b40ad924a74384ae826614ef7296dd34f1785291b0e94739c560b878a01e", + "digest": "c0f9eac3ef964a58f9368fbf412caecdfcf689fb4e2e9120eac0ef56197fa9cf", "enums": [ { "domain": "Impulse", @@ -11649,7 +11649,9 @@ { "emptyArrayAsString": true }, - null + { + "emptyArrayAsString": true + } ], "paramNames": [ "string", @@ -12437,9 +12439,7 @@ { "emptyArrayAsString": true }, - { - "emptyArrayAsString": true - } + null ], "paramNames": [ "string", diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index 6f09e6ae..ca055a90 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "3b66b40ad924a74384ae826614ef7296dd34f1785291b0e94739c560b878a01e"; + "c0f9eac3ef964a58f9368fbf412caecdfcf689fb4e2e9120eac0ef56197fa9cf"; #[test] fn committed_catalog_digest_is_pinned() { From 2a28990371918346bd43f252b709f0001ac95648 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Sun, 20 Sep 2026 12:41:33 +0800 Subject: [PATCH 6/6] fix(catalog): narrow string replacement search contract Keep EntityId support limited to the replacement value and align the regression with the pinned Workshop shape. --- crates/workshop-rs/src/catalog/data/catalog.json | 4 ++-- crates/workshop-rs/tests/contextual_semantics.rs | 2 +- crates/workshop-rs/tests/identity.rs | 2 +- docs/language-support/values.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/workshop-rs/src/catalog/data/catalog.json b/crates/workshop-rs/src/catalog/data/catalog.json index 29b4d64d..ca28cdae 100644 --- a/crates/workshop-rs/src/catalog/data/catalog.json +++ b/crates/workshop-rs/src/catalog/data/catalog.json @@ -5253,7 +5253,7 @@ ] } ], - "digest": "c0f9eac3ef964a58f9368fbf412caecdfcf689fb4e2e9120eac0ef56197fa9cf", + "digest": "96c454290f8cdbf6b8c2960a3df428491fc79c7e614cd4453922e52940ab8914", "enums": [ { "domain": "Impulse", @@ -12389,7 +12389,7 @@ ], "paramTypes": [ "String|Array", - "String|Array|EntityId", + "String|Array", "String|Array|EntityId" ], "params": [ diff --git a/crates/workshop-rs/tests/contextual_semantics.rs b/crates/workshop-rs/tests/contextual_semantics.rs index 863d6b50..d7cbe2d1 100644 --- a/crates/workshop-rs/tests/contextual_semantics.rs +++ b/crates/workshop-rs/tests/contextual_semantics.rs @@ -107,7 +107,7 @@ fn entity_ids_and_boolean_string_slice_counts_match_workshop_contract() { validate_program(&setup); let derived = program( - "Set Global Variable(probe, String Slice(String Replace(Custom String(\"x\"), First Of(Last Created Entity), First Of(Last Created Entity)), 126, True)); Set Global Variable(parts, String Split(First Of(Last Created Entity), Empty Array));", + "Set Global Variable(probe, String Slice(String Replace(Custom String(\"x\"), String Split(Custom String(\"x\"), Empty Array), First Of(Last Created Entity)), 126, True)); Set Global Variable(parts, String Split(First Of(Last Created Entity), Empty Array));", ); validate_program(&derived); } diff --git a/crates/workshop-rs/tests/identity.rs b/crates/workshop-rs/tests/identity.rs index ca055a90..01d2f94f 100644 --- a/crates/workshop-rs/tests/identity.rs +++ b/crates/workshop-rs/tests/identity.rs @@ -12,7 +12,7 @@ use workshop_rs::catalog::{Catalog, Locale}; /// (`workshop-catalog-gen build`) recomputes it and the pin is updated /// deliberately together with the data. const PINNED_CATALOG_DIGEST: &str = - "c0f9eac3ef964a58f9368fbf412caecdfcf689fb4e2e9120eac0ef56197fa9cf"; + "96c454290f8cdbf6b8c2960a3df428491fc79c7e614cd4453922e52940ab8914"; #[test] fn committed_catalog_digest_is_pinned() { diff --git a/docs/language-support/values.md b/docs/language-support/values.md index 66ee4005..124cb714 100644 --- a/docs/language-support/values.md +++ b/docs/language-support/values.md @@ -232,7 +232,7 @@ This document inventories canonical Workshop values and expressions in `workshop | `String` | ✅ Supported | Returns: `String`; Parameters: (String: String, {0}: Object|Array, {1}: Object|Array, {2}: Object|Array). `Custom String` remains supported. | | `String Contains` | ✅ Supported | Returns: `Boolean`; Parameters: (String: String, String: String). | | `String Length` | ✅ Supported | Returns: `Number`; Parameters: (String: String). | -| `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array|EntityId, Replacement: String|Array|EntityId). | +| `String Replace` | ✅ Supported | Returns: `String`; Parameters: (String: String|Array, Search: String|Array, Replacement: String|Array|EntityId). | | `String Slice` | ✅ Supported | Returns: `String`; Parameters: (String: String, Start Index: Number, Count: Number|Boolean). | | `String Split` | ✅ Supported | Returns: `Array`; Parameters: (String: String|Array|EntityId, Separator: String|Array). | | `Subtract` | ✅ Supported | Returns: `Number|Vector`; Parameters: (a: Number|Boolean|Vector, b: Number|Boolean|Vector). |