// Package diag holds the strict diagnosis schema of experiment design 6.3 and the enum sources. package diag import ( "encoding/json" "fmt" "strings" ) // Diagnosis is the submit_diagnosis payload (design 6.3). Every field is required under strict mode. type Diagnosis struct { RootCauseLabel string `json:"root_cause_label"` Confidence float64 `json:"confidence"` Evidence []string `json:"evidence"` ProposedAction string `json:"proposed_action"` Target string `json:"target"` Rationale string `json:"rationale"` } // DefaultLabels mirrors the ground_truth_label values of the 13 scenario files (design 7); the agent refreshes the // list from the harness GET /scenarios at start-up and falls back to this copy. var DefaultLabels = []string{ "api_pod_failure", "api_pod_killed", "db_primary_down", "gitops_drift", "legacy_instance_lost", "legacy_process_killed", "memory_pressure_api", "network_latency_api_to_db", "network_latency_legacy", "replication_paused", "schema_mismatch", "transient_loss_legacy", "transient_partition", } // DefaultActions mirrors the layer-2 action_ids of design 2.3; refreshed from the harness GET /actions/catalog (layer contains "2"). var DefaultActions = []string{ "k8s.rollout_restart", "k8s.rollout_undo", "k8s.scale", "k8s.node_drain", "k8s.node_uncordon", "gce.instance_reset", "mig.recreate_instance", "mig.resize", "db.replay_resume", "net.route_change", } // Enums are the closed sets the schema is built from. type Enums struct { Labels []string // + "unknown" Actions []string // + "none", "escalate" } func (e Enums) LabelEnum() []string { return append(append([]string{}, e.Labels...), "unknown") } func (e Enums) ActionEnum() []string { return append(append([]string{}, e.Actions...), "none", "escalate") } // Schema is the JSON schema of the submit_diagnosis tool parameters (strict: additionalProperties false, all required). func (e Enums) Schema() map[string]any { return map[string]any{ "type": "object", "properties": map[string]any{ "root_cause_label": map[string]any{"type": "string", "enum": e.LabelEnum(), "description": "Root cause label; unknown when the evidence does not support any label."}, "confidence": map[string]any{"type": "number", "description": "0.0 to 1.0. Below 0.5 the harness routes the case to layer 3 (human)."}, "evidence": map[string]any{"type": "array", "items": map[string]any{"type": "string"}, "description": "Quotations of tool results that support the label. At least one."}, "proposed_action": map[string]any{"type": "string", "enum": e.ActionEnum(), "description": "Catalogue action_id (layer 2), none when no action is needed, escalate when a human must decide."}, "target": map[string]any{"type": "string", "description": "Action target: deployment name, instance name, legacy:N, or empty."}, "rationale": map[string]any{"type": "string", "description": "Why this label and action; at most 200 characters."}, }, "required": []string{"root_cause_label", "confidence", "evidence", "proposed_action", "target", "rationale"}, "additionalProperties": false, } } // Validate enforces the schema constraints on the model output (strict mode guarantees shape; this checks the values). func (e Enums) Validate(d Diagnosis) error { if !contains(e.LabelEnum(), d.RootCauseLabel) { return fmt.Errorf("root_cause_label %q not in enum", d.RootCauseLabel) } if d.Confidence < 0 || d.Confidence > 1 { return fmt.Errorf("confidence %v out of [0,1]", d.Confidence) } if len(d.Evidence) == 0 { return fmt.Errorf("evidence must have at least one item") } if !contains(e.ActionEnum(), d.ProposedAction) { return fmt.Errorf("proposed_action %q not in enum", d.ProposedAction) } if n := len([]rune(d.Rationale)); n > 200 { return fmt.Errorf("rationale is %d characters, limit 200", n) } return nil } func Parse(args string, e Enums) (Diagnosis, error) { var d Diagnosis dec := json.NewDecoder(strings.NewReader(args)) dec.DisallowUnknownFields() if err := dec.Decode(&d); err != nil { return d, fmt.Errorf("submit_diagnosis arguments: %w", err) } return d, e.Validate(d) } func contains(xs []string, s string) bool { for _, x := range xs { if x == s { return true } } return false }