G §560: a cancelled recovery act holds the move with the hand act's why

Builds: design 47 G A-117, §560
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 01:06:39 +01:00
parent 0f108fd8ac
commit b3b13f2ae1
3 changed files with 15 additions and 3 deletions
+7 -1
View File
@@ -26,6 +26,8 @@ type Ending struct {
Outcome string
Error string
Snapshot string
// Why is the hand act's words for a cancel (design 47 G A-117, §560).
Why string
}
// RecoveryWaitMinutes is the default of the manifest's config key `recovery-wait-minutes`, the bound of the wait for an
@@ -191,7 +193,11 @@ func (a *Agent) askAndWait(ctx context.Context, h Have, kind string, k KeptMove,
case ev.Error == "stopped":
act, wait.Act = "", ""
case ev.Error == "cancelled":
return ev, &recoveryHeld{Words: "cancelled"}
words := "cancelled"
if ev.Why != "" {
words += ": " + ev.Why
}
return ev, &recoveryHeld{Words: words}
default:
words := ev.Error
if words == "" {
+6 -2
View File
@@ -143,7 +143,11 @@ func testAMoveAcrossAFormChange(t *testing.T) {
fp := func(c string) string { return fpOf(c) }
done := func(act string) Ending { return Ending{Act: act, Outcome: meshrecovery.EndedEventOutcomeDone} }
failed := func(act, why string) Ending {
return Ending{Act: act, Outcome: meshrecovery.EndedEventOutcomeFailed, Error: why}
e := Ending{Act: act, Outcome: meshrecovery.EndedEventOutcomeFailed, Error: why}
if why == "cancelled" {
e.Why = "the operator stopped it" // the hand act's words (design 47 G A-117)
}
return e
}
applied := func(b *bed) bool { return len(b.appliedList()) == 2 }
heldHave := func(b *bed) bool { return b.haves.last("db").Phase == "held" }
@@ -174,7 +178,7 @@ func testAMoveAcrossAFormChange(t *testing.T) {
})
for _, row := range []struct{ error, held string }{
{"cancelled", "cancelled"},
{"cancelled", "cancelled: the operator stopped it"},
{"cap", "cap"},
{"restore point damaged", "restore point damaged"},
{"disk full", "disk full"},
+2
View File
@@ -140,6 +140,8 @@ type RecoveryEnding struct {
Outcome string `json:"outcome"`
Error string `json:"error,omitempty"`
Snapshot string `json:"snapshot,omitempty"`
// Why is the hand act's words for a cancel (design 47 G A-117, §560).
Why string `json:"why,omitempty"`
}
// HearRecoveryEnding follows the events `ended` (kind "ended") or `restored` (kind "restored") of one module's kept data: the last