controller v0.264.0: the household is told when an update is undone or held, in its language
gates / gates (push) Successful in 25s

app_update_undone / app_update_held events (09 decision 15), on by
default and seeded once on existing boxes; R-606 update sentences as
key+args rendered per reader; R-646 startup applied-meta backfill for
apps current with the catalog; R-620 a disabled notifier WARNs once per
event type. Needs hub v0.120.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-23 13:51:21 +02:00
parent c3a2aba0d2
commit bc278944a3
27 changed files with 1086 additions and 86 deletions
+20
View File
@@ -313,6 +313,26 @@ func (s *Server) localeFuncs(lang string) template.FuncMap {
"stateLabel": func(state stacks.ContainerState) string {
return b.Msg(lang, stateLabelKey(state))
},
// v0.264.0 (R-606): the update path in the reader's language. A stored sentence with no key (an
// older version's, or a composed one) renders as it is — never as an empty line.
"updatePhaseText": func(st interface{}) string {
stk := stackOf(st)
if l := stacks.UpdatePhaseLabelIn(lang, stk.UpdatePhase); l != "" && l != stacks.UpdatePhaseLabel(stk.UpdatePhase) {
return l
}
return stk.UpdatePhaseLabel // no translation for this phase: the stored label, never an empty line
},
"updateErrorText": func(st interface{}) string { return stackOf(st).UpdateErrorIn(lang) },
"holdText": func(st interface{}) string {
stk := stackOf(st)
if stk.HoldReason == "" || s.backupMgr == nil {
return stk.HoldReason
}
if held, why := s.backupMgr.RestoreHoldForLang(stk.Name, lang); held && why != "" {
return why
}
return stk.HoldReason
},
"timeAgo": func(t time.Time) string {
if t.IsZero() {
return "–"