Files
wwtools/graccesscli/docs/script-parsing.md
T
Joseph Doherty c12fbc5988 graccesscli/docs: document the package-only writeback boundary
Adds a new "Editing Script Content" section to script-parsing.md that
explains the IAttribute.SetValue silent-no-op behavior on
MxCategoryPackageOnly* attributes, enumerates which ScriptExtension
fields fall on each side of the boundary (text fields = no, trigger
settings = yes), names the EnsureMutableViaSetValue safety check that
landed in bd95ace, and includes a one-liner for inspecting any
object's package-only attributes via `object attributes --configurable`.

Closes the documentation gap surfaced when validating the round-trip
script edit on \$DelmiaReceiver.ProcessRecipe — the previous docs
described the read path comprehensively but said nothing about which
attributes can actually be written.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 15:52:57 -04:00

8.7 KiB

Parsing Scripts And Script Libraries

This guide describes how to capture scripts related to a template such as TestMachine.

GRAccess exposes script libraries directly through IScriptLibraries and IScriptLibrary. Object-level scripts are less direct: depending on object type and System Platform version, they may appear as attributes, extension attributes, or only inside exported object packages.

Run commands from graccess_cli. Examples assume an active session:

graccess session start --galaxy ZB --node .

Without a session, add --node . to each command.

For LLM workflows, include object script metadata in the snapshot first:

graccess object snapshot --galaxy ZB --name TestMachine --type template --llm-json
graccess object scripts list --galaxy ZB --name TestMachine --type template --llm-json
graccess object scripts get --galaxy ZB --name TestMachine --type template --script UpdateTestChangingInt.ExecuteText --llm-json
graccess object scripts get --galaxy ZB --name TestMachine --type template --script UpdateTestChangingInt --llm-json

Direct object script body readback is version-specific. The CLI tries direct GRAccess metadata first, then exports the target object to a temporary .aaPKG, recurses through nested package archives, and parses binary UTF-16 package records for ScriptExtension content. For script extension names, a bare script such as UpdateTestChangingInt resolves to UpdateTestChangingInt.ExecuteText. Explicit fields such as UpdateTestChangingInt.StartupText are preserved.

The exported package fallback can read script text fields such as ExecuteText, DeclarationsText, StartupText, ShutdownText, OnScanText, OffScanText, and Expression when present. When body access is unavailable from both direct GRAccess and package data, object scripts get reports that in structured output.

Script Library Inventory

List script libraries:

graccess script-library list --galaxy ZB --json

The current CLI returns library names. The underlying GRAccess API for IScriptLibrary exposes Name and Export(path).

Export Script Libraries

Export is the authoritative way to preserve script library content:

$out = '.\template-snapshots\script-libraries'
New-Item -ItemType Directory -Force -Path $out | Out-Null

graccess script-library export --galaxy ZB --name CommonScripts --output "$out\CommonScripts.aaslib" --confirm --confirm-target "$out\CommonScripts.aaslib"

script-library export writes a local file, so the CLI requires confirmation and a matching --confirm-target equal to the output path.

To export every listed script library, parse the JSON list and call export for each name:

$galaxy = 'ZB'
$out = '.\template-snapshots\script-libraries'
New-Item -ItemType Directory -Force -Path $out | Out-Null

$libs = graccess script-library list --galaxy $galaxy --json | ConvertFrom-Json
foreach ($lib in $libs) {
  $name = $lib.Name
  $path = Join-Path $out "$name.aaslib"
  graccess script-library export --galaxy $galaxy --name $name --output $path --confirm --confirm-target $path
}

Object-Level Script Discovery

For a template such as TestMachine, first inspect attributes and extended attributes for script-like names:

graccess object attributes --galaxy ZB --name TestMachine --type template --json
graccess object extended-attributes --galaxy ZB --name TestMachine --type template --json

PowerShell classification:

$attrs = Get-Content '.\template-snapshots\TestMachine.attributes.json' -Raw | ConvertFrom-Json
$extended = Get-Content '.\template-snapshots\TestMachine.extended-attributes.json' -Raw | ConvertFrom-Json
$all = (@($attrs) + @($extended)) | Sort-Object Name -Unique

$scripts = $all | Where-Object {
  $_.Name -match '(?i)script|execute|trigger|expression|declaration|startup|shutdown|scan'
}

$scripts | Sort-Object Name | Select-Object Name, DataType, Category, Locked

This discovers script-related setting names and metadata. For bodies, prefer object scripts get --llm-json or object snapshot --llm-json; both can include package-backed script text when GRAccess export is available. Normal CLI script parsing must not query the Galaxy SQL database; SQL is development verification/debug-only.

Editing Script Content

IAttribute.SetValue is not a complete editor for ScriptExtension content. The GRAccess COM API silently no-ops writes to any attribute whose AttributeCategory is MxCategoryPackageOnly or MxCategoryPackageOnly_Lockable — the call returns Successful=true, the surrounding checkout/save/checkin sequence completes cleanly, and a verify-read via direct IAttribute.GetValue confirms the value is unchanged.

For a ScriptExtension primitive named Foo, the package-only fields are:

Field Editable via SetValue Editable via
Foo.ExecuteText no — MxCategoryPackageOnly_Lockable System Platform IDE
Foo.DeclarationsText no — MxCategoryPackageOnly_Lockable IDE
Foo.StartupText no — MxCategoryPackageOnly_Lockable IDE
Foo.ShutdownText no — MxCategoryPackageOnly_Lockable IDE
Foo.OnScanText no — MxCategoryPackageOnly_Lockable IDE
Foo.OffScanText no — MxCategoryPackageOnly_Lockable IDE
Foo.Expression no — MxCategoryPackageOnly_Lockable IDE
Foo.TriggerType yes — MxCategoryWriteable_C_Lockable object scripts settings set --trigger-type
Foo.TriggerPeriod yes — MxCategoryWriteable_C_Lockable object scripts settings set --trigger-period-ms

The CLI guards every SetValue site with EnsureMutableViaSetValue. Writes to package-only attributes fail fast with exit 1 and a message naming the category, instead of returning a misleading success: true. This applies to:

  • object scripts set (any --field that's package-only, including the default ExecuteText)
  • object scripts settings set --expression
  • object attribute value set (any direct write to a package-only attribute)

object scripts create (which calls AddExtensionPrimitive) and object scripts delete (which calls DeleteExtensionPrimitive) are NOT affected — primitive add/delete uses a different COM path and does persist.

To inspect which attributes are package-only on a given object, use:

graccess object attributes --galaxy ZB --name '$DelmiaReceiver' --type template --configurable --json |
  ConvertFrom-Json |
  Where-Object { $_.Category -like 'MxCategoryPackageOnly*' } |
  Select-Object Name, Category

There is no documented GRAccess COM path that bypasses this restriction; the IDE edits script bodies through a separate Object Editor channel (IDM) that is not exposed to GRAccess clients. Bulk script changes that need automation should be staged via the IDE and exported to .aaPKG, then the package promoted between Galaxies via objects export / galaxy import-objects.

Export Template Objects For Script Bodies

Use object export when you need the full object configuration, including script bodies, declarations, triggers, and extension payloads that are not exposed as simple attribute metadata:

$out = '.\template-snapshots\TestMachine'
New-Item -ItemType Directory -Force -Path $out | Out-Null
$pkg = Join-Path $out 'TestMachine.aaPKG'

graccess objects export --galaxy ZB --type template --name TestMachine --output $pkg --confirm --confirm-target $pkg

The exported package should be treated as the complete vendor-owned representation. Use it as the source of truth when CLI JSON and GRAccess attribute metadata do not expose script content.

For a galaxy-wide reference export:

$pkg = '.\template-snapshots\ZB.export.aaPKG'
graccess galaxy export-all --galaxy ZB --output $pkg --json

galaxy export-all is read-only from the galaxy perspective but writes an output file.

Suggested Parse Bundle

A practical template parse bundle should include:

File Command
object.json object get
attributes.json object attributes
configurable-attributes.json object attributes --configurable
extended-attributes.json object extended-attributes
attribute-groups.json Local classifier from attribute-parsing.md
template.aaPKG objects export
script-libraries/*.aaslib script-library export

Notes On GRAccess Script Collections

Some GRAccess examples refer to Template.Scripts[index].ScriptString. The local installed GRAccess interop and docs used by this CLI expose ScriptExtension content through script-like attributes and exported package records instead. Use object scripts list/get as the supported discovery and readback contract for this repository.