From 4731ab535ca7702d692906071f7e2e08bdc510ec Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 30 Apr 2026 10:23:19 -0400 Subject: [PATCH] Remove AGENTS.md superseded by CLAUDE.md The operational rules from AGENTS.md (parity contract, source-update verification matrix, MXAccess/Galaxy analysis sources, dashboard constraints, gateway-doesn't-reattach-orphans) are now in CLAUDE.md. Architecture details remain in gateway.md. Co-Authored-By: Claude Opus 4.7 (1M context) --- AGENTS.md | 481 ------------------------------------------------------ 1 file changed, 481 deletions(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index ed7d5f1..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,481 +0,0 @@ -# MXAccess Gateway Agent Guide - -Repository: https://gitea.dohertylan.com/dohertj2/mxaccessgw - -This project builds a gateway that gives modern clients full MXAccess parity -without requiring those clients to load MXAccess COM, run as x86, or own an STA -message pump. Treat the installed MXAccess COM component as the compatibility -baseline. - -Toolchain paths, versions, and external analysis locations are recorded in -`docs/toolchain-links.md`. Use that file before searching for compilers, -runtimes, protobuf tools, MXAccess notes, or Galaxy Repository SQL notes. - -Implementation planning is recorded in `docs/implementation-plan-index.md`. -Follow the order there unless the user explicitly reprioritizes: gateway first, -MXAccess worker instance second, clients third. - -## Core Contract - -Preserve MXAccess behavior first: - -- public MXAccess command semantics, -- native MXAccess event families, -- STA/message-pump delivery behavior, -- installed-provider quirks, -- HRESULT/status/value marshaling, -- per-client isolation. - -Do not simplify, normalize, or "fix" MXAccess behavior unless an explicit -non-parity mode is being implemented and tested. `MxAsbClient` and managed NMX -are future acceleration paths only; they do not define the parity contract. - -## Architecture - -The intended split is: - -```text -client - -> gRPC over TCP - -> .NET 10 x64 gateway - -> session manager - -> per-session .NET Framework 4.8 x86 worker process - -> dedicated STA thread - -> MXAccess COM instance - -> Windows/COM message pump - -> command queue - -> event sink -``` - -The gateway must never instantiate or call MXAccess directly. All MXAccess COM -interaction belongs in the worker process on its dedicated STA thread. - -The worker must not host public gRPC. Gateway-to-worker communication should use -a small local IPC protocol, with named pipes and protobuf-framed messages as the -default design. - -## Runtime Targets - -- Gateway: .NET 10, C#, x64 preferred, ASP.NET Core gRPC. -- Worker: .NET Framework 4.8, C#, x86 by default. -- Worker IPC: one bidirectional named pipe per worker. -- Worker process model: one external client session maps to one worker by - default. - -## Style Guides - -Follow the project documentation guide and the language guide for every changed -area: - -| Area | Style guide | -|------|-------------| -| Documentation | `StyleGuide.md` | -| Gateway, worker, .NET client, and C# tests | `docs/style-guides/CSharpStyleGuide.md` | -| Public gRPC and worker IPC contracts | `docs/style-guides/ProtobufStyleGuide.md` | -| Go client | `docs/style-guides/GoStyleGuide.md` | -| Rust client | `docs/style-guides/RustStyleGuide.md` | -| Python client | `docs/style-guides/PythonStyleGuide.md` | -| Java client | `docs/style-guides/JavaStyleGuide.md` | - -When a change crosses languages, apply every affected style guide. Generated -code follows its generator output; do not hand-edit it to match handwritten -style. - -## Expected Layout - -Prefer this structure unless there is a strong reason to adjust it: - -```text -src/MxGateway.Contracts/ - Protos/ - mxaccess_gateway.proto - mxaccess_worker.proto - Generated/ - -src/MxGateway.Server/ - Program.cs - Sessions/ - Workers/ - Grpc/ - Dashboard/ - Metrics/ - -src/MxGateway.Worker/ - Program.cs - Ipc/ - Sta/ - MxAccess/ - Conversion/ - -src/MxGateway.Tests/ - contract tests - gateway session tests - fake worker tests - -src/MxGateway.Worker.Tests/ - value/status conversion tests - STA queue tests - -src/MxGateway.IntegrationTests/ - optional live MXAccess tests - -clients/dotnet/ - .NET 10 C# client library, test CLI, and tests - -clients/go/ - Go client module, test CLI, and tests - -clients/rust/ - Rust client crate, test CLI, and tests - -clients/python/ - Python client package, test CLI, and tests - -clients/java/ - Java client library, test CLI, and tests -``` - -The contracts project may multi-target, or the `.proto` files may be shared as -source inputs to both gateway and worker builds. - -## Public API Shape - -The external API should be session-oriented. Initial rollout should prefer -unary `OpenSession`, `CloseSession`, and `Invoke`, plus server-streaming -`StreamEvents`. Add a bidirectional `Session` stream after the command and event -model is stable. - -Do not compress MXAccess into generic verbs too early. Use a command enum with -method-specific payloads so parity can be tested method by method. - -Core MXAccess commands to represent: - -- `Register` -- `Unregister` -- `AddItem` -- `AddItem2` -- `RemoveItem` -- `Advise` -- `UnAdvise` -- `AdviseSupervisory` -- `AddBufferedItem` -- `SetBufferedUpdateInterval` -- `Suspend` -- `Activate` -- `Write` -- `Write2` -- `WriteSecured` -- `WriteSecured2` -- `AuthenticateUser` -- `ArchestrAUserToId` - -Diagnostics may include `Ping`, `GetSessionState`, `GetWorkerInfo`, -`DrainEvents`, and `ShutdownWorker`. - -## Event Requirements - -Represent every public MXAccess event family: - -- `OnDataChange` -- `OnWriteComplete` -- `OperationComplete` -- `OnBufferedDataChange` - -Preserve per-worker event order. The gateway must not reorder events emitted by -the same MXAccess instance. - -Event DTOs should carry event family, session id, server handle, item handle, -value, quality, timestamp, `MXSTATUS_PROXY[]` equivalent, raw HRESULT/status -fields when available, event sequence, worker timestamp, and gateway receive -timestamp. - -## Value And Status Rules - -Use a protobuf value union that can represent COM `VARIANT` values and arrays. -When a value cannot be losslessly converted, preserve both the best typed -projection and enough raw diagnostic metadata to reproduce the case. - -Represent `MXSTATUS_PROXY` explicitly. Do not collapse status arrays into a -single success flag. - -Command replies should include protocol status, COM HRESULT if available, -MXAccess return values, method-specific out parameters, and status arrays where -the MXAccess method emits them. - -## Galaxy Repository SQL Discovery - -Galaxy tags, hierarchy, and attribute details can be queried from the AVEVA / -Wonderware System Platform Galaxy Repository SQL Server database. Use this as a -discovery and metadata path only; runtime MXAccess parity still belongs to the -MXAccess-backed worker unless an explicit non-parity backend is being designed. - -Full notes, schema details, screenshots, and query examples are in: - -```text -C:\Users\dohertj2\Desktop\lmxopcua\gr -``` - -Important files in that notes directory: - -- `connectioninfo.md` - SQL Server connection details and `sqlcmd` usage. -- `layout.md` - hierarchy vs `tag_name` relationship. -- `build_layout_plan.md` - extraction plan for hierarchy and attributes. -- `schema.md` and `ddl/` - Galaxy Repository schema reference. -- `queries/hierarchy.sql` - deployed object hierarchy. -- `queries/attributes.sql` - user-defined dynamic attributes. -- `queries/attributes_extended.sql` - system plus user-defined attributes. -- `queries/change_detection.sql` - deployment-change polling via - `galaxy.time_of_last_deploy`. - -Current documented connection is SQL Server `localhost`, database `ZB`, Windows -Auth. Example: - -```powershell -sqlcmd -S localhost -d ZB -E -Q "SELECT time_of_last_deploy FROM galaxy;" -``` - -Key tables from the notes are `gobject`, `template_definition`, -`dynamic_attribute`, `attribute_definition`, `primitive_instance`, and -`galaxy`. The hierarchy uses contained names for human-readable browsing, while -runtime tag references use globally unique `tag_name` values such as -`.`. - -## MXAccess Analysis Source - -Use the local MXAccess analysis project when answering questions about installed -MXAccess classes, interfaces, fields, events, HRESULT/status behavior, value -projection, captures, and parity gaps: - -```text -C:\Users\dohertj2\Desktop\mxaccess -``` - -Primary files: - -- `README.md` - overview of available analysis and capture artifacts. -- `docs/MXAccess-Public-API.md` - COM class, ProgID, CLSID, method list, - event signatures, `MxDataType`, `MxStatus`, and `MXSTATUS_PROXY`. -- `docs/MXAccess-Reverse-Engineering.md` - installed runtime path and x86 COM - constraints. -- `docs/Current-Sprint-State.md` and `docs/DotNet10-Native-Library-Plan.md` - - current parity gaps and managed native-client research status. -- `src/MxTraceHarness/` - x86 MXAccess harness examples using the real COM - interop assembly. -- `captures/` and `analysis/` - observed native behavior and generated - reverse-engineering artifacts. - -Concrete MXAccess COM target from the analysis: - -- class: `ArchestrA.MxAccess.LMXProxyServerClass` -- CLSID: `{C30B52F5-2CB5-4760-AF0A-3A344A7EB5DC}` -- ProgID: `LMXProxy.LMXProxyServer.1` -- version-independent ProgID: `LMXProxy.LMXProxyServer` -- registered server: `C:\Program Files (x86)\ArchestrA\Framework\Bin\LmxProxy.dll` -- interop assembly: - `C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll` -- threading model: `Apartment` - -## Worker Rules - -Each worker owns: - -- one process, -- one MXAccess session, -- one dedicated STA thread, -- one MXAccess COM object, -- one inbound command queue, -- one outbound event queue. - -All MXAccess operations must run on the STA. A plain blocking queue is not -enough for the STA; the STA loop must pump Windows/COM messages and service -queued commands. - -Do not block the STA on pipe writes, gRPC calls, or slow consumers. Event -handlers should convert event args, enqueue outbound events, and return to -pumping messages. - -On graceful shutdown, reject new commands, optionally clean up active MXAccess -handles, detach events, release the COM object, uninitialize COM, and exit. If -graceful shutdown exceeds the configured timeout, the gateway may kill the -worker. - -## IPC Rules - -Default pipe name shape: - -```text -mxaccess-gateway-{gatewayProcessId}-{sessionId} -``` - -Frame messages as: - -```text -uint32 little-endian payload_length -payload_length bytes protobuf WorkerEnvelope -``` - -Every envelope should include protocol version, session id, monotonic sender -sequence, correlation id, and a typed body. Protocol version mismatch should -fail session creation. - -Pipe security should be local-machine only, with ACLs restricted to the gateway -identity and launched worker identity. Prefer a per-session nonce handshake. - -## Gateway Rules - -The gateway is responsible for: - -- public TCP/gRPC API, -- Blazor Server dashboard using Bootstrap CSS/JS only, -- authn/authz when needed, -- session creation and teardown, -- worker launch and lifecycle management, -- command routing, -- event streaming, -- leases, heartbeats, timeouts, and quotas, -- worker kill/restart policy, -- metrics and structured logs. - -The gRPC layer should stay thin: validate request, find session, call the -session worker client, map worker replies to public replies, and stream events. -Keep MXAccess-specific translation logic testable outside the gRPC handlers. - -Dashboard code should also stay thin and read-only for v1. Use a snapshot -service over session/worker/metrics state; do not let Razor components mutate -gateway sessions or workers directly. Do not use MudBlazor or other Blazor UI -component libraries. - -Gateway restart should not try to reattach old workers in the first version. -Terminate orphaned workers on startup if that behavior is implemented. - -## Command, Timeout, And Cancellation Semantics - -Command lifecycle: - -```text -client gRPC command -gateway validates session and payload -gateway assigns correlation id -gateway writes WorkerCommand to pipe -worker queues command to STA -STA executes MXAccess method -worker captures return/out/status/HRESULT -worker sends WorkerCommandReply -gateway completes gRPC response -``` - -Canceling a gRPC call should stop waiting in the gateway, but it cannot safely -abort an in-flight COM call on the STA. Hard cancellation means killing the -worker process. - -If a command wedges the STA beyond a configured grace period, the gateway should -kill the worker and fail the session. - -## Backpressure Policy - -Worker outbound events must use a bounded queue. For parity testing, prefer -fail-fast behavior over silent drops. Production coalescing or drop policies -must be explicit and observable. - -The gateway should preserve per-session event order, apply backpressure from -slow gRPC streams, and disconnect or coalesce only according to an explicit -policy. - -## Security And Logging - -Use TLS for remote gRPC when crossing machine boundaries. Authentication may be -Windows auth, mTLS, or a deployment-specific token. - -Commands that write, authenticate users, or alter runtime state need explicit -authorization design. - -Never log passwords or raw credential values for `AuthenticateUser`, -`WriteSecured`, or related secured operations. Do not log full values by -default; make value logging opt-in and redacted. - -## Testing Expectations - -Use focused tests for: - -- contract/protobuf compatibility, -- gateway session state and worker lifecycle, -- gateway behavior with a fake worker, -- worker value/status conversion, -- STA queue and message-pump behavior. - -Live MXAccess integration tests are optional but should be isolated because they -depend on installed COM components and provider behavior. - -Parity tests should compare direct MXAccess behavior against the gateway: - -- return values, -- HRESULTs and exceptions, -- event sequence, -- value projection, -- quality/status arrays, -- invalid handle behavior, -- cross-server handle behavior, -- cleanup behavior. - -Known important parity areas: - -- `WriteSecured` may fail before a value-bearing NMX body is emitted. -- `WriteSecured2` can succeed in observed native paths. -- `OperationComplete` is distinct from write completion. -- `OnBufferedDataChange` has a distinct public event shape. -- Invalid handles and cross-server handles have specific exception/status - behavior. -- STA message pumping is required for event delivery. - -## Source Update Workflow - -When source code changes, build the affected component before handing work -back. If the change crosses component boundaries, build each affected component -instead of relying on a single top-level build. - -Use the native build and test command for each changed area: - -| Changed area | Required verification | -|--------------|-----------------------| -| Contracts or `.proto` files | regenerate generated code, then build gateway, worker, and every generated client touched by the contract | -| Gateway server, sessions, workers, gRPC, dashboard, or metrics | build the .NET 10 gateway project and run affected gateway or fake-worker tests | -| Worker IPC, STA, MXAccess, or conversion code | build the .NET Framework 4.8 x86 worker project and run affected worker tests | -| Shared test infrastructure | run every test suite that consumes the changed helpers | -| .NET client | build the .NET client library, CLI, and tests | -| Go client | run Go formatting, build, and tests for the Go module | -| Rust client | run Rust formatting, build or check, and tests for the Rust crate | -| Python client | run Python formatting or linting if configured, package/build checks, and tests | -| Java client | build the Java client library, CLI, and tests | -| Integration tests | run them only when the required MXAccess COM component, provider state, and external services are available; otherwise document why they were skipped | - -Update affected documentation in the same change as the source update. This -includes `gateway.md`, component design docs under `docs/`, client docs, API -contract notes, test instructions, and operational guidance. Documentation must -follow `StyleGuide.md`: write technical present-tense prose, explain the reason -for non-obvious choices, use exact code names, specify languages on code -blocks, use relative links for internal docs, and avoid stale temporary notes. -Source code and contract changes must also follow the relevant language guide -from the Style Guides section. - -Do not leave documentation describing old behavior after changing public APIs, -contracts, configuration, build steps, security behavior, event shapes, value -conversion, status mapping, lifecycle rules, or client semantics. - -## Implementation Priority - -Build the smallest end-to-end slice first: - -1. .NET 10 gateway starts. -2. Client calls `OpenSession`. -3. Gateway launches .NET Framework 4.8 x86 worker. -4. Worker creates STA and MXAccess COM object. -5. Client calls `Register`. -6. Client calls `AddItem`. -7. Client calls `Advise`. -8. Worker forwards one `OnDataChange` event to the gateway. -9. Gateway streams the event to the client. -10. Client calls `CloseSession`. -11. Gateway shuts down the worker. - -That slice proves the high-risk requirements: process isolation, STA ownership, -message pumping, command routing, and event streaming.