praxis: an empty attention list is not always an all-clear (V-540)

ECOSYSTEM-SPEC §2.6 requires list_attention to distinguish "nothing needs
attention" from "I cannot currently tell", and to say so when a source is
failed or stale. Maven said the first one unconditionally: ListAttention
decoded into []map[string]any, the word degraded appeared nowhere, and an empty
list answered "ничего не требует внимания". A Praxis with every source dead
read as calm.

Two halves, because the spec's mechanism does not exist server-side yet. The
deployed Praxis answers /api/v1/tools/attention with a bare array and no
envelope, so praxisAttention now decodes either shape and believes a degraded
array when one arrives. Until one does, an empty list triggers one read of
/api/v1/sources, and anything that is not reporting health "ok" is named
instead of the all-clear. Zero sources is the same answer: a Praxis that polls
nothing knows nothing, which is the state of this box today.

A sources read that fails is deliberately not a hedge. The attention call
succeeded, and not being able to ask about health is not evidence of a fault.

Both hedges also cover the entity-scoped digest, where a per-entity all-clear
is the more convincing of the two. New keys attention_degraded and
attention_no_sources, in acts_ru_v1.json and the floor. The fake Praxis serves
one healthy source by default, so the existing attention tests still assert an
all-clear on purpose rather than by omission.
This commit is contained in:
2026-08-05 12:07:07 +04:00
parent c586346a60
commit 1524991adc
6 changed files with 283 additions and 14 deletions
+14 -7
View File
@@ -60,13 +60,17 @@ const (
AttentionNoneEntity = "attention_none_entity"
AttentionListEntity = "attention_list_entity"
AttentionFailEntity = "attention_fail_entity"
ChangesNone = "changes_none"
ChangesList = "changes_list"
ChangesFail = "changes_fail"
HomeUnreachable = "home_unreachable"
HomeEmpty = "home_empty"
HomeOn = "home_on"
HomeDark = "home_dark"
// AttentionDegraded and AttentionNoSources — the two ways an empty
// attention list is not an all-clear (ECOSYSTEM-SPEC §2.6, Vikunja #540).
AttentionDegraded = "attention_degraded"
AttentionNoSources = "attention_no_sources"
ChangesNone = "changes_none"
ChangesList = "changes_list"
ChangesFail = "changes_fail"
HomeUnreachable = "home_unreachable"
HomeEmpty = "home_empty"
HomeOn = "home_on"
HomeDark = "home_dark"
)
var actKeys = []string{
@@ -76,6 +80,7 @@ var actKeys = []string{
EcoDenied, EcoDown, EcoAmbiguous, EcoUnknownEntity, EcoNoNexus, EcoAboutWhat, EcoRecall,
AttentionNone, AttentionList, AttentionFail,
AttentionNoneEntity, AttentionListEntity, AttentionFailEntity,
AttentionDegraded, AttentionNoSources,
ChangesNone, ChangesList, ChangesFail,
HomeUnreachable, HomeEmpty, HomeOn, HomeDark,
}
@@ -113,6 +118,8 @@ var actFloor = map[string]string{
AttentionNoneEntity: "по «{name}» ничего нет.",
AttentionListEntity: "по «{name}»: {items}",
AttentionFailEntity: "не могу сейчас узнать, что требует внимания по «{name}».",
AttentionDegraded: "за всё не отвечу — источники молчат: {items}.",
AttentionNoSources: "мне пока нечего смотреть — у Praxis нет источников.",
ChangesNone: "изменений нет.",
ChangesList: "изменения: {items}",
ChangesFail: "не могу сейчас узнать об изменениях.",
+8
View File
@@ -114,6 +114,14 @@
"fixed": true,
"variants": ["не могу сейчас узнать, что требует внимания по «{name}»."]
},
"attention_degraded": {
"fixed": true,
"variants": ["за всё не отвечу — источники молчат: {items}."]
},
"attention_no_sources": {
"fixed": true,
"variants": ["мне пока нечего смотреть — у Praxis нет источников."]
},
"changes_none": {
"fixed": true,
"variants": ["изменений нет."]