Add drill: an ask the operator starts at the controller's terminal, whose approval performs nothing and is recorded (hq ADR 0259)

The live acceptance needs an approval the operator can ask for at will and that changes nothing. A
drill is asked like any condition's ask, bound to its own act, claimed once on its warrant and recorded
as a warrant hand-act with who answered, through which channel and the proofs. A verb's process may not
start one, so no agent asks the operator a question they did not start.
This commit is contained in:
2026-10-09 16:22:34 +02:00
parent 2190e2c664
commit 646c5e53db
4 changed files with 183 additions and 5 deletions
+11 -5
View File
@@ -84,6 +84,9 @@ type asked struct {
// Acted is what the controller did on the warrant: empty before it did anything, "acting" while it acts,
// then "done", "failed: …" or "nothing: …". Anything but empty is never acted on again.
Acted string `json:"acted,omitempty"`
// Drill is an ask started at the controller's terminal (drill.go): about no condition, its answers
// perform nothing, and the reconciling of conditions leaves it alone.
Drill bool `json:"drill,omitempty"`
}
// askedStore keeps the asks (broker.AskedBucket).
@@ -202,7 +205,7 @@ func (a *asker) reconcile(ctx context.Context) error {
}
byCondition := map[string]asked{}
for _, r := range all {
if r.State == askOpen {
if r.State == askOpen && !r.Drill {
if prior, held := byCondition[r.Condition]; !held || r.Opened.After(prior.Opened) {
byCondition[r.Condition] = r
}
@@ -226,7 +229,7 @@ func (a *asker) reconcile(ctx context.Context) error {
}
byCondition = map[string]asked{}
for _, r := range all {
if r.State == askOpen {
if r.State == askOpen && !r.Drill {
byCondition[r.Condition] = r
}
}
@@ -490,7 +493,7 @@ func (a *asker) Decided(ctx context.Context, body []byte) error {
if err != nil {
return err
}
stillOpen := false
stillOpen := r.Drill // a drill is about no condition
for _, c := range open {
stillOpen = stillOpen || c.Key == r.Condition
}
@@ -521,9 +524,12 @@ func (a *asker) Decided(ctx context.Context, body []byte) error {
args["why"] = why
}
var acted error
if act.Arguments["silence"] != "" {
switch {
case r.Drill && act.Verb == drillVerb:
// A drill's answer performs nothing: it is recorded below as the operator's decision.
case act.Arguments["silence"] != "":
acted = a.silence(ctx, act.Arguments["silence"], conditions.MaxSilence, byWords(w), why)
} else {
default:
acted = a.call(ctx, act, args)
}
r.Ended = a.now()