VerseGrammar: Open refuses a role named actor and two verbs with one name; edge and command-update pins
ValidateAll (one owner, called by AetheriaStores.Open) refuses duplicate verb names; Validate refuses the reserved role name actor. Tests pin the name-class edges (a z 0 9 _), a null role element, the starter verb replaced when only its description or render path differs, the grammar global updated in place, and the fixture's second allegiance and zero-role speak. The test's scoped registry is TestCatalog.Registry(). Builds; unverified until the full run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
88fb919099
commit
972848cb5f
3 changed files with 96 additions and 7 deletions
|
|
@ -40,7 +40,7 @@ public static class AetheriaStores
|
|||
// cut.md), stat modifiers, role usage (Cut 7). Fails loudly, naming the item.
|
||||
foreach (var data in cache.GetAll<EquippableItemData>()) CultRecordRefs.Validate(data);
|
||||
foreach (var data in cache.GetAll<ConsumableItemData>()) CultRecordRefs.Validate(data);
|
||||
foreach (var verb in cache.GetAll<VerseVerb>()) VerseGrammarValidation.Validate(verb);
|
||||
VerseGrammarValidation.ValidateAll(cache.GetAll<VerseVerb>());
|
||||
return cache;
|
||||
}
|
||||
catch
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ public static class VerseGrammarValidation
|
|||
public const int VerbNameMaxLength = 48;
|
||||
public const int RoleNameMaxLength = 32;
|
||||
|
||||
// The invoking subject, never a role (Ghostlight refuses a world affordance that names it: ReservedRole).
|
||||
public const string ActorRole = "actor";
|
||||
|
||||
// Canonical: a lower-case letter, then lower-case letters, digits and underscores, at most maxLength characters.
|
||||
private static bool Canonical(string name, int maxLength)
|
||||
{
|
||||
|
|
@ -67,6 +70,18 @@ public static class VerseGrammarValidation
|
|||
return true;
|
||||
}
|
||||
|
||||
// Every verb valid and no two sharing a name: a verb is found by name (Ghostlight refuses DuplicateAffordanceKind).
|
||||
public static void ValidateAll(IEnumerable<VerseVerb> verbs)
|
||||
{
|
||||
var seen = new HashSet<string>(StringComparer.Ordinal);
|
||||
foreach (var verb in verbs)
|
||||
{
|
||||
Validate(verb);
|
||||
if (!seen.Add(verb.Name))
|
||||
throw new InvalidOperationException($"VerseVerb \"{verb.Name}\": duplicate verb name.");
|
||||
}
|
||||
}
|
||||
|
||||
// Canonical names, unique role names, defined enum values. A failure names the field and the rule, and the verb once
|
||||
// its name is known canonical; it never prints a value the author wrote that is itself the fault.
|
||||
public static void Validate(VerseVerb verb)
|
||||
|
|
@ -82,6 +97,8 @@ public static class VerseGrammarValidation
|
|||
{
|
||||
if (role == null || !Canonical(role.Name, RoleNameMaxLength))
|
||||
throw new InvalidOperationException($"VerseVerb \"{verb.Name}\" Roles.Name: not a canonical role name ([a-z][a-z0-9_], 1 to {RoleNameMaxLength} characters).");
|
||||
if (role.Name == ActorRole)
|
||||
throw new InvalidOperationException($"VerseVerb \"{verb.Name}\" Roles.Name: reserved for the invoking subject, never a role.");
|
||||
if (!seen.Add(role.Name))
|
||||
throw new InvalidOperationException($"VerseVerb \"{verb.Name}\" Roles.Name: duplicate role name.");
|
||||
if (!Enum.IsDefined(typeof(VerseReferentKind), role.Binds))
|
||||
|
|
|
|||
Loading…
Reference in a new issue