# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a .NET Framework 4.8 console application (CLI) for automating Aveva System Platform Galaxy configuration via the **ArchestrA GRAccess** COM/.NET library. The GRAccess API exposes a hierarchical object model rooted at `GRAccessAppClass` for programmatically managing Galaxies, templates, instances, attributes, users, roles, and security. ## Key References - **GRAccess documentation**: `graccess_documentation.md` (full API reference, type definitions, code examples) - **GRAccess DLL**: `lib/ArchestrA.GRAccess.dll` — COM interop assembly, referenced by the CLI csproj - **GRAccess operations**: `graccess_operations.md` - all library operations organized by functional area with page references - **CLI usage**: `docs/usage.md` - all CLI commands, options, session mode, IPC protocol. **Must be updated whenever commands are added or changed.** - **LLM integration**: `docs/llm-integration.md` - implemented LLM-facing operating contract, stable envelope, safety rules, validation, batch plans, and IDE intent wrappers. - **Adding features**: `docs/adding-features.md` - checklist for adding commands, dispatcher handlers, capabilities metadata, LLM output, validation, tests, and documentation. - **ZB galaxy documentation**: `docs/zb-galaxy.md` - read-only documentation captured from the live `ZB` galaxy with `graccess_cli`. - **ZB TestMachine documentation**: `docs/zb-testmachine.md` - deep read-only documentation of the `ZB` `$TestMachine` template family and instances. - **Template parsing**: `docs/template-parsing.md` - read-only workflow for inspecting existing templates such as `TestMachine`. - **Attribute parsing**: `docs/attribute-parsing.md` - detailed workflow for parsing all template attributes and setting families. - **Script parsing**: `docs/script-parsing.md` - workflow for parsing script libraries and object-level scripts. - **Template editing**: `docs/template-editing.md` - end-to-end workflow for safely editing existing templates. - **Template instance editing**: `docs/template-instance-editing.md` - workflow for creating and editing template instances, areas, engine assignments, and I/O settings. - **Attribute editing**: `docs/attribute-editing.md` - detailed workflow for editing template attributes, UDAs, extensions, and setting families. - **Script editing**: `docs/script-editing.md` - workflow for editing script libraries and script-bearing template content. - **CliFx reference**: `docs/clifx_reference.md` - local copy of CliFx framework docs (commands, parameters, options, DI, testing) - The DLL's default GAC path is `C:\Windows\assembly\GAC\Archestra.GRAccess\1.7.0.0_23106a86e706d0ae\Archestra.GRAccess.dll` ## Solution Layout ``` ZB.MOM.WW.GRAccess.Cli.slnx ├── lib/ArchestrA.GRAccess.dll ├── docs/usage.md ├── docs/llm-integration.md ├── docs/adding-features.md ├── docs/zb-galaxy.md ├── docs/zb-testmachine.md ├── docs/template-parsing.md ├── docs/attribute-parsing.md ├── docs/script-parsing.md ├── docs/template-editing.md ├── docs/template-instance-editing.md ├── docs/attribute-editing.md ├── docs/script-editing.md ├── docs/clifx_reference.md ├── graccess_documentation.md ├── graccess_operations.md ├── src/ZB.MOM.WW.GRAccess.Cli/ # CLI project (net48, x86, CliFx) │ ├── Program.cs # Dual entry: CLI mode or --daemon mode │ ├── IsExternalInit.cs # Polyfill for init accessors on net48 │ ├── Commands/Session/ # session start|stop|status commands │ ├── Session/ # Daemon infrastructure │ │ ├── StaComThread.cs # STA thread + Win32 message pump │ │ ├── SessionDaemon.cs # Named pipe server, idle timeout │ │ ├── SessionClient.cs # Named pipe client │ │ └── SessionInfo.cs # Session state file (PID, pipe name) │ ├── GRAccess/ │ │ ├── GRAccessConnection.cs # Wraps connect/login/logout │ │ └── PackageSnapshot.cs # Read-only exported package parser for deep snapshots │ ├── Protocol/ # IPC message DTOs │ │ ├── PipeRequest.cs │ │ ├── PipeResponse.cs │ │ └── PipeProtocol.cs │ └── Infrastructure/ │ └── CommandRouter.cs # Routes via session or one-shot └── tests/ZB.MOM.WW.GRAccess.Cli.Tests/ # xunit + Shouldly ``` ## Build & Test Commands ```bash # Build dotnet build src/ZB.MOM.WW.GRAccess.Cli/ZB.MOM.WW.GRAccess.Cli.csproj -p:Platform=x86 # Run CLI dotnet run --project src/ZB.MOM.WW.GRAccess.Cli/ZB.MOM.WW.GRAccess.Cli.csproj -- # Run all tests dotnet test tests/ZB.MOM.WW.GRAccess.Cli.Tests/ZB.MOM.WW.GRAccess.Cli.Tests.csproj -p:Platform=x86 # Run a single test dotnet test tests/ZB.MOM.WW.GRAccess.Cli.Tests/ --filter "FullyQualifiedName~TestName" ``` Target framework is **.NET Framework 4.8** (SDK-style csproj). Must target **x86** (both CLI and test projects) because GRAccess is a 32-bit COM component. Uses **CliFx** for CLI parsing — commands are classes implementing `ICommand` with `[Command]`, `[CommandParameter]`, and `[CommandOption]` attributes. C# 9.0 `init` accessors require the `IsExternalInit.cs` polyfill; `required` keyword is not available. ## Session Architecture The CLI supports two execution modes to avoid expensive repeated GRAccess connections: ### One-shot mode (default) Opens connection, runs command, closes. Simple but slow. ### Session mode ```bash graccess session start --galaxy MyGalaxy --node MyNode # spawns daemon graccess session status --galaxy MyGalaxy # check status graccess --galaxy MyGalaxy # routes via daemon graccess session stop --galaxy MyGalaxy # tears down ``` **How it works:** Same binary, two codepaths. `--daemon` hidden flag (bypasses CliFx) launches the daemon which: 1. Acquires a `Mutex` (`Global\graccess-session-{galaxy}`) for single-instance 2. Starts a `StaComThread` (STA thread + Win32 message pump for COM interop) 3. Connects to the galaxy on the STA thread 4. Writes session info to `%LOCALAPPDATA%\ZB.MOM.WW.GRAccess.Cli\sessions\{galaxy}.json` 5. Listens on named pipe `graccess-session-{galaxy}` for JSON requests 6. Auto-exits after idle timeout (default 30 min) **IPC protocol:** Newline-delimited JSON over named pipes. Request types: `execute`, `shutdown`, `status`. **`CommandRouter`** detects active sessions via `SessionClient.TryConnect()` and routes commands through the pipe. Falls back to one-shot if no session is running. **Key constraint:** All GRAccess COM calls must execute on the `StaComThread`. The daemon marshals work via `RunAsync(Func)` which posts to a `ConcurrentQueue` and wakes the message pump with `PostThreadMessage(WM_APP)`. For LLM/deep parsing, prefer `object snapshot`, `object lineage`, and `object children` with `--llm-json`. These commands use typed GRAccess reads first and can fall back to temporary GRAccess-exported package parsing for lineage, contained objects, scalar attribute values, and script bodies. Normal CLI behavior must not query the Galaxy Repository SQL database; SQL is only for development verification/debugging. ## GRAccess API Patterns All GRAccess code must follow these patterns: 1. **Entry point must use `[STAThread]`** — GRAccess is a COM STA component 2. **`GRAccessApp` must stay in scope** for the lifetime of any GRAccess objects — do not let it get garbage collected 3. **Error handling**: Check `CommandResult.Successful` after every API call. Multi-object operations return `CommandResults` (plural). These work like `GetLastError` in C++. 4. **Workflow for modifying objects**: `CheckOut()` → make changes → `Save()` → `CheckIn(comment)` 5. **Collections are 1-based**, not 0-based 6. **Namespace**: `using ArchestrA.GRAccess;` — classes are `GRAccessAppClass`, `MxValueClass`, etc. ### Typical connection flow ```csharp GRAccessApp grAccess = new GRAccessAppClass(); IGalaxies galaxies = grAccess.QueryGalaxies(Environment.MachineName); IGalaxy galaxy = galaxies["GalaxyName"]; galaxy.Login("", ""); // ... work with galaxy ... galaxy.Logout(); ``` ## GRAccess Object Model Hierarchy ``` GRAccessApp (root) ├── IGalaxies → IGalaxy │ ├── IGalaxySecurity → ISecurityGroups → ISecurityGroup │ ├── IGalaxyRoles → IGalaxyRole → IGalaxyUsers → IGalaxyUser │ └── IgObjects (QueryObjects/QueryObjectsByName) │ ├── ITemplate → CreateInstance() → IInstance │ └── IInstance (CheckOut/Save/CheckIn/Deploy/Undeploy) │ └── IAttributes → IAttribute (Get/SetValue via MxValue) ├── IToolsets → IToolset ├── IScriptLibraries → IScriptLibrary └── ICommandResults → ICommandResult ``` ## Important Type Definitions - **`EgObjectIsTemplateOrInstance`**: `gObjectIsTemplate` or `gObjectIsInstance` — used in query methods - **`MxDataType`**: `MxString`, `MxInteger`, `MxFloat`, `MxBoolean`, etc. - **`MxAttributeCategory`**: `MxCategoryWriteable_USC_Lockable`, etc. - **`EAuthenticationMode`**: `galaxyAuthenticationMode`, `osAuthenticationMode` - **`MxValue`/`MxValueClass`**: Universal value container (like Variant), handles type conversions automatically ## Platform Requirements - Must run on a machine with Aveva System Platform (Application Server) installed, or have the GRAccess DLL registered - For remote machine access, the OSConfigUtility must have been run - On 64-bit OS, the import path must include `(x86)`: `C:\Program Files (x86)\ArchestrA\Framework\Bin\`