Three new subcommands that take a JSONL file (or '-' for stdin) and reuse a
single MxSession across all entries. The big win is in write-batch: a
two-phase pipeline (Advise all -> drain DataChange to resolve types; Write
all -> drain WriteComplete) reduces wall time from N x (resolve + write_ack)
to ~max(resolve) + ~max(write_ack). Measured 38.2s -> 10.3s (~3.7x) for
four writes against the ZB dev galaxy; the saving grows with N.
Per-item continue-on-error: parse errors are collected line-by-line and
abort with exit 2 before any LMX session opens; runtime failures (resolve
timeout, bad references, coerce errors, write timeouts) get their own
results[] row with a typed `error` string and exit 1. Auth flags mirror
`mxa write` and are resolved once before Phase A.
Shared infra:
- Mx/JsonlInputReader.cs: lazy line reader (skips blank / '#' lines),
bare-string or {"tag":"..."} for read/sub, {"tag","value","type"?} for
write, with array-suffix consistency check at parse time.
- Mx/ValueCoercion.cs: new CoerceJToken(...) wrapper preserves the
single source of truth for type vocabulary.
Docs:
- README run examples extended for each new command.
- docs/usage.md: new "Batch input format" subsection (shared contract),
one section per command with envelope examples and a full
failure-mode table for write-batch, plus a "Batch commands -
verified live" section capturing the 2026-05-10 ZB-galaxy run and
pipelining-timing numbers.
- test-fixtures/ holds the exact JSONL files used in the verified-live
run so the doc numbers are reproducible.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a dated incident-style file at the tool root recording the full
arc of the User_Name attribution work over the last two days:
- Six runs tabulated (galaxy mode x advise variant x write variant x
resulting User_Name) so the next agent can see what's already been
ruled out.
- Current state of the CLI (auth, advise routing, WriteSecured) and
the galaxy (eOSUserBased, ArchestraUsers role, engines deployed
before the security change).
- Leading hypothesis: running aaEngine processes still operate under
the original eNone security context because galaxy security is
compiled at deploy time. Until the platform/engines are
redeployed, auth_user_id stays at 1 and User_Name stays NULL.
- Concrete pick-up commands: undeploy/redeploy DevPlatform ->
DevAppEngine -> TestArea -> TestMachine_001 via graccesscli, then
re-run the trigger / ack-as-dohertj2 / clear sequence and query
Events.
- Fallbacks if a clean redeploy doesn't change the answer
(aaBootstrap restart, two-person Verified Write, attribute
security classification check, cross-tool comparison vs Object
Viewer / InTouch).
Linked from README.md's resource index so an agent landing on the
tool finds the open thread without spelunking commit history.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New tool wrapping ArchestrA.MxAccess.LMXProxyServerClass (the same COM
proxy aaObjectViewer / WindowViewer use) as a CliFx CLI for LLM-driven
debugging.
Commands:
- mxa info — loaded MxAccess assembly identity, supported value
types, MxStatusCategory enum.
- mxa read — fetch one or more tag values; subscribes briefly,
captures first OnDataChange per tag, tears down.
- mxa write — write a value with optional --type coercion; advises
first to resolve the attribute type, then waits for
OnWriteComplete with a per-call timeout.
- mxa subscribe — stream OnDataChange events for --seconds; JSON Lines
under --llm-json for piped agent consumption.
- mxa diag — minimal smoke test on a private STA thread; bypasses
the CliFx pipeline for diagnosing apartment / pump
issues.
Implementation notes documented in docs/api-notes.md (reverse-engineered
because AVEVA does not publish a single canonical MxAccess reference):
- Net48 / x86 / [STAThread] are non-negotiable. The CLI runs the entire
CliFx pipeline on a dedicated STA thread.
- COM events are dispatched as Win32 messages; AutoResetEvent.WaitOne
alone does not pump them on this configuration. MxSession.WaitForUpdate
loops Application.DoEvents() + drain + Sleep(20ms) instead.
- Write requires the target attribute's type to be resolved first.
WriteCommand advises and waits for the initial OnDataChange before
calling LMXProxyServerClass.Write to avoid ArgumentException
"Value does not fall within the expected range".
- Errors carry the full MXSTATUS_PROXY[] from MxAccess (Success,
Category, DetectedBy, Detail) so an agent can tell exactly which
layer rejected a request.
Verified against the live ZB galaxy with a writeable tag identified
via grdb (TestChildObject.TestInt, mx_attribute_category=10):
read: 99 (q=192, MxCategoryOk)
write 7: round-tripped — read returned 7 — written back to 99
write str: TestChildObject.TestString round-tripped a timestamp
subscribe: captured initial value plus subsequent change from a
separate process
The vendored ArchestrA.MxAccess.dll is gitignored — it is copied from
C:\Program Files (x86)\ArchestrA\Framework\Bin\ on any System Platform
install per the README.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>