c12fbc5988e6037340d31ab16d5c9ca70baec6fa
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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
|
||
|
|
bd95ace1c5 |
graccesscli: fail fast on package-only attribute writes (writeback gap fix)
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> |
||
|
|
3f6bfebd6d |
graccesscli: extend script editor surface — --field, --lock-trigger-type, scripts delete
Three additions to the script editor commands. Each one closes a real gap surfaced by the round-trip-test against \$DelmiaReceiver.ProcessRecipe. 1. `object scripts set --field <name>` — explicit text-field selection. Previously `scripts set` always wrote to <Name>.ExecuteText (via ScriptAttributeName's default). To rewrite DeclarationsText / StartupText / ShutdownText / OnScanText / OffScanText / Expression, callers had to pass the full attribute name as `--script Foo.StartupText`, which is brittle. The new `--field` flag accepts any of the seven canonical ScriptTextSuffixes and composes <script>.<field> directly. Validates against the suffix list so an unrecognised --field surfaces a friendly error rather than a downstream FindAttributeForMutation failure. Default behavior (no --field) is unchanged: ExecuteText. 2. `object scripts settings set --lock-trigger-type` — parallel to the existing --lock-trigger-period. After writing TriggerType the new flag calls SetLocked(MxLockedInMe), matching the lock pattern on the period field. Without it, --trigger-type writes the value but leaves the attribute unlocked. 3. `object scripts delete` — script-named alias for the existing extension-delete subcommand. Wraps obj.DeleteExtensionPrimitive( "ScriptExtension", scriptName) inside AtomicObjectEdit (checkout / save / checkin). Removes the burden of remembering the generic `--extension-type ScriptExtension --primitive <Name>` form. Test count delta: 61 -> 63 (+2 command-shape assertions for the new ObjectScriptsSetCommand and ObjectScriptsDeleteCommand). Live round-trip-test against \$DelmiaReceiver.ProcessRecipe: - `--field DeclarationsText` write composed `ProcessRecipe.DeclarationsText`, CheckOut/Save/CheckIn all returned OK. - `--field ExecuteText` round-trip same. - A subsequent re-read shows the original body, suggesting that IAttribute.SetValue silently no-ops for ScriptExtension text fields on this GRAccess version (or the package-export reader pulls from a different snapshot than the just-saved revision). This is upstream of the editor surface — the new flags route correctly to the same SetValue path that scripts set already used. Diagnosing the SetValue ineffectiveness for script-text fields is a separate followup that should look at IScriptExtension-specific COM interfaces (per docs/script-parsing.md:8 "Object-level scripts are less direct"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
65537570b8 |
graccesscli: enumerate ScriptExtension via canonical text-attribute suffixes
`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>
|
||
|
|
32f26272ae |
Initial commit: Wonderware / System Platform tools and reference
Five tools under one repo, all docs organized per DOCS-GUIDE.md: - aalogcli: .NET 4.8 / x86 CliFx CLI for reading System Platform binary logs (*.aaLGX) for LLM debugging, built on aaOpenSource/aaLog. Commands: last, tail, range, unread, fields. Stable JSON envelope under --llm-json. Build template under lib/build/ for rebuilding aaLogReader.dll. - aot: ArchestrA Object Toolkit 2014 v4.0 reference material. Dev guide (Markdown converted from CHM), API reference for the ArchestrA.Toolkit namespace, and the Monitor / Watchdog VS sample solutions. - graccesscli: .NET 4.8 / x86 CliFx CLI that automates Galaxy configuration via the ArchestrA GRAccess COM interop. Includes session daemon, IPC protocol, and llm-json envelope contract. - grdb: SQL/DDL exploration of the Galaxy Repository database. DDL captures, reusable queries, hierarchy / contained-name <-> tag-name translation notes. - histdb: LLM-oriented reference for AVEVA Historian retrieval. INSQL linked-server, extension tables, every wwXxx time-domain extension, every retrieval mode, alarm/event SQL recipes, REST API. Distilled from the 243-page Historian Retrieval Guide. Root contains: - CLAUDE.md: thin index pointing into each tool's README. - DOCS-GUIDE.md: doctrine for organizing docs for LLM consumption. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |