A run sometimes waits for a person: a question of the procedure (ask operator), or a decision
about a step that failed or was interrupted. An operator may also act on a run at any time:
suspend it, resume it, or abort it. Every answer and command is traced in the log with the
identity of whoever gave it.
What a run waits for#
| Waiting for | Log event | Answered with |
|---|---|---|
A confirmation (ask operator "…") | asked | yes or no |
A typed answer (ask operator "…" as <type> into <name>) | asked | A value: 27.9 V, true, STANDBY |
| A hazardous confirmation, by the roles of the environment | asked, with role | yes or no, by a person of that role |
| A decision | decision_required | replay, skip, fail or abort |
| A resumption, while suspended | suspended | stellar resume |
stellar watch prints the command expected under the event, and stellar status shows the
question or decision pending with its path.
Answering#
stellar answer <run> yes # confirm
stellar answer <run> no # refuse: the step fails
stellar answer <run> '27.9 V' # a typed answer
stellar answer <run> true
stellar answer <run> replay # a decision: replay, skip or abortstellar answer finds the step waiting in the state of the run; --path names another step.
yes and no answer accepted: true or false; any other word is the value of an accepted
answer (parsed as JSON when it can be: 3, true; a string otherwise: 27.9 V, STANDBY,
replay).
Through the API:
curl -X POST http://localhost:8080/v1/runs/<run>/answers -H 'X-Stellar-User: alice' \
-d '{"path": "Hot standby test / Power the PPU", "accepted": true, "value": "27.9 V"}'| Field | Meaning |
|---|---|
path | The step asking, as in its asked or decision_required event |
accepted | Whether the operator confirms |
value | The typed answer, or the decision: replay, skip or abort |
The API answers 202 once the answer is published to the executor on
stellar.run.approval.<run_id>, with the identity of the caller, its roles and, for a verified
token, the token itself. The executor decides whether the answer is taken.
Confirmations and typed answers#
- A confirmation answered
no(accepted: false) fails the step, which is not retried. - A typed answer is converted into the type and unit of the answer: a quantity into its unit
(
27900 mVfor anf32 V), a number, a boolean, an enum value. An answer missing or of the wrong type fails the step. - The answer is a name of the step from then on:
step "Supply voltage"
uses psu: lab-psu
ask operator "Voltage read on the bench multimeter?" as f32 V into measured
check psu.voltage is measured +/- 0.5 V- Without human orchestration (
human_orchestration: off, typicallySIMandAIT), a confirmation is acknowledged automatically: the log showsansweredwithoutby, and the run does not stop. A typed answer then fails the step: no operator is expected to give it.
Answers not taken#
The executor checks each answer with the policies of the environment of the run. An answer that
does not qualify is logged as answer_refused, with who answered and why, and the run keeps
waiting:
- with
identity: jwt, no token, a token that does not verify, or the token of someone else; - for a hazardous confirmation, someone without the role awaited, or someone who already confirmed this step.
answer of bob not taken: `bob` is not supervisorDecisions#
A step waits for a decision (decision_required) in two cases:
- a step not eligible for retry (it sends a telecommand that changes the on-board state)
failed: the reason is
the step failed: …; - a step was interrupted by a restart of the executor after a telecommand that changes the on-board state: the executor cannot know whether the telecommand acted.
| Decision | Effect |
|---|---|
replay | A new attempt of the step, with new telecommand identifiers |
skip | The step counts as passed (skipped by <operator>); the run goes on |
fail | The step counts as failed: the run goes on as after any failure — the actions up to the next if failed block are skipped, that block runs (to make the target safe), and the run ends failed |
abort | The run stops, failed, without running its if failed blocks |
A decision answered no, or with anything but replay, skip or fail, aborts the run.
Decisions are asked in every environment, human orchestration or not: only a person can say
whether replaying a state-changing telecommand is safe. A dry run is the exception: its targets
are simulated and nobody watches it, so it answers by itself, fail by default
(stellar run --dry --on-decision, see Dry runs).
Suspend, resume, abort#
stellar suspend <run>
stellar resume <run> # --choice replay (default), skip, fail or abort
stellar abort <run>| Command | API | Effect |
|---|---|---|
| Suspend | POST /v1/runs/{id}/suspend | At the end of the current instruction, the run stops and releases its leases, so that an operator can act on the targets by hand |
| Resume | POST /v1/runs/{id}/resume, {"choice": "replay"} | The leases are taken again and the targets checked ready, then the choice applies to the step where the run stopped |
| Abort | POST /v1/runs/{id}/abort | At the end of the current instruction, the run ends for good, failed, without its if failed blocks; leases released, report generated |
Details:
- Suspension and abort take effect between two statements: a telecommand already sent finishes its acknowledgement chain, and no new one leaves.
- The choices of a resumption:
replayreplays the step where the run stopped (a new attempt),skipcounts it as passed,failcounts it as failed — the run goes on as after any failure, itsif failedblocks included —,abortends the run. - A resumption whose targets are not ready, or held by another run, is refused, and the run stays suspended.
- A suspended run can be aborted with
stellar abort, or resumed with--choice abort. - Live hazardous confirmations of a replayed step are asked again.
- The log traces
suspended(with the step and the operator) andcontinued(with the choice); an abort ends withfinishedand the reasonaborted by <who>; a step failed by the choice readssuspended by <who suspended>, failed by <who resumed>. - A run taken over by another executor while suspended stays suspended.
- An alarm reaction suspends the run holding its target (
by=alarm <key>) before its own run starts; see Alarm Handling.
The API sends the command to the executor holding the run, on stellar.run.control.<run_id>,
and waits for its reply:
| Status | Code | Meaning |
|---|---|---|
202 | Accepted by the executor | |
404 | api::unknown-command | Not suspend, resume nor abort |
409 | run::not-running | No executor holds the run: it is over, or not started |
409 | run::refused | The executor refused: no suspension to resume, targets not ready, unknown choice… |
504 | run::timeout | The executor did not answer within 30 s |
Identity#
Answers and commands need the identity of the operator: a token (--token, STELLAR_TOKEN,
Authorization: Bearer) or, where the environment allows it, a declared identity (--as,
--role; X-Stellar-User, X-Stellar-Role). The environment of the run applies, as at launch:
- an answer or a command without any identity is refused (
api::anonymous); - with
identity: jwt, a declared identity is refused (auth::jwt-required).
See Identity and Roles.