This commit is contained in:
2026-09-15 01:12:50 +08:00
parent 2db889ad89
commit 1a75503105
99 changed files with 4168 additions and 726 deletions
@@ -90,17 +90,24 @@
<p>The Mission branch root of the <a class="xref" href="../index.html">Execution page</a>'s Control Tree: route
<code>/execution</code>, Control-Tree path <code>execution/mission</code>, panel <code>MissionRootPanel.vue</code>. <code>/mission</code>
resolves to the same place — it redirects onto <code>/execution?tree=execution/mission</code>.</p>
<p>The panel edits one list of commands: the mission's own command, which is always a
<a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html">ListCommand</a>. The branch root is therefore a list editor — Add Command, the
entries in run order, and the operations that rewrite the list. Editing a command is not this
panel's job: clicking a row selects that command's tree node, and the command's own editor renders
on that node's panel.</p>
<p>The node roots one list of commands: the mission's own command, which is always a
<a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html">ListCommand</a>. Its entries are the node's tree children, in run order, and
the row operations that rewrite the list — Add Command, drag, move up, move down, duplicate, delete —
live on the Control Tree rows and run in the tree host; no panel carries a second copy of them. The
one panel-side insert is the Program File editor's multi-pick: picking several files at once keeps
the first on that command and adds one Program File command per further file right after it, in its
own list, then hands the host the inserted range so the same busy gate and id translation cover the
rebuild. The root's own panel is informational: the command count and the run-order hint. Editing a
command is not this node's job either: selecting a command row opens that command's own editor on
its node's panel.</p>
<p>Command nodes are addressed by index-derived tree ids and by dotted API paths (<code>&quot;0&quot;</code>, <code>&quot;1&quot;</code>, nested
<code>&quot;0.2&quot;</code>). A command node id extends its parent's, so a root entry is <code>execution/mission/{index}</code> and
an entry inside a nested list is <code>execution/mission/{index}/{index}</code>; a command's section children
extend it once more, as <code>execution/mission/{index}/{id}</code> keyed on the section. Both forms shift on
every structural change — deleting entry 2 slides the next command into path <code>&quot;2&quot;</code> — so each branch
build stamps its nodes afresh and the editor panels remount onto the new paths.</p>
build stamps its nodes afresh and the editor panels remount onto the new paths, and the host carries
its own index-based ids — the expansion set, the Add focus and the selection — through every row op
so they follow the rows rather than the slots.</p>
<h2 id="key-models">Key Models</h2>
<ul>
<li><strong>Primary</strong>: <a class="xref" href="../../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_PlayerCommand">PlayerCommand</a> — the mission's command,
@@ -122,17 +129,19 @@ top-down.</li>
<ul>
<li>Mission Root Panel
<ul>
<li>Head Line
<li>No-Project Caption
<ul>
<li>Add Command Button
<ul>
<li>Opens the Add Command dialog. Disabled while no project is open.</li>
<li>&ldquo;No project loaded. Open or create a project first.&rdquo; while nothing is open; the head line,
separator and empty state are withheld with it.</li>
</ul>
</li>
<li>Head Line
<ul>
<li>Commands Caption</li>
<li>Command Count Badge
<ul>
<li>Outlined, and grey rather than primary while the list is empty.</li>
<li>The root list's own entries — the node's command children. Outlined, and grey rather than
primary while the list is empty.</li>
</ul>
</li>
</ul>
@@ -140,56 +149,101 @@ top-down.</li>
<li>Separator</li>
<li>Empty State
<ul>
<li>&ldquo;No project loaded&rdquo; while nothing is open; otherwise &ldquo;No commands yet&rdquo;, naming Add Command.</li>
</ul>
</li>
<li>(Each) Command Row
<ul>
<li>Drag Handle Icon
<ul>
<li>The whole row is draggable; the handle is the affordance for it.</li>
</ul>
</li>
<li>Command Label
<ul>
<li>The command's title as the engine composes it: the kind's localized display name, with a
title the user typed appended as <code>Name [title]</code>.</li>
</ul>
</li>
<li>Move Up Button / Move Down Button
<ul>
<li>Disabled at the ends of the list.</li>
</ul>
</li>
<li>Duplicate Button</li>
<li>Delete Button</li>
<li>A disabled command's row is dimmed, and its buttons stay live.</li>
<li>Clicking the row anywhere but on a button selects that command's tree node.</li>
</ul>
</li>
<li>Drop-Out Zone
<ul>
<li>Present in a nested list editor only, and shown only while a row is being dragged. It sits
below the rows, so the rows do not shift under the pointer at drag start.</li>
<li>&ldquo;No commands yet. Click Add Command to create one.&rdquo; while the list is empty.</li>
</ul>
</li>
<li>Run-Order Hint
<ul>
<li>Commands run top-down, and the checkbox on each command's tree item enables or disables it.</li>
<li>Always present. It names the row affordances: commands run top-down in the Control Tree; add
one with + on the Mission or a List row; drag a row to reorder it; a row's own buttons move,
duplicate or delete it; its checkbox enables or disables it.</li>
</ul>
</li>
</ul>
</li>
<li>Mission Root Row (Control Tree)
<ul>
<li>Add Command Button
<ul>
<li>The <code>+</code>, always visible and pinned to the row's right edge. Opens the Add Command dialog
scoped to the root list. Disabled while no project is open, and while the busy gate is held —
a mission op, or a checkbox toggle's save, in flight.</li>
<li>The row carries no drag handle and no command ops. It is a drop target: anywhere on its height
lands the dragged command in the root list.</li>
</ul>
</li>
</ul>
</li>
<li>(Each) Command Row
<ul>
<li>Enable Checkbox
<ul>
<li>The tree's tick, and the command's enable switch; a disabled command's label is dimmed.</li>
</ul>
</li>
<li>Drag Handle Icon
<ul>
<li>The whole row is draggable; the handle is the affordance for it. Plain and List command rows
carry one; the root row does not.</li>
</ul>
</li>
<li>Command Label
<ul>
<li>A real link to the node's <code>?tree=</code> URL, so the browser's context menu can open it in a new
tab, while a plain click keeps the in-app selection. The text is the command's title as the
engine composes it: the kind's localized display name, with the command's key value appended
in brackets where the kind has one — a List's or Script's typed title, a Program File's file,
a resolution's millimetres, a switch's On / Off.</li>
</ul>
</li>
<li>Move Up Button / Move Down Button / Duplicate Button / Delete Button
<ul>
<li>Hidden at rest, revealed on hover and on the selected row, and always shown where there is no
hover to reveal them with (touch). Move Up is disabled on the first entry and Move Down on the
last; all four while the busy gate is held — a mission op, or a checkbox toggle's save, in
flight.</li>
</ul>
</li>
<li>Add Command Button
<ul>
<li>On a List row only: the same <code>+</code>, scoped to that list, to the right of the row buttons.</li>
</ul>
</li>
<li>Drop Indicator
<ul>
<li>A primary edge line for a before / after landing, a tinted row for a landing into a list; the
dragged row itself dims.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Enable/disable is not a control on this panel. It is the tree item's checkbox on the command node; a
disabled command is skipped when the mission plays and stays fully editable.</p>
<p>Enable/disable is not a control on any panel. It is the tree item's checkbox on the command node; a
disabled command is skipped when the mission plays and stays fully editable. A toggle PUTs straight
to the Mission API and flips the node's own state, with no rebuild; on failure the checkbox snaps
back. The toggle holds the same busy gate as the structural ops while its save is on the wire — a
row op sent meanwhile could be applied first server-side and land the flag on whichever command
slid into the ticked path — so until the save lands every row button and <code>+</code> is disabled, no drag
starts, the tree selection is refused, an op that still reaches the host returns silently, and a
further checkbox click snaps back. The gate holds in the other direction too: the checkboxes and
the tree selection are read-only while a mission op is in flight, since a tick would address the
node's pre-op path.</p>
<h2 id="add-command">Add Command</h2>
<p>The button opens a search-first picker. The search box matches a command's display label, its kind
key, or one of its declared aliases — each alias searchable both by its English key and by its word
in the request language. Arrow keys walk the results and Enter takes the highlighted one. Results
are grouped by category, in the catalog's own display order.</p>
<p>The picked command is appended to the list this editor is scoped to, and the branch rebuilds in
place: the selection stays on the list rather than jumping into the new command's panel.</p>
<p>The <code>+</code> on the Mission root row, or on any List row, opens a search-first picker. The search box
matches a command's display label, its kind key, or one of its declared aliases — each alias
searchable both by its English key and by its word in the request language. Arrow keys walk the
results and Enter takes the highlighted one. Results are grouped by category, in the catalog's own
display order. One pick per opening: a second click or Enter before the dialog has closed adds
nothing.</p>
<p>The picked command is inserted right after the focused command when that command is a direct
entry of the list the <code>+</code> is scoped to, and at that list's tail otherwise. The focus is one for the
whole mission, not one per list: the most recently selected command anywhere in the tree (a section
row counts for its owning command), or the last command an Add landed on. So the Mission row's <code>+</code>
never chases a focus inside a nested list — and once a nested command has been selected, the root
row's <code>+</code> appends at the root's tail rather than after whichever root command was selected before
it. The branch rebuilds in place, the new row is revealed and becomes the focus, so a run of adds
lands in order below it, and the selection stays where it was rather than jumping into the new
command's panel.</p>
<p>The addable set is served by the backend rather than mirrored in a frontend menu. Every engine
command carrying <code>[CommandCatalog]</code> is reflected into the catalog, so attributing a new engine
command is all it takes for it to appear in the dialog. Thirteen kinds ship:</p>
@@ -207,42 +261,64 @@ Failure, Physics</li>
can override that choice.</p>
</div>
<h2 id="ordering-duplicating-and-deleting">Ordering, Duplicating and Deleting</h2>
<p>Every structural op runs through one path in the tree host: a busy gate that holds every row
affordance, the tree selection and the checkboxes read-only while the op is in flight — the one
gate a checkbox toggle also holds while its save is on the wire, so an op and a tick never
interleave on the server; the open editor's dirty flush — an editor with staged edits (Script, NC
Code, a List's title) saves or resolves them first, waiting for a save already on the wire, and a
refused flush drops the op with a notice rather than silently; the API call; a rebuild scoped to
the list the op rewrote; then the post-op selection. The selection follows the acted-on row only
when it already rode on it — that row, or a node under it — and otherwise stays on its own
re-indexed row, so the editor the user is in is left alone.</p>
<p>Move Up and Move Down move an entry within its own list; they never change which list owns it.
Duplicate deep-clones the entry through the same XML round-trip the project file uses — so a nested
list copies with its whole subtree — and the clone lands right after the source. Delete asks for
confirmation in a dialog naming the command.</p>
list copies with its whole subtree — and the clone lands right after the source; a selection riding
on the source moves onto the clone. Delete asks for confirmation in a dialog naming the command,
before the dirty gate runs, so a cancelled delete forces no save prompt on the open editor; a
selection riding on the deleted row lands on the nearest remaining entry of that list, or on the
list node itself once the list is empty, where Add Command waits.</p>
<p>Dragging a row has three landings:</p>
<ul>
<li>On another row — reorder within this list. A plain row splits at its midline into before and
after, and the whole new order is sent as one ordered path list.</li>
<li>On the middle band of a <code>list</code> row — move the entry inside that list. That row's outer quarters
still reorder around it.</li>
<li>On the drop-out zone of a nested list editor — move the entry out, landing right after the list
command itself in the owning list.</li>
<li>On a command row's edge — before or after it. A plain command row splits at its midline; a List
row's outer quarters are its edges. When both rows share a list this is a reorder, and the whole
new order is sent as one ordered path list; when they do not, the entry relocates into the
target's list at that slot — which is also the way out of a nested list.</li>
<li>On the middle band of a List row — move the entry inside that list, at its tail.</li>
<li>On the Mission root row — anywhere on its height moves the entry into the root list, at its tail.</li>
</ul>
<p>The last two are the same reparent call. The server resolves both lists to object references before
it mutates either, so the index shift the removal causes cannot misroute the insert, and it refuses
to move a list into itself or into one of its own descendants.</p>
<p>Which call a landing makes depends on whether the entry changes list, not on where the pointer
sat. A landing that keeps the list — an edge in the entry's own list, or an into-landing on the
list that already holds it (a List row's middle band, or the Mission root row for a root entry),
which sends it to the tail — is the reorder call, the whole new order as one ordered path list; a
landing that changes the list — into a list the entry is not in, or an edge in another list — is
the reparent call. The client refuses to drop a row onto itself or into its own subtree, starts no
drag while the busy gate is held — an op, or a checkbox toggle's save, in flight — and abandons a
drop whose row was re-stamped by a rebuild mid-drag. The server resolves both lists to object
references before it mutates either, so the index shift the removal causes cannot misroute the
insert, and it refuses to move a list into itself or into one of its own descendants. A move across
lists rebuilds from the nearest list above both, and the selection follows the dragged command when
it rode on it.</p>
<h2 id="nesting">Nesting</h2>
<p>A <code>list</code> entry grows the same structure one level down: its children are its own entries, so nested
lists read as sub-trees at any depth, and the very same panel edits them. The differences are the
scope — the root list, versus the node's own dotted path — and the drop-out zone, which appears only
in a nested editor. A nested list's node adds an optional title above the embedded editor, and that
title is appended to the List name in the row and tree label.</p>
<p>Because the mission's own command is always a list, the root and a nested list are one editor at two
scopes. A project file whose stored command is something else loads with that command wrapped into
the root list, so the panel always has a list to edit.</p>
lists read as sub-trees at any depth, and the very same row affordances act on them. The difference
is the scope — the root list, versus the node's own dotted path: each List row's <code>+</code> inserts into
its own list, and a drop into either lands there. A nested list's panel is the optional title alone,
and that title is appended to the List name in the tree label.</p>
<p>Because the mission's own command is always a list, the root and a nested list are one row shape at
two scopes. A project file whose stored command is something else loads with that command wrapped
into the root list, so the branch always has a list to root.</p>
<h2 id="where-a-command-is-edited">Where a Command Is Edited</h2>
<p>A command's editor renders on its own tree node, below the control bar carrying the operations that
rewrite the parent list (Up, Down, Duplicate, Delete):</p>
<p>A command's editor renders on its own tree node; the row operations that rewrite the parent list stay
on the tree row:</p>
<ul>
<li>Nine kinds have a bespoke editor: General Config, Machining Motion Resolution,
<a class="xref" href="NcFileCommand-panel.html">Program File</a>, <a class="xref" href="NcCodeCommand-panel.html">NC Code</a>,
<a class="xref" href="script-command-panel.html">Script</a>, <a class="xref" href="NcOptOption-panel.html">NC Optimization Config</a>,
<a class="xref" href="PostExecutionCommand-panel.html">Post-Execution</a>, Record Meshed Geometry and Export Meshed
Geometry.</li>
<li><code>list</code> is edited inline by the control-bar panel: the optional title over the embedded
<a class="xref" href="ListCommand-panel.html">list editor</a>.</li>
<li><code>list</code> shows only its optional title on its node; its entries are its tree children, and
<a class="xref" href="ListCommand-panel.html">List Command Panel</a> covers what a list is and what moving in and
out of one costs.</li>
<li>The four remaining Setup kinds — Machining Resolution, Collision Detection, Pause on Failure and
Physics — are served by the generic field editor, which renders the command's reflected
<code>[CommandField]</code> scalars with server-localized labels. That is what the app does instead of
@@ -254,38 +330,59 @@ reads a command, but the catalog does not offer it: a project file that stores t
the individual commands it stands for, and the panel serves projects that construct one through the
API.</p>
<p>The multi-card kinds — General Config, NC Optimization Config and Post-Execution — put their extra
cards on section child nodes of the command, one node per card, with the card's own enable flag
surfaced as that section node's tree checkbox. Post-Execution's Shot Files Output and Optimization
Output sections appear only while the physics preference is on.</p>
cards on section child nodes of the command, one node per card. Where a card has its own enable
flag — General Config's Meshed Geometry section and each of Post-Execution's five — that flag is the
section node's tree checkbox; NC Optimization Config's five sections (Distances, Feedrate, Motion
Dynamics, Force &amp; Safety, Compensation) carry no checkbox — its enable switches sit on the command
node's own panel instead. Post-Execution's Shot Files Output and Optimization Output sections appear
only while the physics preference is on.</p>
<h2 id="source-code-path">Source Code Path</h2>
<p>See <a class="xref" href="../../index.html">HiNC App Anatomy</a> for git repository links.</p>
<h3 id="web-application">Web Application</h3>
<ul>
<li><code>wwwroot-src/src/components/controlTree/MissionRootPanel.vue</code> — this panel: Add Command, the entry
rows and their four actions, the three drag landings, and the delete confirmation. It serves the
Mission root and, embedded under a command's control bar, every nested <code>list</code> node.</li>
<li><code>wwwroot-src/src/components/controlTree/AddCommandDialog.vue</code> — the search-first catalog picker.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionRootPanel.vue</code> — this panel, informational only:
whether a project is open, the command count, the empty state and the run-order hint. It changes
nothing and emits nothing.</li>
<li><code>wwwroot-src/src/components/controlTree/ControlTreePanel.vue</code> — the tree pane that renders the
Mission rows' affordances: the drag handle, the hover-revealed move / duplicate / delete buttons on
every command row, the <code>+</code> on every list row (the Mission root included) and the Add Command
dialog it opens, plus the drop-indicator styles.</li>
<li><code>wwwroot-src/src/components/controlTree/useMissionTreeDrag.ts</code> — the HTML5 drag-and-drop
bookkeeping between Mission rows: which rows drag, which receive, the before / after / into mode
from the pointer position, and the stamp check that abandons a drop after a mid-drag rebuild.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — builds the page's two roots,
Mission above Program; owns the five mission row ops — add, drag move, step, duplicate, delete —
through one <code>missionRowOp</code> helper (the busy gate, the open panel's dirty flush, the API call, the
scoped rebuild, the post-op selection) and the index translation that carries the expansion set,
the Add focus and the selection through each op; drives the command and section checkboxes,
holding the same busy gate while a tick's PUTs are on the wire.</li>
<li><code>wwwroot-src/src/components/controlTree/AddCommandDialog.vue</code> — the search-first catalog picker;
one pick per opening.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionCommandSlavePanel.vue</code> — one entry's panel: the
move / duplicate / delete control bar over the kind's editor, or over the title input and embedded
list editor of a <code>list</code> entry.</li>
kind's editor, or the optional title input alone for a <code>list</code> entry. It forwards the editor's
dirty-switch gate — and flushes a pending title save — to the host, and relays the Program File
editor's multi-pick as a structure change on the parent list carrying the inserted range.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionSectionPanel.vue</code> — the panel of a command's
section child, rendering that one card.</li>
<li><code>wwwroot-src/src/components/controlTree/missionItemTypes.ts</code> — the Mission wave of the Control
Tree: the item types, the child builders that carry the recursion, the per-kind editor map, the
section definitions and their enable flags, and the kind and category icons.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — builds the Execution root with
the Mission branch node above the Program branch, and drives the command and section checkboxes.</li>
Tree: the item types, the child builders that carry the recursion, the per-kind editor map, and
the section definitions and their enable flags.</li>
<li><code>wwwroot-src/src/components/controlTree/missionKindIcons.ts</code> — the kind and category icons the
Add Command dialog shows.</li>
<li><code>wwwroot-src/src/api/mission.ts</code> — typed wrapper over <code>/api/Mission/*</code>: <code>listCommandEntries</code>,
<code>addEntry</code>, <code>removeEntry</code>, <code>moveEntry</code>, <code>duplicateEntry</code>, <code>reparentEntry</code>, <code>reorderEntries</code>,
<code>setListTitle</code>, <code>getCommandCatalog</code>, <code>loadCommandFields</code> / <code>setCommandField</code>, and the per-kind
readers and writers.</li>
<code>addEntry</code> (with an optional insert index, resolving to the new entry's path), <code>removeEntry</code>,
<code>moveEntry</code>, <code>duplicateEntry</code>, <code>reparentEntry</code>, <code>reorderEntries</code>, <code>setListTitle</code>,
<code>getCommandCatalog</code>, <code>loadCommandFields</code> / <code>setCommandField</code>, and the per-kind readers and
writers.</li>
<li><code>wwwroot-src/src/components/mission/GenericCommandPanel.vue</code> — the fallback editor for a catalog
kind with no bespoke panel: the command's reflected <code>[CommandField]</code> scalars.</li>
<li>The bespoke editors:
<ul>
<li><code>wwwroot-src/src/components/mission/PreSettingCommandPanel.vue</code></li>
<li><code>wwwroot-src/src/components/mission/MachiningMotionResolutionCommandPanel.vue</code></li>
<li><code>wwwroot-src/src/components/mission/NcFileCommandPanel.vue</code></li>
<li><code>wwwroot-src/src/components/mission/NcFileCommandPanel.vue</code> — also the one panel-side
insert: its multi-pick adds the extra files as new Program File commands right after its own,
through <code>addEntry</code> at an insert index.</li>
<li><code>wwwroot-src/src/components/mission/NcCodeCommandPanel.vue</code></li>
<li><code>wwwroot-src/src/components/mission/ScriptCommandPanel.vue</code></li>
<li><code>wwwroot-src/src/components/mission/NcOptOptionCommandPanel.vue</code></li>
@@ -294,18 +391,24 @@ kind with no bespoke panel: the command's reflected <code>[CommandField]</code>
<li><code>wwwroot-src/src/components/mission/ExportMeshedGeomCommandPanel.vue</code></li>
</ul>
</li>
<li><code>wwwroot-src/src/i18n/en/tree.ts</code> — the <code>tree.mission.*</code> strings this panel renders: Add Command,
the Commands caption, the no-commands-yet state, the drop-out zone, the run-order hint, the kind
display names, the section names and the operation labels.</li>
<li><code>wwwroot-src/src/i18n/en/tree.ts</code> — the <code>tree.mission.*</code> strings: Add Command, the Commands
caption, the no-commands-yet state, the run-order hint that names the row affordances, the
disabled-command hint, the cancelled-op notice, the kind display names, the section names and the
op-context phrases.</li>
<li><code>wwwroot-src/src/i18n/en/common.ts</code> — the row buttons' titles (Move up, Move down, Duplicate,
Delete), the List title's label and the no-project caption.</li>
<li><code>wwwroot-src/src/i18n/en/dialog.ts</code> — the Delete Command confirmation.</li>
<li><code>wwwroot-src/src/router/routes.ts</code> — resolves <code>/mission</code> onto <code>/execution?tree=execution/mission</code>.</li>
<li><code>Missions/MissionController.cs</code> — the entry lifecycle (<code>GET list-command/entries</code>,
<code>POST list-command/entries</code> and <code>POST list-command/entries/{path}</code> to add at the root or inside a
nested list, <code>DELETE list-command/entries/{path}</code>, <code>POST list-command/entries/{path}/move</code>,
nested list — at an optional <code>insertIndex</code>, answering the new entry's index and path —
<code>DELETE list-command/entries/{path}</code>, <code>POST list-command/entries/{path}/move</code>,
<code>PUT list-command/reorder</code>, <code>POST list-command/entries/{path}/duplicate</code> and
<code>POST list-command/entries/{path}/reparent</code>), the <code>GET command-catalog</code> the Add Command dialog
reads, and the per-command endpoints including the generic <code>commands/{path}/fields[/{key}]</code> pair.
<code>reparent</code> is what backs both drag-into-a-list and drop-out-to-the-parent, and it is the endpoint
that rejects moving a list into itself or its own descendants.</li>
<code>reparent</code> is what backs a drop that changes the entry's list — into another list, or an edge in
another list — and it is the endpoint that rejects moving a list into itself or its own
descendants; a drop that keeps the list, the tail landing included, goes through <code>reorder</code>.</li>
<li><code>Missions/MissionCommandCatalog.cs</code> — reflects every <code>[CommandCatalog]</code> command into the addable
set served to Add Command, and creates the picked kind.</li>
<li><code>Missions/MissionCommandFields.cs</code> — the reflection layer behind the generic field endpoints: it
@@ -326,8 +429,8 @@ one when a project is read.</li>
<ul>
<li><a class="xref" href="../program.html">Program Branch</a> — the read-only inspection twin of this list: what a
run actually read, one node per NC source file</li>
<li><a class="xref" href="ListCommand-panel.html">List Command Panel</a> — the same editor one level down, and what moving an entry in or out of a nested list costs</li>
<li><a href="../../../manual/run/building-a-mission.html">Building a Mission</a> — the task this panel serves, as a procedure</li>
<li><a class="xref" href="ListCommand-panel.html">List Command Panel</a> — the same rows one level down, and what moving an entry in or out of a nested list costs</li>
<li><a href="../../../manual/run/building-a-mission.html">Building a Mission</a> — the task this branch serves, as a procedure</li>
</ul>
</article>