65537570b82d29e7eb8590f8a3c7ba48d0a63a71
`object scripts list` previously walked obj.Attributes through a
substring heuristic (`IsScriptAttribute`) that matched any name
containing "script", "expression", "execute", "startup", "shutdown",
or "scan". Two failure modes:
- "deSCRIPTion" contains "script", so every `MoveIn*.Description` /
`MoveOut*.Description` attribute on `$MESReceiver` (and any other
object with `.Description` UDAs) was mis-emitted as a script.
- `ScanState` / `ScanStateCmd` (ordinary attribute UDAs) leaked in via
the "scan" keyword.
Net result on $MESReceiver: 25 entries, all false positives, zero
true ScriptExtensions.
The GRAccess COM API does not expose an `IScriptExtension` enumerable
(verified against ArchestrA.GRAccess.dll string table — only
`AddExtensionPrimitive` / `DeleteExtensionPrimitive` /
`RenameExtensionPrimitive` mutators exist). The only attribute-side
signal that an object carries a real ScriptExtension is the canonical
text-attribute suffix list documented in docs/script-parsing.md:
ExecuteText, DeclarationsText, StartupText, ShutdownText, OnScanText,
OffScanText, Expression.
Replace `IsScriptAttribute` with `ScriptExtensionPrefix(name)` that
detects exactly those suffixes, then group attributes by prefix:
- Each ScriptExtension yields one logical entry named by its prefix.
- The Fields[] list reports which text attributes are present.
- Sibling `<prefix>.TriggerType` / `<prefix>.TriggerPeriod` attributes
are surfaced as TriggerType / TriggerPeriod when present.
- ExtensionType is always "ScriptExtension".
Outer `ObjectScripts(IGalaxy, IgObject, PackageSnapshot)` updated to:
- Thread ExtensionType / Fields / TriggerType / TriggerPeriod through.
- Look up body content by prefix first, then fall back to
`<prefix>.ExecuteText` (the package's serialized bodies are keyed
by full attribute name).
- Mark every `<prefix>.<field>` as emitted so the package-fallback
branch doesn't re-emit each text field as its own entry.
Drop dead `IsScriptAttribute` (no other callers).
Validation against live ZB galaxy:
- $MESReceiver: 25 → 0 (correct: no ScriptExtensions on this template)
- $TestMachine: 1 entry — UpdateTestChangingInt with body
"Me.TestChangingInt = System.Random().Next(1,1000);" + all 7 fields
+ trigger metadata.
- $DelmiaReceiver: 2 entries — ProcessRecipe + Reset, both with bodies
("Me.RecipeDownloadFlag = false;") + trigger metadata.
61/61 existing tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
No description provided
Languages
C#
93.3%
TSQL
4.2%
PowerShell
1.5%
Shell
0.7%
Python
0.3%