Territory Grounder is an open-source, self-hosted SRE platform: an LLM agent ingests alerts, chat messages, and tickets, triages incidents across Kubernetes, hypervisors, network, and storage, and (from Phase 2 on) executes remediations inside a mechanical governance envelope. It is the ground-up rewrite of Agentic ChatOps as a distributable product: Go and Temporal instead of Python, n8n, and cron. Same control logic, none of the code.

GitHub: territory-grounder/grounder · Product site: territorygrounder.com

Overview

AspectDetails
FunctionAlert/chat/ticket ingest, LLM triage, governed remediation (predict, act, verify)
Control planeGo 1.25, Temporal workflows, PostgreSQL + pgvector
Model accessBundled LiteLLM gateway: one OpenAI-compatible endpoint, multi-provider fallback ladder
Integrations~31 connector modules across 7 adapter surfaces (ingest, tracker, notifier, CMDB, actuation, model provider, observability)
DeploymentSingle docker-compose stack; no SaaS dependency, no phone-home
StatusPhase 1 live, read-only; mutation code merged, globally disabled
LicenseApache-2.0
Repositorygithub.com/territory-grounder/grounder

Control Loop

No mutating action runs without a consequence prediction committed first, keyed to action_id = SHA-256(canonicalJSON(Action)). After execution, a pure Go function compares observed state against the committed prediction and writes the verdict: match, partial, or deviation. The model that proposed the action has no write path to the verdict columns. A deviation disables auto-resolve for that action class.

Predictions are additionally scored against a degree-preserving shuffled-graph negative control. The real prediction must be at least twice as precise as the shuffle (control_ratio <= 0.5), otherwise the gate is treated as uninformative.

alert / chat / ticket ──▶ adapter ──▶ Temporal workflow
                          predict ──▶ commit prediction  (the gate)
                                      act  (bounded to its territory)
                    independent verify ──▶ verdict ──▶ hash-chained ledger
                          band:  AUTO · AUTO_NOTICE · POLL_PAUSE

The human is a circuit-breaker, not a per-action approver. Three autonomy bands set the interrupt level per session: AUTO (execute, log), AUTO_NOTICE (execute, notify), POLL_PAUSE (wait for a vote; never proceeds on timeout, pinned by a DB CHECK).

Enforcement by Construction

Safety properties live in the type system, the schema, and boot checks, not in review discipline:

Failure classEnforcement
Approve action X, execute action Yaction_id is asserted at classification, prediction, approval, execution, and verification. Any change to the action mints a new id and voids prior approvals
Approval poll without a predictionBuildApprovalPoll accepts only a GatedProposal, a type constructible only by the prediction-gate activity. The bypass does not compile
Error path defaults permissiveZero values are the restrictive option: unset band is POLL_PAUSE, unset reversibility is Irreversible
Shell injectionActuation is fixed argv vectors via exec.Command / x/crypto/ssh with pinned host keys. sh -c is not expressible; CI greps for it
SQL injectionpgx/sqlc generated queries only; string-built SQL fails CI
Unauthenticated routeHandlers come from a factory that requires the authenticated principal; a route declared auth=none fails to register at boot
Silently unwired controlA startup self-test fails boot if the actuation interceptor chain is not in place
Ledger tamperingAppend-only SHA-256 hash chain with no UPDATE/DELETE grants; a verifier walks the chain and alerts on break or staleness

A non-configurable never-auto floor covers mkfs, dropdb, zpool destroy, tofu destroy, kubectl delete/drain, credential revocation, and reboot/halt. No flag or org policy lifts it. An unrecognized mutation classifies as never-auto.

Operator Console

Grounding scorecard: verifier match rate, falsifiability signal, blast-radius precision and recall

15 live-wired surfaces: sessions, approvals, ledger, estate graph, governance controls, and the Grounding scorecard (verifier match rate, blast-radius precision/recall, falsifiability signal against the shuffled control). The estate causal graph is discovered from NetBox, Proxmox, and LibreNMS with per-source confidence tiers (1.00 for declared tunnels down to a 0.75 cap on learned co-occurrence edges). Screenshots show fixture data.

Build Process

Most of the Go is written by coding agents under a spec-driven workflow: EARS-format requirements, godog acceptance oracles in CI, and a content-hash lockstep that binds each safety-critical file to its owning spec. Current gate: 1,926 spec checks across 74 lockstep-bound files, -race clean. The -race sweep fixed 7 latent concurrency bugs, one of them a ledger writer racing itself and corrupting its own hash chain.

Status

PhaseScopeStatus
0 · Secure foundationMandatory-auth router, argv-only actuation, DML-only runtime DB role, fail-closed mutation gateDone
1 · Typed spineIngest, risk classifier, agent loop, prediction gate, verdict engine, ledger, console, estate graphLive, read-only
2 · Governed autonomyActuation interceptor chain, human approval loop, mutation enableMerged, gated OFF
3 · Anti-driftReconciliation, drift correction, safe decommissionPlanned
4 · Adversarial assuranceBoundary-coverage gate, sealed-holdout evals, incident-replay benchmarkPlanned

Running read-only against my own estate: authentication, the console, the estate graph, the prediction/verdict/ledger spine, the scorecard. Not implemented: the vote-consuming half of the approval loop, the incident-replay benchmark, and mutation itself, which stays globally disabled (mutation_enabled=false, asserted at boot preflight) until the Phase 2 self-tests pass.


Successor to Agentic ChatOps . Product site: territorygrounder.com . Design rationale: The Map Is Not the Territory .