A parser and its per-case data travel as one file.NcRunnerSuit bundles a
runner with the dependency data a particular job needs, as a single file-loadable unit. The project
holds three suits — NcRunnerSuit,
CsvRunnerSuit and
ClsfRunnerSuit — and
ReadNcRunnerSuit /
WriteNcRunnerSuit switch the active parser mid-project
from a suit file. A switch attempted while a program is playing is refused with
ReadNcRunnerSuit--Refused.
One NC runner configuration is shareable across projects. Per-case data — tool offsets,
work-coordinate offsets, Siemens frames, Heidenhain datums, retained macro variables, seeded brand
parameter tables — travels as proxy placeholders inside SoftNcRunner and
resolves against the owning project's per-case list, so a controller configuration is no longer
welded to the job it was first built for. Machine-config consumers read the resolved view through
GetEffectiveNcDependencyList; legacy <NcDependencyList> XML and
NcEnv-based projects still load and migrate automatically.
HTTP guards and one envelope.RequireActiveSessionAttribute answers a
session-scoped action with HTTP 409 and an ApiActionResult.NoActiveSession() body when no session is
active, instead of the previous null-reference 500;
RequireLoadedProjectAttribute does the same for the project-level controller.
Both are applied at the controller level and honour opt-out markers
(AllowNoActiveSessionAttribute,
AllowNoLoadedProjectAttribute). Mutating actions inject a fresh
MessageCollector and return the collected notifications inline in the
shared ApiActionResult envelope, so a REST or AI caller sees progress,
success and error messages in the response instead of only out of band.
LocalProjectServiceController exposes the project-level (session-independent)
surface parallel to SessionShellController.
Session commands declare themselves.CommandCatalogAttribute marks an
ISessionCommand as user-addable and places it in a
CommandCategory (Setup / Program / Optimization / Output / Flow, declaration
order = display order) with an Order sort key and an optional wire kind (default: the class name
minus the Command suffix, lower-cased). CommandFieldAttribute marks a
bool / int / double / string property as a directly editable scalar with an optional label, unit and
physics-licence flag, so a generic editor renders and updates it without a hand-written form. A
command without the catalog attribute stays loadable from project files but is not offered for
creation.
Program File dispatches by kind.NcFileCommand gains an NcKind
property (XML element NcKind, absent = Auto for legacy projects) and its mission label becomes
“Program File”; each command resolves its own file, so a List of Program Files can mix
brand NC, CL and CSV.
Two session commands saved but could never be read back.ListCommand.Reg chained every type
except NcOptOptionCommand and
RecordMeshedGeomCommand, so any XML round-trip of an entry holding one threw
KeyNotFoundException out of the XFactory generator lookup — reloading a
saved project containing an NC Optimization Config command failed. Both are now chained.
Naming.Title is an optional name shown in place of the type
name, so nested command lists can be named in the mission tree. PreSettingCommand displays as
“General Config” and NcOptOptionCommand as “NC Optimization Config” — display strings only, so
serialization and endpoints are untouched. A bare non-list PlayerCommand root is normalized on read
into a single enabled entry of the default ListCommand. Command titles, catalog categories and field
labels are now localized, and a zh-Hans resource set was created (none existed before). Default-script
template keys stay untranslated on purpose — they compose the C# comments and script title written
into the user's .hincproj, which travels to other machines.
Script faults are keyed errors. A CompilationErrorException or a faulted script task used to
surface as an anonymous warning; ScriptCommand now reports
ScriptCommand-Compile--Failed with the full diagnostic list and ScriptCommand-Run--Fault with the
exception, both at Error severity.
A fresh session re-homes the machining chain.ResetRuntime wrote the configured XYZ home but
hard-coded ABC to 0, and it only ran on project switch or pace-player reset — never before a plain
Play. A freshly loaded project therefore started from whatever pose the .mt happened to serialize,
while the act stream interpolated from the home seed, so the first contour swept from a pose the
machine was never at and cut along the way. The re-home now reads the rotary homes from the same home
configuration and also runs at BeginSession; a
mid-session replay is untouched.
What a reset actually resets.ResetRuntime now also
rewinds the NC-runner session state, so the next play restarts file and line indexing from scratch
the way PowerReset does, and it resets the CL device pose to identity. It no longer clobbers
MachiningResolution_mm: the runtime resolution is seeded from the workpiece's initial resolution
only when a project loads, so an explicit override survives a runtime reset and a workpiece swap.
Mixed runner kinds in one session are refused.NcRunnerSessionState remembers the runner that
initialised it and RunNcLines refuses a different one with
RunNcLines--RunnerMismatch — reachable now that NcKind.Auto makes mixed-kind missions a
first-class flow.
Stale state on a chain or project switch. Building the coordinate converter nulls the rotary
solver when the chain is not an IXyzabcChain, so a solver built for the old machine no longer keeps
converting after a switch to a CL device; and
ClearCache now also calls
ClearIdealGeomCache, so loading another project stops
rendering the previous project's target geometry.
Project-file operations are serialized through a zero-wait gate. A New / Load / Save / Reload
/ Close arriving while another is in progress throws
ProjectFileBusyException immediately instead of racing into a file-in-use
IOException. Close was the one operation left outside the gate, so a Close arriving during a Save
could let the Save finish without writing and still return 200; it now refuses with the same 409
the other five ops already used.
LoadProject and
ReloadProject take a message sink for load-time
diagnostics (a referenced STL missing on disk, a child XML that will not deserialize). A load-time
diagnostic does not fail the load; passing no sink leaves the application log as the only witness.
See Message Management.
AlignWorkpieceProgramZeroToIso
computes in the machine-zero state. It reflects the assembly and zeroes every dynamic axis before
querying displacements, so the alignment is correct even when the live machine's axes are
displaced.
RunCount counts runs started, incremented synchronously before the
run's task launches and never reset. Pairing it with IsFinished in one snapshot lets a polling
client distinguish “the run I started has finished” from a stale Finished left by a previous run.