Skip to content

fix(deep): guard against the Consul 'not deployed in k8s' category error - #259

Closed
WZ wants to merge 3 commits into
mainfrom
fix/consul-category-error-guard
Closed

fix(deep): guard against the Consul 'not deployed in k8s' category error#259
WZ wants to merge 3 commits into
mainfrom
fix/consul-category-error-guard

Conversation

@WZ

@WZ WZ commented Jun 10, 2026

Copy link
Copy Markdown
Owner

What the trace showed

A bd-management run had the keystone confirm a true-but-wrong cause: "bd-management is not deployed in the cluster (no k8s pod exists)". It's literally true (a Consul service has no k8s pod) but it's not the root cause — and the same run had already gathered consul_health evidence proving the service is bare-metal Consul. The #256 skill tells the model not to conclude this, but it does ~half the time. A prompt can't guarantee it.

Deterministic guard

In the conclude path: if the run gathered any consul_health_service_status evidence and the confirmed cause asserts a missing k8s deployment (not deployed, no k8s pod, deployment missing/absent), reject it and make the agent confirm via the Consul health signal instead.

Safe for genuine k8s incidents: agw-admin-ui's deleted-namespace cause gathers no consul_health evidence, so the guard never fires for it — pinned by a control test.

Verification

  • tsc clean · 2 new tests (guard fires for Consul / allows genuine k8s) · full suite 2702/2702
  • Live re-test pending

Context

The consistency fix on top of the form→predict→gather→verify chain (#256/#257/#258). Makes the category error structurally impossible for Consul services. Feature still gated off.

WZ added 3 commits June 9, 2026 23:43
Trace of a bd-management run showed the keystone CONFIRMING a true-but-wrong cause:
'bd-management is not deployed in the cluster (no k8s pod exists)'. It's true (a
Consul service has no k8s pod) but it is NOT the root cause — and the run had
already gathered consul_health evidence proving the service is bare-metal Consul.
The skill tells the model not to do this, but it does ~half the time; a prompt
can't guarantee it.

Deterministic guard in the conclude path: if the run gathered any
consul_health_service_status evidence AND the confirmed cause asserts a missing
k8s deployment ('not deployed', 'no k8s pod', 'deployment missing/absent'), reject
it and make the agent confirm via the Consul health signal instead. Genuine k8s
incidents (e.g. agw-admin-ui's deleted namespace) gather no consul_health
evidence, so the guard never fires for them — proven by a control test.

tsc clean; 2 new tests (guard fires for Consul / allows genuine k8s); suite green.
Validation surfaced a second wrong-layer failure: investigating the idle
minimax-m25-metrics-proxy, the orchestrator ruled out every real hypothesis, then
chased its OWN query errors — 'datasource with UID loki not found' (MI350 has no
Loki datasource configured) appearing as 404s in logs — and confirmed 'Grafana
datasource misconfigured' as the root cause. That's a query-layer artifact, not
why the service is unhealthy.

Guard (same pattern as the Consul category-error guard, same conclude path): reject
a confirmed cause that blames the observability tooling (mentions 'datasource' or
'grafana') UNLESS the incident service is itself an observability component
(grafana/loki/prometheus/...). Forces the agent back to the service's own signals;
an idle service with no real cause then exhausts/pauses honestly instead of
inventing a tooling cause.

tsc clean; 2 new tests (guard fires for a service / allows a grafana incident); suite green.
…-pause

Investigating minimax-m25-vllm-bench-4gpu (a k8s Deployment scaled to 0 replicas,
kube_deployment_spec_replicas=0), the orchestrator spent all ~30 moves chasing
Consul hypotheses ('is it a bare-metal Consul service / not registered in Consul /
health check unknown...'), never proposed the obvious 'deployment scaled to 0',
and operator-paused. Root cause: #256 injects the Consul runbook into EVERY
orchestrator run (always-on), which over-steers k8s services into Consul
tunnel-vision — a regression for the k8s case introduced by the Consul fixes.

Two parts:
- Skill: lead the 'When investigating' section with DETERMINE SERVICE TYPE FIRST —
  query kube_deployment_status_replicas; if it returns data the service IS a k8s
  Deployment (0 = scaled to 0 = a valid root cause, conclude it), and ONLY treat as
  Consul when there's no kube_deployment metric. Stops the Consul tunnel-vision.
- Guard: the Consul category-error guard no longer fires when the run also saw
  kube_deployment/kube_pod evidence — a real k8s Deployment's k8s-absence cause is
  legitimate (only consul_health-AND-no-kube services are the bare-metal ones).

tsc clean; 1 new test (k8s service not blocked); suite green.
@WZ

WZ commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #261, which combines #258 + #259 + #260 into a single inc-7 accuracy PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant