feat(tui-go): health-checks pane

Surface the health subsystem (llama/event-store/disk probes) in the TUI,
mirroring the session-stats pane: ClientMessage.GetHealthChecks ->
ServerMessage.HealthChecks (health.checks, reuses HealthReport) ->
StreamQueries.healthChecks via HealthInspectionService; Go OverlayHealth on
key H + palette 'health checks', pull-based fetch, per-subject status with
degraded loud. Empty/disabled -> visible fallback (no blank/lie). Go+Kotlin
golden tests pin the wire contract field-for-field. Observability spec §4/§3.
This commit is contained in:
2026-06-14 18:57:51 +04:00
parent 09f05549a0
commit fd67a6c68d
13 changed files with 285 additions and 3 deletions
+29
View File
@@ -55,6 +55,7 @@ const (
TypeConfigSnapshot = "config.snapshot"
TypeSessionStats = "session.stats"
TypeIdeaList = "idea.list"
TypeHealthChecks = "health.checks"
)
// ServerMessage is a flat decode of every server->client variant. Field names
@@ -139,6 +140,9 @@ type ServerMessage struct {
// session.stats — derived metrics for a session (reply to GetSessionStats)
Stats *StatsDto `json:"stats"`
// health.checks — system health report (reply to GetHealthChecks)
Health *HealthDto `json:"health"`
// clarification.required — open questions a stage raised for the operator
Questions []ClarificationQuestionDto `json:"questions"`
@@ -242,6 +246,26 @@ type FailureMetricsDto struct {
WorkflowFailures int64 `json:"workflowFailures"`
}
// HealthSubjectDto is one monitored subject's health status. Mirrors Kotlin HealthSubjectReport.
// status is "HEALTHY" or "DEGRADED"; since is an ISO-8601 string for the last edge event.
type HealthSubjectDto struct {
Subject string `json:"subject"`
Status string `json:"status"`
Metric string `json:"metric"`
ObservedValue int64 `json:"observedValue"`
Detail string `json:"detail"`
Since string `json:"since"`
}
// HealthDto is the system health snapshot. Mirrors Kotlin HealthReport.
// overall is "HEALTHY" or "DEGRADED". subjects is empty when health monitoring is disabled
// or no probes have fired yet — the TUI renders a visible fallback in that case.
type HealthDto struct {
Overall string `json:"overall"`
Subjects []HealthSubjectDto `json:"subjects"`
CheckedAt string `json:"checkedAt"`
}
type ConfigFieldDto struct {
Key string `json:"key"`
Type string `json:"type"`
@@ -465,3 +489,8 @@ func CreateGrant(sessionID, scope string, permittedTiers []string, reason, toolN
func Hello(workingDir string) []byte {
return encode("Hello", map[string]any{"workingDir": workingDir})
}
// GetHealthChecks requests the system health-check report (replied to with health.checks).
func GetHealthChecks() []byte {
return encode("GetHealthChecks", map[string]any{})
}