Table of Contents

Namespace Hi.MachiningProcs

Classes

AllowNoActiveSessionAttribute

Marks a session-scoped controller action as callable without an active session, exempting it from RequireActiveSessionAttribute. Use on the session lifecycle entry points (BeginSession / EndSession), which by definition run when no session exists yet.

AllowNoLoadedProjectAttribute

Marks a project-level controller action as callable without a loaded project, exempting it from RequireLoadedProjectAttribute. Use on the endpoints that create or load a project (which by definition run when no project is open yet).

ApiActionResult

The shared outcome envelope for a web-API action: whether it succeeded and the messages it reported, in order. Returned by the project-level surface (LocalProjectServiceController) and, with HTTP 409, by the session-scoped surface (SessionShellController): on the no-active-session boundary (via RequireActiveSessionAttribute), and when one of its session calls is refused while the player is running or paused (ResetRuntime–Busy, EndSession–Busy, BeginSession–Busy) or another thread plays (ResetRuntime–BusyAnotherThread, EndSession–BusyAnotherThread), or when its player reset is refused while another thread than the player's plays (Reset–Busy), and on 200 by its RecomputeStepPhysics, whose per-call collector it flattens. A REST / AI caller therefore reads the progress / success / error notifications inline in the HTTP response instead of only out-of-band via the SignalR sinks, and can branch on Success without parsing severities.

CompiledStepColorTree

Internal Use Only. A StepColorTree compiled for evaluation: immutable, its nodes in flat arrays, read by whichever thread classifies a step. Classify(ReadOnlySpan<double>, out double) takes the values of the step properties the tree refers to, one per entry of Keys in that order and NaN for no value, and gives the id of the leaf the step falls into. Made by Compile().

CompiledStepColorTree.Leaf

A leaf of a compiled tree.

EnvironmentPhysicsFingerprint

Value fingerprint of the environment the sequential chain reads live: ambient temperature, the coolant heat condition, the spindle capability and the wear / initial spindle temperature config flags. The spindle capability is hashed by value — the energy efficiency, the working temperature upper boundary, the gear shift speed, the two dry-run coefficients and every power and torque contour with its workable duration — because the chain stores the spindle temperature and the two accumulated spindle energies it computes from them on every step; its name and note are excluded.

LocalProjectService

Root(Local) project service. Apply absolute file path.

LocalProjectServiceController

HTTP controller exposing the project-level (session-independent) operations of Hi.MachiningProcs.LocalProjectServiceController.LocalProjectService — the lean API-user surface, parallel to SessionShellController (which mirrors the session-scoped SessionShell). A controller mirrors exactly one body; project-level settings belong here, not bolted onto the session controller.

MachiningActRunner

Represents a runner for machining actions that manages milling steps, tool paths, and collision detection.

MachiningActRunnerConfig

Represents the configuration for a milling act runner. Provides settings for physics simulation, evaluation, and temperature control.

MachiningParallelProc

The step pipeline of a MachiningActRunner (play-core migration P17): the shell thread freezes every built step into one machining_pipeline_step_in_t and submits it to the native pool of core.dll (t1 sweep, t2 subtraction, t3 force on std::thread workers; P16's machining_pipeline.hiapi.cpp behind the P15 contract), and one pump thread of this class polls the completed records back in submit order and runs the sequential stage (t4: the thermal chain over the managed SeqPhysicsState, the step, the events, the consignment) as the seq worker ran it before. The four Hi.Parallels schedulers of the TPL pipeline are gone from the play path. What crosses, when and on which thread is the contract of CppCore/inc/mech/machining/machining_pipeline.hiapi.h (revision 2).

The public shape is kept: RunStep(int, double, double, SpindleDirection, CoolantMode, TimeSpan, TimeSpan, double, ISentenceCarrier, Action<MachiningStep>, StepTaskBundle, CollidedKeyPair[], CancellationToken, IMachiningService, StepDiagnosticProgress, StepScopedProgress) answers a MachiningParallelProc.StepTaskBundle whose three tasks the pump completes (Hi.MachiningProcs.MachiningParallelProc.StepTaskBundle.StepSubstractionTask and Hi.MachiningProcs.MachiningParallelProc.StepTaskBundle.StepMillingPhysicsStepTask before the sequential stage, D-19; Hi.MachiningProcs.MachiningParallelProc.StepTaskBundle.PostSeqPhysicsTask with the published step), the step index is the strip position's by construction (the position is added inside the submit lock and the record's index is overwritten with its index before the step is built, P15 R5 / P17-4), the deflection reader waits on the pipeline (__wait_force) or reads the facade of a retired step (R3), and WaitAll() drains the pool and the pump before the writer.

MachiningParallelProc.StepTaskBundle

Represents a bundle of tasks related to a milling step: the facade of a step in the pipeline, whose three tasks the pump completes in step order (play-core migration P17; the tasks of a bundle a reset seeded or the runner rebuilt are completed ones). A step behind a held one completes only when the pump reaches it (D-19).

MachiningParallelProc.SubstractionResult

Represents the result of a subtraction operation.

MachiningProject

Represents a milling project that manages the execution, simulation, and analysis of NC programs.

MachiningSession

Represents a machining session that manages the execution and optimization of machining operations. Provides functionality for controlling the machining process, handling optimization options, and managing session state. Implements IDisposable to clean up SessionWriters on session end.

MessageDto

One reported IMessage, flattened for JSON transport.

MillingUtil

Provides utility methods for milling calculations and operations.

NcKindUtil

NcKind helpers.

NcResultCompletion

Internal Use Only. What Complete(bool, Action<string>) answers: the outcome, where the file is, what it holds and the range of steps it holds.

NcResultEntry

One result folder as SessionShell.ListNcResults lists it: a sub-folder of the results directory that holds a result.db, with what the file says about itself when it opens – the program's name, when it was recorded, whether it is complete, whether the play ran to its end, the counts, whether values written after the play were taken in – else what refused it. A review opens the newest complete one by default; a folder named to it opens whether complete or not (an incomplete one with NcResult-Review–Incomplete).

NcResultFolders

Internal Use Only. The result folders of a project (the NC play result recording's P3): each recording section leaves one folder under the results directory (Output/results by default), named [NcName]-[timestamp], holding result.db and, when the stock could be written, finish.wct. The folders accumulate – nothing deletes a completed result but Delete(string) – and the latest is found by its creation time; the project file keeps no pointer to them. An orphan is a folder whose recording never completed – crashed or abandoned; DeleteOrphans(string, IProgress<IMessage>, string) removes them on request (the recorder's host only says they are there when a recording begins), repairs a file whose completion was refused, and leaves alone what it could not read or what a connection still holds. Nothing here deletes a completed result but Delete(string). A delete takes the files a recording writes (result.db, its side files, finish.wct) and then the folder, when nothing else is left in it: what the user put in a result folder, or the result folders a template without tokens put inside another, stays.

NcResultRecorder

Internal Use Only. The recorder of one play's result file (the NC play result recording's P3): the IMachiningResultSink the play's three threads hand their records to, a queue, and one writer thread of its own that feeds a SqliteNcResultWriter (Create(string, string)). The recorder is begun armed, with no file: the file and its folder (Output/results/[NcName]-[timestamp]/result.db by default, the template relative to the project folder, the name the first recorded piece's program) are created on the writer thread when the first record reaches it, so a section that records nothing leaves nothing behind. The play's threads never wait on it: a record is offered to a bounded queue, and a record the full queue refuses – the disk stalled, or a play faster than the writer – is dropped and counted, the recording going on (the file's order contract allows a gap; the recorder is Degraded from the first drop and completes its file as a play that did not run to its end); a failure of the storage turns it Failed, which leaves the file an orphan. Nothing a record does reaches the play: every exception is caught here, counted and said once on the progress.

The piece ids (the PieceId of the file) are issued here, by the piece's sentence snapshot (Of(ISentenceCarrier), the same object the steps built from the piece carry) in execution order from 0, at the piece's event; a step whose sentence had no piece event (a legacy HardNc play, whose events carry no piece) gets no id. A piece's bytes are taken once the pipeline has frozen the piece: the pieces wait in a queue of the recorder's own, the frozen ones at its head are recorded at each piece event, and a piece that has waited past twice the pipeline's freeze lag, or is still live when the recording ends (a stop, a reset, freezing turned off), is serialized by the recorder itself.

The host (LocalProjectService) wires it: NotePosAdded(ClStripPos) to PosAdded, NoteSyntaxPieceRan(SyntaxPiece) to SyntaxPieceRan, the recorder itself to ResultSink, NotePlayEnded(bool) to the play's end, and calls Complete(bool, Action<string>) or Abort() when the section ends.

NcResultReview

Internal Use Only. One recorded play result open for review on the host (the NC play result recording's P4): the result file (SqliteNcResultReader, read-only) and what the host counted while it rebuilt its strip, its steps and its physics channels from it. While a review is open the host's strip is the result's, its step reads (the two briefs) come from the file, and the panels that show a source program read the pieces through this object (FindPieceIds(int, int), FindPieceAddresses(int, int, int), TryGetSyntaxPiece(int, out SyntaxPieceRecord), TryGetStepRangeOfPiece(int, out int, out int)). Any thread may read it, during the fill too: the reader's members run under the reader's own lock, the piece-to-step table is a concurrent dictionary the fill adds to, and the counts are plain integers the fill writes (a read in the middle of the fill sees the count so far). Disposed by the host when the review closes (CloseNcResultReview(IProgress<IMessage>), every reset path): a reader-backed query after that throws ObjectDisposedException, while Directory, DatabasePath, Meta, NcFiles, the counts and TryGetStepRangeOfPiece(int, out int, out int) stay readable (the web service's status reads them after a close).

NcRunnerSessionState

NC pipeline state held on a MachiningSession and shared across multiple RunNcLines(string, IEnumerable<string>, MachiningSession, StepDiagnosticProgress, NcDiagnosticProgress, CancellationToken) calls within that session. The per-layer SyntaxPieceLayers are extended via AppendSource(IEnumerable<T>) for each subsequent file so that Previous/Next connectivity (and thus ModalCarrySyntax deep-clone) crosses file boundaries.

NcRunnerSessionState.ResumeRequest

Internal Use Only. What a hosted session hands the SoftNc runner at the start of an outermost run: whether a reset stands, the block the next run's seed is anchored to and whether that block's predecessor is the base, the machine coordinates by axis letter (mm and rad; null without a machine), the program cutter location, the tool in the spindle, and the spindle speed, direction and coolant mode the machine holds. The runner consumes it at its seed point and tells the session so (NoteResumeConsumed()).

OverloadRunFold

Internal Use Only. Folds the built steps of a play, in step order, into the runs of spindle overload and of yielding-stress overload — the consecutive steps whose ratio is above 1 — and records the step range of every rapid line the RapidCutMonitor reports: the sparse tables behind the four step properties SpindleOverloadRevolutions, SpindleOverloadPeakRatio, YieldingStressOverloadRevolutions and IsRapidCut (step coloring p08). One instance per MachiningActRunner (OverloadRunFold), kept for the session with the strip: nothing is kept on the step (0 B a step) and nothing is read from the step cache — a run is one OverloadRunTable.Run (24 B), a flushed run's boundary one int, and the memory follows the number of runs and plays, not the number of steps.

A run: consecutive steps whose ratio is above 1 — for the spindle the larger of the max spindle torque ratio and the max spindle power ratio that are known (MaxSpindleRatio(MachiningStep)), for the yielding stress its ratio. A step whose ratio is 1 or below, or unknown (NaN), and a rapid step close the run and are in none; so does a gap in the step order (a position whose step was never built: a step that faulted, the steps a stop dropped), and the flush at the start and the end of an outermost run. A change of spindle speed does not close it, every step adds its own revolutions (RevolutionsOf(MachineMotionStep): speed × duration / 2π, the seconds times the rpm over 60). Every step of a closed run reads the run's total revolutions and its peak ratio; a step of the open run reads the total so far, a lower bound. The torque and the power ratio fold into one run. The runs are of the ratios as the play computed them, or as the last step-physics recompute recomputed them: an edit of the spindle capability or the ambient reaches the ratio getters at once and the runs with the next recompute, as the card rules for an in-place edit (recompute after the edit).

One writer at a time. During a play the sequential post-physics stage observes every step (Observe(in Sample, out int, out int), through the runner's ObserveOverloadRun, after the step's channels are written and before the step-built hook fills its inspecting slot) and notes the rapid lines the monitor reports (NoteRapidCutLine(int, int, out int, out int)). The player thread, after the runner's WaitAll(), flushes at the start of an outermost run and at the end of a run that reaches its closing action (Flush(out int, out int): the open runs close, so a run of one play is never folded into the next; a nested run — an NC-embedded script's play — is part of the run around it and flushes nothing, though its closing action still notes the rapid line it closes), refolds the two run tables after a step-physics recompute (Refold(int, Func<int, Sample?>), from the rewritten channels, at the flush boundaries recorded; the rapid-cut ranges stay, the recompute does not change the removal) and resets with the strip (Reset()). A stop at a pace point has no drained point to flush at: the open runs stay open and read the total so far until the next outermost run starts or the runtime is reset; a cancellation the runner sees between blocks reaches the closing action and flushes. Readers — the step getters, a color tree, the inspecting-slot scan, the export, a request's poll — read on any thread without a lock (TryGet(int, out Run), Contains(int)); the publication order is the tables' own.

When a run closes or a rapid line is noted, the steps of that range read new values: the methods answer the range as [revisedBegin, revisedEnd), and the runner raises InternalStepsRevised with it, so the host refills those steps' inspecting slots and recolors them (the fold itself raises nothing, as the RapidCutMonitor emits nothing). A step observed and then not published (its step-built handler threw) stays in the live fold's run, where a refold skips the position: a difference in how a run is cut, on a step no reader can reach.

OverloadRunTable

Internal Use Only. The runs of one kind of overload (OverloadRunFold): the closed runs in step order, disjoint, each one OverloadRunTable.Run (24 B), and the open run, if any. Written by the fold's one writer and read by any thread without a lock. A closed run is written into the array and then published by the count (an array that is full is copied into a larger one, published before the run is written into it); the open run is an immutable record replaced whole; a run closes by first publishing its closed entry and then dropping the open record. A reader reads the open record, then the count, then the array — so a reader never finds a step of a run in neither table half, and a count read before the array names entries the array holds (an array published later holds every entry the count names, copied before its publication). A refold replaces the table whole: an enumeration (ClosedCount, GetClosed(int)) holds one table reference throughout, not the fold's property.

PhysicsInputFingerprintTable

Per-session table of the physics input fingerprints the steps were computed with, keyed by tool id plus the workpiece and the environment. The workpiece and the tool are recorded on the shell thread at every run start (RunNcLines(INcRunner, string, IEnumerable<string>, CancellationToken)) and at every tool change, the tool whenever the session builds its physics pack (GetToolPhysicsPack(int) — the moment the pack freezes what the steps compute with); the environment is recorded twice per step a play issues (on the shell thread as the step is issued, with the value its spindle-speed cache is built or kept under, and on the sequential worker once its sequential physics has run, with the capability values, coolant fields and wear switch of that moment – the step's ambient temperature and coolant object are the ones it was issued with; MachiningParallelProc), since the play reads it live on every step; a recompute (StepPhysicsRecomputer) hashes it at every step of its chain and writes every environment it ran with at its end. Read by the step-physics recompute to classify which inputs differ from what the steps carry, and written by it at its end: a completed recompute makes the table current (Overwrite(IReadOnlyDictionary<int, ToolPhysicsFingerprint>, WorkpiecePhysicsFingerprint, EnvironmentPhysicsFingerprint, int)), one that left steps on other inputs adds the inputs it wrote with beside the earlier ones (RecordBesideEarlier(WorkpiecePhysicsFingerprint, EnvironmentPhysicsFingerprint)). Thread-safe.

Every entry keeps each DISTINCT value recorded since the table was last made current (Overwrite(IReadOnlyDictionary<int, ToolPhysicsFingerprint>, WorkpiecePhysicsFingerprint, EnvironmentPhysicsFingerprint, int) after a completed recompute, or Clear()), not only the latest: an input edited during a play leaves steps on more than one value — the tool and the cutting parameter stay frozen in the running pack until the next invalidation point, while the material is read by every step from the edit on — and a later record (the tool mounted again, the next run start, the next step with the environment set back) must not hide the steps that were computed with the earlier value. The same goes for a recompute that rewrote some steps and not the others: one cancelled after it wrote, and the workpiece of one scoped to a tool, which rebuilt that tool's results alone. The recompute reruns a change class when ANY recorded value differs from the current one. The record starts at the strip's count when the session began (RecordedFromStepIndex): the steps below it were played before, and no record here speaks for them — what the session records later (the next run start, a tool change, a pack build) takes the inputs as they are then, which vouch for the session's own steps alone.

A tool entry can also hold a value no step carries: an NC optimization after the play (OptimizeNcFiles(string, string, ICuttingPara, IProgress<IMessage>, CancellationToken, ReadBulkDelegate<StepLuggage>, ReadBulkDelegate<StepBrief>)) drops the session's packs before its solve, and the builds that follow record the tool as it is then beside the play's value, until a completed recompute with the tool in scope replaces the entry (the default scope takes every tool on the strip; a recompute scoped to another tool leaves it) or the table is cleared — an input put back to the play's value meanwhile still reads as changed to such a recompute. And no workpiece record is taken per step: a value written in place on the workpiece's material or cutting parameter and written back between two records of the workpiece (a run start, a tool change, a recompute that rewrote steps) is on no record, though steps may have been computed with it — the material is read by every step as its physics runs, and the parameter's values are taken by the pack at its build (the minimum uncut chip thickness, at the tool's first step) and by its native sessions at the first force step and the first thermal step the pack serves.

PhysicsInputFingerprints

Builders of the physics input fingerprints. Every builder is null-safe on every path and never throws — a half-configured tool (no fluting, a coating layer without a material, a material without curves) is hashed with null markers, so a play-time hook can never fail the play.

PhysicsNoneMonitor

Folds, over the built steps of a play, what the session's two play-end warnings ask of the physics results on the steps that touched the workpiece:

  • Play-Physics--None — how many touched steps ran on a tool with a flute envelope (the tools the physics runs on by their kind, MachiningParallelProc.HasFluteEnvelope), and whether at least one of them carries a physics result (a no-cut or a computed MillingForceBrief, not the null one: HasMillingForceBrief).
  • Play-YieldingStress--None — per tool, on how many touched steps with a result the yielding stress ratio was evaluated and on how many it was NaN; a tool NaN on every such step is named (ToolsWhoseYieldingStressWasNeverEvaluated).
Unlike RapidCutMonitor and ToolSectionTouchMonitor it reports nothing itself: its two messages are session-level configuration warnings with no step to anchor on, so their emit sites, gates, one-shot flags and texts stay in MachiningSession (WarnIfPhysicsNeverProducedOnTouch, WarnIfYieldingStressNeverEvaluatedOnTouch), which read the accumulators at the end of the play.

Why: until the brief-into-DB chain's C2 (2026-10-06) the session scanned every strip step at the end of the play and read each step's resident force brief. The two briefs left the per-step heap in that chain's C4b (they live in the step cache DB), and a play-end scan would read the DB once per step. Folded here, on the sequential post-physics stage as each step is published, the two questions are answered while the step's result is in hand: "did the physics run" off the tri-state byte the step keeps (HasMillingForceBrief), the ratio off the brief the force stage just built. The fold sees exactly the steps the scan saw — the steps attached to a strip position: sampled before the publish and folded in its finally, so a step whose publish throws (published, reported as Step--Exception) is folded too, and a step whose stage throws before the publish is neither. A step's touch, tool and ratio do not change after its force stage (the extension that carries the ratio is built there, before the seq stage); the one thing that rewrites a published step's brief is the step-physics recompute, which can land on a paused play and be read out at that play's end — so the counters are retractable, and the recompute Replace(in Sample, in Sample)s the sample of every step whose brief it rewrites.

One instance per MachiningActRunner. Observe(in Sample) runs on the sequential post-physics stage of every built step (one thread, step order); Replace(in Sample, in Sample) runs on whichever thread drives the recompute — the player thread on the paced path, which parks the play for the recompute, or the caller's thread on the direct entry, whose contract is to be the player thread or to run while no play is live; the session reads the accumulators on the shell thread after WaitAll(), and Reset() forgets everything on a session reset, on that thread too. One private lock serialises all of them — uncontended on every step of a play — so a caller that breaks the direct entry's contract cannot corrupt the tallies.

ProjectFileBusyException

Thrown when a project-file operation (New / Load / Save / SaveAs / Reload) is requested while another one is already in progress. The newcomer is cancelled rather than queued; controllers surface this as HTTP 409 Conflict.

ProxyProjectService

Delegate (User-based) Project Service. Apply relative file path from AdminDirectory.

PublishedStepValues

Internal Use Only. The values written onto one published step, with its index (Hi.MachiningProcs.MachiningActRunner.LastPublishedStepValues): what a step-built handler reading the previous step reads, in place of a row of the store.

RapidCutMonitor

Reports a rapid traverse that removed stock: the steps of one NC line that were commanded as rapid traverse (G00, IsRapid) and touched the workpiece fold into one Play-RapidCut–Detected validation warning, anchored on the line's first touching step and carrying the line's total removed volume and its largest cutting depth. A rapid move through material breaks the tool or crashes the machine on a real run, yet with the spindle turning the engine treats it as ordinary cutting: the collision rule (Detect(bool)) pairs flute and workpiece only while the spindle speed is zero, so such a line used to pass with no message at all. A rapid plunge after M05 (the direction stops, S stays modal) is not a zero-speed step and is reported here.

One instance per MachiningActRunner. Observe(in Sample, double, bool, out Report) runs on the sequential post-physics stage of every built step (one thread, step order), Flush(double, out Report) closes the last line at the end of a play and Reset() drops a pending line on a session reset; both run on the shell thread after WaitAll(), so no lock is needed. The fold is a pure function of the samples: a closed line comes back as a RapidCutMonitor.Report and the caller emits it at its own site (Emit(in Report, IProgress<StepDiagnostic>)); the forms that take a sink wrap the two.

Folding: consecutive rapid steps with the same LineKey (the NC line number, or the sentence itself where a runner has no line numbers) form one report; a feed step, a different line or the end of the play closes it. A line re-entered later (a subprogram loop) reports again, deliberately. The report is emitted only when the line's total removed volume reaches RapidCutVolumeThreshold_mm3 (default 0: any touch, as IsTouched reads it). Zero-speed steps before any step has run with a spindle speed are skipped while collision detection is on — that rule owns them and raises Collision--Detected — and counted otherwise; a zero speed after that (an S0, a CL SPINDL/OFF, a CSV row back at 0 rpm) is a stop the collision rule leaves alone, like M05, and is counted.

RapidCutRangeTable

Internal Use Only. The step ranges of the rapid lines the RapidCutMonitor reported (RapidCutRanges): in step order, disjoint, each the line's first through last touching step. Written by the fold's one writer (the range is written into the array, then published by the count; a full array is copied into a larger one, published first) and read by any thread without a lock (the count, then the array).

RequireActiveSessionAttribute

Action filter for the session-scoped web-API surface: before a guarded action runs, verifies a machining session is active (SessionShell is non-null). When none is active it short-circuits with HTTP 409 and an NoActiveSession() envelope, so a REST / AI caller gets a helpful “call BeginSession() first” notice instead of a null-reference 500. Apply at the controller level; exempt the session lifecycle entry points (BeginSession / EndSession) with AllowNoActiveSessionAttribute.

RequireLoadedProjectAttribute

Action filter for the project-level web-API surface: before a guarded action runs, verifies a project is loaded (MachiningProject is non-null). When none is loaded it short-circuits with HTTP 409 and an NoProjectLoaded() envelope, so a REST / AI caller gets a helpful “create or load a project first” notice instead of a null-reference 500 (the project-level members — MachiningActRunner.Config, workpiece, runners — are null until a project is open). Apply at the controller level; exempt the endpoints that create or load a project with AllowNoLoadedProjectAttribute.

ScriptRenameBridge

Internal Use Only. Keeps session scripts compiling after a type they name is renamed. Apply(string) puts a using alias from each former type name to its current type in front of the script source. Every place that compiles a session script applies it: ScriptCommand, the C# line embedded in an NC program (MachiningActRunner), and the webservice's compile check and completion, so a script compiles the same way in each.

SessionShell

End-user-facing facade for a machining session: aggregates session lifecycle, NC playback, optimization, geometry I/O, and scripting infrastructure into a single delegation surface. Used as the C# script globals object and as the concrete target of ISessionCommand implementations.

SessionShellController

HTTP controller exposing SessionShell over the web API. Each action delegates to the underlying SessionShell instance owned by Hi.MachiningProcs.SessionShellController.LocalProjectService.

SetupAngleOnlineRequest

What one online setup-angle estimation samples, reads and does — the argument of ArmSetupAngleEstimation(SetupAngleOnlineRequest, IProgress<IMessage>) and EstimateSetupAngleByFirstContact(SetupAngleOnlineRequest, int, IProgress<IMessage>, CancellationToken).

SetupAngleOnlineResult

What one online setup-angle estimation did, in order: the sampled window, the mapping, the estimate, the gate, the application, the recompute.

SetupController

Controller for setup operations of machining projects.

ShellProgress

Append-only, thread-safe sink for session-level routine / lifecycle messages on the IMessage channel — one of the partitioned message homes.

This is partitioned by message kind, orthogonal to the other sinks: plain SimpleMessage notices that belong to the session as a whole (cache reset, file load / save progress, session start/done) live here; messages tied to a particular machining step live in StepDiagnosticProgress; NC-pipeline diagnostics live in NcDiagnosticProgress.

Append-only: session-routine messages are emitted sequentially, so report order already is execution order — there is no per-step anchor and no stable-index bookkeeping.

SkippedStep

What ProcAct(IAct, MachiningSession, IMachiningService, ISentenceCarrier, CancellationToken, StepDiagnosticProgress) yields in the place of a step's bundle when the step procedure built no step for a step act – no tool in the spindle, no program zero or no reachable tool tip to place it on, a cutter location that is not finite, a pose the motion valve has already covered, or a step the licence refused on a play that cannot pause (the step cap, the cloud lease or its step grant: every later step of that play is refused the same way, with no further message, and yields a SkippedStep of its own – the remaining steps of the act the refusal met included, a contour's or a CL move's – until the session's NC play ends before the program's next act; an act played directly, outside an NC play and outside the player's live run, is not ended) – so that the session's loop still checks the pose the act left the chain in, once, as it does for a built step (a play with no tool mounted keeps its stroke-limit check and its pause on failure). NextStepIndex is the index the step would have taken: the strip's count on the shell thread (ShellThreadStepIndex), which the next built step takes.

SpindleSpeedCache

Represents cached spindle speed information.

StepColorCondition

The condition of a StepColorNode: its terms, joined by Join. With All and no terms the condition holds; with Any and no terms it never holds. Saved as <When Join> with one <Term> element per term.

StepColorGroup

A node whose children are tried, in order, by the steps it takes; a step none of them takes gets no color. Saved as <Group Id Name> holding its <When> and its children.

StepColorLeaf

A node that colors the steps it takes. Saved as <Leaf Id Name Hue_deg ValueKey> holding its <When>.

StepColorNode

A node of a StepColorTree: a StepColorGroup or a StepColorLeaf. The nodes of a list are tried in order; the first whose When holds takes the step — a leaf gives it its color, a group hands it to the group's own children, where only they are tried. A node without a condition takes every step that reaches it: the list's “otherwise”.

StepColorTerm

One term of a StepColorCondition: a step property, named by its key in the step-property registry, compared against a threshold by Op. The threshold is NaN — none — for HasValue and NoValue, and must be a number for every other operation. Saved as <Term Key Op Threshold/> under a <When> element.

StepColorTree

A color tree the project defines: a step property whose value is the id of the leaf a step falls into, with a color per leaf. The nodes are tried in order; the first whose condition holds takes the step — a leaf colors it, a group hands it to the group's own children — and a node without a condition takes every step that reaches it. A tree is authored data, made to be built in a script with object initializers; what evaluates steps is the immutable CompiledStepColorTree that Compile() makes. Saved in the project file (StepColorTreeList).

StepColorTreeProblem

A problem FindProblems() finds in a tree, or one the load of a tree from XML put right (LoadProblems). A code, the place, and whether it keeps the tree from compiling.

StepColorTreeScan

Internal Use Only. What a preview scan of a tree over the strip counted (ScanStepColorTree(CompiledStepColorTree, int, int, CancellationToken)).

StepColorTreeScanLeaf

Internal Use Only. One leaf's share of a preview scan (ScanStepColorTree(CompiledStepColorTree, int, int, CancellationToken)).

StepColorTreeSlot

Internal Use Only. How a step's inspecting slot holds the outcome of a StepColorTree: the id of the leaf the step fell into in bits 63 to 32 and the leaf's shown value, a float32, in bits 31 to 0 of one double. An id below IdLimit leaves the sign and every exponent bit 0, so the packed double is finite — a subnormal or zero — whatever the value's bits, NaN included; the slot's own “no value”, NaN, is therefore never a packed outcome. Packing and unpacking move bits only: no floating-point operation runs, so no flush-to-zero or denormals-are-zero mode can change them.

StepColorTreeTrace

Internal Use Only. One step under a tree, explained (ReadStepColorTreeTrace(CompiledStepColorTree, MachiningStep)).

StepDiagnostic

An IMessage produced while constructing a MachiningStep, anchored to the step's execution-order StepIndex and (when available) its NC-source SentenceCarrier.

Decorator over an inner Message — the five IMessage members delegate to it — so a plain SimpleMessage emitted during step processing can be upgraded to a step-anchored diagnostic without the producer needing to know the step context.

StepDiagnosticAnchorUtil

Bridges a step-anchored IProgress<T> sink (e.g. StepDiagnosticProgress) back to the generic IProgress<T> surface, so out-of-step-pipeline producers can keep using the id-first MessageUtil shorthands (ValidationError, ConfigurationWarning, …) and still land a StepDiagnostic on the sink.

StepDiagnosticProgress

Append-only, thread-safe sink for step-anchored diagnostics on the IMessage channel.

This sink stores only StepDiagnostic: every message is anchored to a motion step. Per-step batches arrive via FlushTo(IProgress<StepDiagnostic>); out-of-pipeline emits (e.g. stroke-limit / tooling diagnostics) anchor themselves with AnchoredToStep(IProgress<StepDiagnostic>, int, ISentenceCarrier) before reporting. Data that already has another owner is not duplicated here — NC diagnostics live in NcDiagnosticProgress, plain session-level notices live in ShellProgress, cutter positions live in the CL strip.

Because every StepDiagnostic carries its own StepIndex anchor, ordering is recovered downstream by sorting on that anchor. Producers therefore only ever Report(StepDiagnostic) (append) — even from parallel step-processing tasks — and never insert at a computed position.

StepPhysicsChannelReader

Internal Use Only. The reader of the resident channels (StepPhysicsChannels): the per-step quantities the plural strip charts and the color trees derive from the few float32 source numbers a published step left in the channels, with the formulas the step's getters use — the same static formulas, with the spindle capability, the ambient temperature, the tool house and the physics packs of the moment — so that a poll over the whole strip and a tree's evaluation never read the step cache. One reader a runner (StepPhysicsChannelReader), read on any thread at once: the sequencing thread (the step-built hook), the inspecting-slot scan, the requests' polls and the export.

The spindle limits at a step's speed (SpindleSpeedCache) are built once per speed met and kept in a snapshot of the environment they were built from: the capability object, the ambient temperature's bits and the tool house object. A read whose environment differs from the snapshot's by identity builds a new snapshot (a capability or a tool house replaced, an ambient edited); an edit made in place on the capability object is not seen by identity, and the host drops the snapshot where it moves the inspecting-slot generation (Invalidate()) — the environment forward, the step-physics recompute's end, a session's begin — and the runner drops it with the strip.

StepPhysicsChannels

Internal Use Only. The resident channels of a play: for every published step, the twelve float32 source quantities of StepPhysicsChannel and the “thermal stress evaluated” bit, in chunks of ChunkSteps steps, a chunk allocated on the first write into it (one 32 KB column per channel a chunk, under the large-object heap threshold). Written by the sequential physics stage as it publishes each step and by the step-physics recompute for the steps it rewrites — one writer at a time — and read by the plural strip charts' polls on any thread: a value is read as it was written (a float is atomic), a chunk is published before its first value is readable, and a step never written reads NaN / false. Cleared on a session reset with the strip. The two briefs themselves live in the step cache (the brief-into-DB chain's C4b); the channels hold what a poll over the whole strip would otherwise read from it once a step.

StepPhysicsRecomputeOptions

Options of RecomputeStepPhysics(StepPhysicsRecomputeOptions).

StepPhysicsRecomputeResult

Result of RecomputeStepPhysics(StepPhysicsRecomputeOptions).

StepPhysicsRecomputer

Recomputes the step physics of the finished steps from the stored cutter-workpiece engagement with the current inputs — the engine behind RecomputeStepPhysics(StepPhysicsRecomputeOptions), and the resumable job CreateStepPhysicsRecomputeJob(StepPhysicsRecomputeOptions) hands out. One instance per call.

Order: preconditions (physics on, WaitAll, steps, tools resolvable) → classification against the session's PhysicsInputFingerprintTable (Classify(IReadOnlyList<StepPhysicsFacts?>, PhysicsInputFingerprintTable, IReadOnlyDictionary<int, ToolPhysicsFingerprint>, WorkpiecePhysicsFingerprint, EnvironmentPhysicsFingerprint, int?, bool, IReadOnlyCollection<int>), pure) → licence and para checks → a read-only pre-scan of which luggage kinds the rows the plan needs hold (the stored columns' NULL-ness, nothing decoded; the chunk loop then reads the rows themselves), that every step of the chain has its stored briefs' row (or a creation cache a failed flush left), and the chain's seed read from the store → cutter cache clears, pack invalidation, pack assertions and the thermal pre-check → the SpindleSpeedCache chain walked from step 0 → chunks of [one range read of the chunk's luggage rows and briefs' rows, brief phase in parallel, sequential chain, commit of the chunk's amendments in one transaction] with a convergence stop against the stored sequential physics states, a progress report and a drawing refresh at every chunk boundary → last-bundle patch, drawing refresh, fingerprint overwrite. The briefs the chain reads and compares against are the store's rows, not the resident copies on the steps (the brief-into-DB chain's C4a); what a chunk rewrites in memory it writes to the store before the next chunk, and takes back out of memory when its chain or that write throws.

The work is driven from outside, one chunk per TryRunNextChunk() (the first call does everything up to and including the first chunk), so that whoever drives it can pace between the chunks: the player's pace-point queue parks it at a chunk boundary on Pause and lets it see the run's cancellation on Stop; Run() drives it to the end in one call, pacing through Pace. The state between chunks lives on the instance (the chain's previous sequential physics state and motion step, the chunk cursor, the counters). Nothing is mutated before the pre-scan passed. Published objects are never mutated: every replaced brief is a new object assigned by reference.

StepScopedProgress

A per-step IProgress<T> of IMessage that accumulates the messages emitted while one step is built and, when the batch is flushed, upgrades every plain message to a StepDiagnostic anchored to this step's StepIndex / SentenceCarrier. An already step-anchored StepDiagnostic is passed on unchanged. (NC diagnostics are not seen here — they live in their own NcDiagnosticProgress, not on this channel.)

The scope is opened on the thread that plays the acts, on the strip's count at the step's act, and anchored on the same thread to the index the step's strip position receives (Index) as the step is issued -- the two agree unless another thread issued steps in between. Anchoring at the flush, after that call, puts every message of the batch on the step's own index.

It does not forward to a downstream sink as messages arrive; instead it collects them into MessageList and is drained once via FlushTo(IProgress<StepDiagnostic>) at the step's sequential post-physics stage. Because that stage runs strictly in step order, the per-step batches land in execution order with no position-scanning insert. A step the step procedure does not build (it answers no bundle) is flushed on the thread that plays the acts right away, on the index it was opened on; a step refused with a cancelled bundle, or dropped or faulted in the pipeline, is never flushed.

No locking: a single step's scope has one writer at a time -- the thread that plays the acts until the step is issued (the anchor included), then the pipeline thread that runs the step's sequential stage; the issue orders the two, and the stages in between do not touch the scope. Parallelism across steps writes to different scopes, so each step holds its own instance — never a shared mutable "current step" on StepDiagnosticProgress, which would race.

StepVariable

A step variable the project defines: a per-step indicator a C# formula computes from the step whenever it is read — for a chart, the tool-path colors, Step Properties, a step file — and that is never stored on the step. Saved in the project file (StepVariableList) and registered in StepPropertyAccessDictionary every time the registry is built, so it is listed from the project's load on and in every session, where a script's RegisterStepVariable(string, string, string, string, Func<MachiningStep, object>) lasts for its session. After editing the list, call RefreshStepVariables(IProgress<IMessage>).

StepVariableCompiler

Internal Use Only. Compiles the formulas of project StepVariables into Func<MachiningStep, double?>s the way a session script is compiled — the scripts' references and imports (ScriptOptions), with ScriptRenameBridge applied — but with no script globals: a formula reads the step it is given (and what the step reaches, such as the steps around it through step.Host.ClStrip). Each formula has to parse on its own as one C# expression or one block in braces, with no preprocessor directive, before it is compiled, so no formula reaches outside its lambda and compiling a project's formulas runs none of them. Any number of formulas compile in one compilation, each body mapped to a file of its own (#line 1 "step-variable-<i>"), so an error is placed by line and column within its formula. An outcome is kept for each script options and formula text: a compiled script cannot be unloaded, so a text is compiled once for the options it is compiled with. An editor checks a formula with Check(string, ScriptOptions), which loads and keeps nothing.

StepVariableCompiler.Error

An error within one formula.

StepVariableCompiler.Result

The outcome of one formula: its function, or the errors that kept it from compiling.

ToolPhysicsFingerprint

Value fingerprint of everything on a tool that the milling physics reads, split into the change classes the step-physics recompute distinguishes. Compared by value; a re-loaded material file with equal numbers is “no change”, an in-place script edit is a change.

ToolSectionTouchMonitor

Watches each tool section of a play — the consecutive built steps on one tool id: a tool called again after another opens a new section, the same id called again does not — for the one thing the per-step messages never say: the tool has removed nothing. Two validation warnings, at most one of each per section:

  • Tool-NoRemoval--Collision — the section has touched nothing so far and this step brings the holder or the shank into the workpiece. Anchored on the colliding step and said when that step is built, at its sequential stage, not at the pause: a play with EnablePauseOnFailure pauses on the step's Collision--Detected before the step is submitted, so this warning follows the resume, and a play stopped at that pause never says it (the stopped step is not built); and only with collision detection on (EnableCollisionDetection and its licence): the step's collision pairs are all it sees. A collision on the section's first step — the tool change pose itself — is left to the collision rule (Collision--Detected); the next colliding step of the section is reported.
  • Tool-Touch--None — the section ended (the next tool's first step, or Flush(IProgress<StepDiagnostic>) at the end of the play) and none of its steps touched the workpiece. Anchored on the section's first step, naming the tool, its step count and its first and last step; needs no collision detection. Not reported for a section with no feed step after its first one — that first step is the tool change pose itself, built in whatever motion mode was modal, so consecutive tool changes and a return home at rapid are no section to speak of — nor for a section the collision warning above already named, nor for the sections of a session that has touched nothing since its last reset: that is one setup accident, which the session says once as Play-Touch--None. A section that ends before that first touch is held back until the touch comes, and dropped by Flush(IProgress<StepDiagnostic>) when it never does. A run that stops before its end (the player terminated) does not end its open section: DropOpenSection() forgets it, at the stop and at the next run's start, so a tool the user stopped is not read as one that touched nothing.
A tool without a cutter — a spindle fan, a probe, a chip blower, defined with a holder only — is not equipped by its tool call at all (Tooling--NoCutter, or Tooling--CutterUnreadable when the cleared cutter came from a side file; once per call): its moves run tool-less and build no step, so its section is never seen here. That is how a tool that is not meant to cut stays out of both warnings.

Why: the collision rule reports every colliding step as Collision--Detected — hundreds of thousands of them in the plays this was written for — and nothing said the tool had cut nothing at all; a tool whose holder and shank never reached the stock said nothing at all. Showcase cases on 3.2.43 played a whole tool after an M06 without a touch (the cl valve carried a NaN frame from the M05 ahead of the tool change on) and read as finished until the exported stock was looked at. The valve is fixed; the combinations stay worth a sentence: a cutter whose APT profile refuses its geometry (Cutter-ShaperProfile--AptRefused: it stays equipped and removes nothing), a length offset or work offset that keeps one tool in the air, a program run on stock that is already cut — and a healthy tool whose holder or shank reaches the stock before its first cut, which is why the collision message states both readings.

One instance per MachiningActRunner. Observe(in Sample, IProgress<StepDiagnostic>) runs on the sequential post-physics stage of every built step (one thread, step order), where the step's touch flag and collision pairs are final; Flush(IProgress<StepDiagnostic>) closes the last section at the end of a play, DropOpenSection() forgets it at a run boundary and Reset() forgets everything on a session reset, all on the shell thread after WaitAll(), so no lock is needed.

WorkpiecePhysicsFingerprint

Value fingerprint of the workpiece-side physics inputs.

Structs

CompiledStepColorTree.Visit

One node tried for a step by the trace (ReadStepColorTreeTrace(CompiledStepColorTree, MachiningStep)): the node's id, whether it is a leaf, and whether its condition held (a node without a condition holds). A group that holds is followed by its children tried in order; a leaf that holds is the last visit.

NcResultRecorderCounts

Internal Use Only. What an NcResultRecorder counted: the records it wrote, the events it skipped, the records it refused or dropped, the pieces it serialized itself.

OverloadRunFold.Sample

One built step as the fold sees it — the few facts the fold needs, detached from MachiningStep so the fold is testable on synthetic steps.

OverloadRunTable.Run

One run.

PhysicsNoneMonitor.Sample

One built step as the fold sees it — the few facts it needs, detached from MachiningStep so the fold is testable on synthetic steps.

RapidCutMonitor.Report

One closed rapid line that is to be reported, as data: the fold answers it from Observe(in Sample, double, bool, out Report) and Flush(double, out Report), and the caller that owns the message channel emits it with Emit(in Report, IProgress<StepDiagnostic>) (play-core migration P9: the fold is a pure function of the samples, the message channel stays with the caller).

RapidCutMonitor.Sample

One built step as the monitor sees it — the few facts the fold needs, detached from MachiningStep so the fold is testable on synthetic steps.

RapidCutRangeTable.Range

One reported rapid line's steps, inclusive at both ends.

ToolSectionTouchMonitor.Sample

One built step as the monitor sees it — the few facts the fold needs, detached from MachiningStep so the fold is testable on synthetic steps.

Interfaces

IMachiningProjectGetter

Interface for objects that can provide a MachiningProject instance.

IProjectService

Interface for services that manage machining projects.

Enums

MachiningSession.PacedPlayRefusal

Internal Use Only. Why a paced play, a paced act or a host's session call is refused on the calling thread (FindPacedCallRefusal()); None admits it.

NcKind

Kind of an NC program file — selects which of the session's runners plays it (ActiveNcRunner / ClRunner / CsvRunner).

NcResultCompletionOutcome

Internal Use Only. How the completion of a result file ended (Complete(bool, Action<string>)).

NcResultRecorderState

Internal Use Only. Where an NcResultRecorder stands in the life of its one result file.

NcResultWctState

What became of the finished stock a result folder holds (finish.wct) when its review opened.

RenderingFlag

Flags that control which elements are rendered in the visualization.

SpindleSpeedCacheWarning

What Create(SpindleCapability, MachineMotionStep, SpindleSpeedCache, out SpindleSpeedCacheWarning) has to say about the capability it read, as data: the builder is a pure function of its inputs, and the caller that owns a message channel emits the warning at its own site with the text of WarningText(SpindleSpeedCacheWarning) (play-core migration P9: the capability contours and the message channel stay managed, the builder has no sink).

StepColorJoin

How the terms of a StepColorCondition combine.

StepColorOp

What a StepColorTerm asks of a step property. A step that has no value under the key — a numeric property that is null or NaN, a text property that is null or empty — satisfies none of the comparisons, Ne included; HasValue and NoValue tell a value from none. A bool property reads as 1 or 0.

StepPhysicsChannel

The per-step source quantities the plural strip charts read off the resident channels (StepPhysicsChannels): the few numbers of the two briefs the charts derive their series from, so that a poll over the whole strip never reads the step cache.

StepPhysicsRecomputeOutcome

What RecomputeStepPhysics(StepPhysicsRecomputeOptions) did.

StepRefusal

Why the licence holds the play back (StepRefusal): the answer of ConsumeStep(int) that refused the step MachiningParallelProc.RunStep asked for, each said once on the message channel, with the wording fixed at the report.

Delegates

ConfigStepFunc

Delegate for configuring a milling step with additional arguments.

LocalProjectService.MachiningProjectChangedDelegate

Delegate for machining project changed events.

MachiningActRunner.MachiningStepBuiltDelegate

Delegate for configuring a step with previous and current step information.