# 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 -- <args>

# 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 <command> --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<T>(Func<T>)` 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\`
