Tune Spiral with Helix
Tuning is the process of adjusting the domain’s cost model — delay costs, noSoln outsourcing costs,
travel factors, option times, quality settings — until Spiral’s decisions match the operation’s
intent. Helix gives you a repeatable loop for it: replay a recorded situation, watch what Spiral
decides and why, adjust the domain, replay again, compare. This guide walks that loop end to end.
(Prerequisites: an admin login, a client dev environment — see
Develop a client extension — and one or more recorded
.run.json files in the client’s tests/ tree.)
1. Replay a run file
Section titled “1. Replay a run file”A run file (<name>.run.json) is a recorded input stream: every command that reached the CRUD,
in order, with its Spiral synchronisation tag. Replaying one reproduces the recorded situation
exactly.
From the landing screen choose Run File (shown when run files exist and you have the admin
permission), then pick a file from the picker — it lists the client’s tests/ directory
(HELIX_TESTS_DIR overrides the location).
Two modes:
- Continuous (default): the file streams through at full speed. The application is read-only
while loading (the top bar shows progress, e.g.
1240 of 3800 (32%)) and unlocks automatically when the final tag completes. - Single step (tick the checkbox in the picker): the file advances one tagged command at a time, and the application stays fully editable throughout — this is the tuning mode.
2. Step through the interesting part
Section titled “2. Step through the interesting part”In single-step mode the dispatch top bar (the slot that normally shows progress/errors) becomes a release button showing the next waiting command:
▶ tag 1041 — {"add":{"project":{"id":20003,"stops":{...Hover it to see the complete command; click it to release that command for processing. The next tagged command then takes its place. Untagged lines (comments, configuration) flow through without stopping.
This lets you bring the replay to precisely the moment you care about — the project whose allocation
looked wrong, the surge that triggered outsourcing — then examine the world before letting the next
command land. Because the app is not read-only, you can open editors, change values and probe
between steps. (The parked command is also available programmatically: GET /run-files/next echoes
it; POST /run-files/step releases it.)
3. Review the costs — Full / Developer mode and auto-allocate
Section titled “3. Review the costs — Full / Developer mode and auto-allocate”Switch to Full or Developer mode from the top-bar settings menu (☰ → Mode: Full / Mode: Developer). Normal mode is the operator view; the tuning detail only shows in these modes.
Auto-allocate asks Spiral to re-place a stop freely and — crucially — to explain itself:
right-click a stop row (or Ctrl+right-click its map marker) and choose Auto Allocate. Helix
sends a force coerce with rid: 0 (recalculate the resource; did: 0 for desk assignment) and
the tagged reply comes back as a Spiral reply dialog:
- Warnings are translated through the domain’s
helix.warningtemplates — the operator-facing reasons a placement was refused or penalised. simpleSolns(Full/Developer only) is Spiral’s raw solution set — the candidate resources it considered with their solution data, shown as an expandable JSON tree. This is the primary cost-review surface: compare the candidates Spiral weighed and what separated them.
Per stop, the Schedule card in the stop editor shows what the current solution costs bought:
dep / arv / fin, travel (tvl/dst), the solnTier the solution landed in, cbt
(Full/Developer), and Spiral’s info messages. Developer mode additionally shows each tree node’s
stop id (and flags #in≠out when an entity’s recorded stop id has drifted from the live document —
useful when correlating with the raw stream).
The Developer-mode CRUD dialogs (every outgoing request and raw reply shown for confirmation) are useful when you want to see exactly what a UI action sends to Spiral.
4. Inspect the runtime domain in the JSON editor
Section titled “4. Inspect the runtime domain in the JSON editor”Open the JSON Editor (☰ → JSON Editor). The entity buttons include the Define set — Stop
Parameters, Resource Parameters, Customer Parameters, Contract Parameters, Topography — each seeded
from the live reference.define of the running system. This is the runtime domain as Spiral
currently sees it: resolved values, clone chains, the lot. The Dispatch Stream Viewer below it
dumps the whole live in-memory database, reference included.
Use it to:
- confirm what a parameter actually resolved to at runtime (clone chains can surprise),
- copy the current
stopParamsblock as the starting point for your tuned version.
Note — the Define verb does not apply live. The editor lets you modify the JSON, but an interactive
definepost is rejected by the CRUD (define not available in crud mode): the domain reaches a running Spiral only through file replay or a restart. Validation therefore happens by replay, not by posting the editor’s buffer — see the next step.
5. Validate the change
Section titled “5. Validate the change”Two equivalent validation routes; both end with replaying the same run file and comparing decisions:
- Domain-file route (recommended): edit the client domain file
(
<CLIENT>.domain.json— e.g. adjust adelay.cost, anoSoln.costStop, an optiont). In the dev environment the domain is read live from the mounted repo, so the change applies on the next load — reload the same run file and step to the same moment. - Run-file route: for a self-contained experiment, copy the tuned
defineblock (from the JSON editor) into a copy of the run file, ahead of the recorded commands — replay applies defines in-stream, so the recorded traffic runs under the modified domain without touching the real file.
Compare before/after: the same auto-allocate on the same stop — did the candidate ranking change as
intended? Did solnTier improve? Did the warnings disappear? Single-stepping makes the comparison
precise because you can halt at the identical tag in both runs.
6. Land the change in the client runtime
Section titled “6. Land the change in the client runtime”Once the values are settled, make the domain-file edit permanent:
- Dev: already done — the dev loop reads
<CLIENT>.domain.jsonlive from your repo (dev loop); commit it to your client repo. - Production: rebuild and ship the client bundle —
publish-<client>.sh <version>packs the extension and the domain config, thenhelixctl deploy+ run on the node (build & deploy).
Keep the run file you tuned against in the client’s tests/ tree — it becomes the regression
baseline for the next tuning round.
Related
Section titled “Related”- Develop a client extension — the dev loop, domain-driven UI, deploy
- stopParams — the cost-model attributes (delay, noSoln, quality, appt …)
- Scenarios — scripted demonstrations (as opposed to recorded replays)
- errorObject / perfObject — Spiral’s monitoring stream