bd95ace1c5
Investigation findings: IAttribute.SetValue silently no-ops for any attribute whose AttributeCategory starts with `MxCategoryPackageOnly`. The COM call returns Successful=true and the dispatcher reports OK, but a verify-read via direct IAttribute.GetValue confirms the value is unchanged. Discovered while validating the new --field flag round-trip on \$DelmiaReceiver.ProcessRecipe.ExecuteText: - BEFORE write: ExecuteText body = `Me.RecipeDownloadFlag = false;` - WRITE: scripts set --field ExecuteText --file marker.txt → OK - AFTER write: ExecuteText body = `Me.RecipeDownloadFlag = false;` (UNCHANGED — the marker prefix from marker.txt is absent) - ConfigurableAttributes shows `ProcessRecipe.ExecuteText` category = `MxCategoryPackageOnly_Lockable`. Same for DeclarationsText, StartupText, ShutdownText, OnScanText, OffScanText, Expression. - Per docs/script-parsing.md:8, "Object-level scripts ... may appear as attributes, extension attributes, or only inside exported object packages" — script-text fields are in the third bucket. Trigger settings (TriggerType, TriggerPeriod) are `MxCategoryWriteable_C_Lockable` and remain effective via SetValue — verified by `scripts settings set --trigger-period-ms 1000` returning OK on a clean checkout state. Add `EnsureMutableViaSetValue(IAttribute, name)` helper that throws InvalidOperationException with a clear remediation hint when called on a package-only attribute. Wired into three write sites: - `case "value-set"` (object attribute value set) - `ObjectScriptSet` (scripts set body writer) - `SetScriptSettings` Expression branch (the one trigger-related field that's package-only; TriggerType/TriggerPeriod stay unguarded) Validation against live ZB galaxy: - Before fix: `scripts set --field ExecuteText` returned `success: true` but didn't mutate the body. - After fix: same call returns `success: false` with `"Attribute 'ProcessRecipe.ExecuteText' has category 'MxCategoryPackageOnly_Lockable'. Package-only attributes silently no-op via IAttribute.SetValue and can only be edited through the package import/export round-trip..."` (exit code 1). - `scripts settings set --trigger-period-ms 1000` against the same script: still OK (TriggerPeriod is Writeable_C_Lockable). The real fix for editing script bodies is the package-rewrite path — export `.aaPKG`, modify the binary script-extension records, re-import via `galaxy.ImportObjects`. graccesscli already has the read half (`PackageSnapshotParser.Parse`); the write half is a separate followup. 61 → 63 → 63 (no test count delta this commit; the new helper is exercised end-to-end by the live validation above; unit tests for the failure path require a mock IAttribute proxy that's out of scope here). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
graccesscli
A .NET Framework 4.8 / x86 CliFx-based CLI for automating AVEVA / Wonderware System Platform Galaxy configuration through the ArchestrA GRAccess COM interop library (ZB.MOM.WW.GRAccess.Cli).
Hard constraints
GRAccess is a 32-bit COM stack. Skipping any of these will fail at load or corrupt Galaxy state:
- Target framework / arch:
net48,x86,[STAThread]. No exceptions. - Cannot be loaded from a .NET 10 / x64 process — see
GRAccess-DLL-and-DotNet10-Notes.md. - AVEVA System Platform must be installed locally (or
ArchestrA.GRAccess.dllregistered in the GAC atC:\Windows\assembly\GAC\Archestra.GRAccess\1.7.0.0_23106a86e706d0ae\). The bundled copy inlib/is for build-time reference only. - In daemon mode, every COM call must be marshalled through
Session/StaComThread.cs; calling GRAccess from any other thread will deadlock or corrupt state. - Keep the root
GRAccessAppalive for the lifetime of any derivedIGalaxy/IgObjecthandle. - Mutation flow is fixed:
CheckOut → modify → Save → CheckIn(comment). SkippingCheckInleaves the object locked in the Galaxy repo. - Build requires Visual Studio / MSBuild with the
x86platform target.
Layout
graccesscli/
ZB.MOM.WW.GRAccess.Cli.slnx # solution
lib/ArchestrA.GRAccess.dll # bundled COM interop assembly (reference only)
src/ZB.MOM.WW.GRAccess.Cli/ # CLI project (net48, x86, CliFx)
tests/ZB.MOM.WW.GRAccess.Cli.Tests # test project
docs/ # CLI workflows, LLM contract, parsing/editing guides
AGENTS.md # coding-agent rules for this tool
CLAUDE.md # detailed agent guide
graccess_documentation.md # full GRAccess API reference
graccess_operations.md # GRAccess operations grouped by functional area
usage.md # compatibility copy of docs/usage.md
GRAccess-DLL-and-DotNet10-Notes.md # platform / 32-bit COM / .NET 10 incident notes
requirements-mutation-typelib-fix.md # active mutation-path defect tracker
Resource index
| Task | Go to |
|---|---|
| Coding-agent rules for working in this folder | AGENTS.md |
| General agent guide (project overview, references) | CLAUDE.md |
| Full GRAccess API surface (types, methods) | graccess_documentation.md |
| GRAccess operations grouped by functional area, with page refs | graccess_operations.md |
| CLI commands, options, session mode, IPC protocol | docs/usage.md |
| LLM-facing operating contract (envelopes, safety, batch) | docs/llm-integration.md |
| Add a new CLI command end-to-end | docs/adding-features.md |
| Inspect / read existing templates (read-only) | docs/template-parsing.md |
| Parse template attributes and setting families | docs/attribute-parsing.md |
| Parse script libraries and object-level scripts | docs/script-parsing.md |
| Edit existing templates safely | docs/template-editing.md |
| Create / edit template instances, areas, engine assignments, I/O | docs/template-instance-editing.md |
| Edit template attributes, UDAs, extensions, setting families | docs/attribute-editing.md |
| Edit script libraries and script-bearing template content | docs/script-editing.md |
Live ZB galaxy reference (read-only capture) |
docs/zb-galaxy.md |
Live ZB $TestMachine template family reference |
docs/zb-testmachine.md |
| CliFx framework reference (commands, options, DI, testing) | docs/clifx_reference.md |
| GRAccess DLL / 32-bit COM / .NET 10 platform notes | GRAccess-DLL-and-DotNet10-Notes.md |
| Active mutation-path COM lifecycle defects | requirements-mutation-typelib-fix.md |
Index for docs/ only |
docs/README.md |
Maintenance
Documentation rules live in ../DOCS-GUIDE.md; the root task → tool index lives in ../CLAUDE.md. When adding, renaming, or removing any doc in this folder, update the resource index above in the same change. When the user-facing CLI surface changes, update docs/usage.md (and keep usage.md aligned).