Time stone
Sentinel
Watches, never speaks, never reasons.
The discipline
The Time stone keeps the cheapest seat in the gauntlet. A Sentinel is a deterministic observer: it looks at the world, compares what it sees against a rule, and either fires or stays quiet. That is the whole job.
Sentinels escalate facts, not opinions. A fire says "this condition held at this moment," never "this seems important." Interpretation is a paid act, and paid acts belong to the Council, not the watcher.
A Sentinel that needs an LLM to decide something is interesting is a Worker wearing the wrong label. The watch loop makes exactly zero LLM calls, and the fire decision lands in 100 milliseconds or less.
Enabling a Sentinel only permits observation and recording. Nothing downstream wakes up, nothing spends, nothing acts. Watch is cheap; the expensive stones each demand their own, separate permission.
Why so strict
An observer that can think will eventually think about things it was never asked to watch. The gauntlet holds because every stone stays in its lane, and the Sentinel's lane is the narrowest of all: see, compare, record, shut up.
The eight stock Sentinels
Eight watchers ship in the box. Each is configured in the Sentinels config file, located via SENTINELS_CONFIG_PATH (default /etc/gateway/sentinels.yaml).
file-inbox-watch
stock sentinelWatches a directory.
Fires on new or changed files in a watched directory. Uses a 1 second PollWatcher by default on macOS.
silence-watch
stock sentinelWatches the quiet.
Fires only when BOTH conditions hold: no audit event for threshold_hours AND the backlog directory is non-empty. Silence alone is not a fact; silence with pending work is.
queue-depth-watch
stock sentinelWatches a number over HTTP.
An HTTP plus jsonpath threshold poller: it fetches an endpoint, extracts a value with a jsonpath such as $.active_total, and fires when the value crosses the configured threshold.
watch-health-watch
stock sentinel, metaWatches the watchers.
The meta Sentinel: fires if any other sentinel is quarantined, hard-killed, or its hash chain is broken. It excludes itself, because a watcher reporting on its own health is how horror stories start.
ledger-delta-watch
experimentalWatches the money.
Experimental. Fires on a spend spike of threshold_pct over baseline, with min_baseline_usd guarding against tiny denominators turning pennies into alarms.
anomaly-watch
experimentalWatches failure rates.
Experimental. Tracks the escalation failure rate against an EWMA baseline and fires when the rate drifts too far above it. Pure statistics, still no LLM.
completion-verify-watch
stock sentinelWatches the receipts.
Fires on acked outbox rows whose worker_provenance is missing or is not VerifiedExact. A completed action without verified provenance is a fact worth escalating.
precedent-integrity-watch
stock sentinelWatches the record.
Treats the Council sessions/index.jsonl as an append-only byte stream and verifies count, bytes, and the SHA-256 prefix. If the precedent log was rewritten, this Sentinel says so.
The watch API
Everything a Sentinel sees is readable over HTTP. Reads are public; mutations are admin; arming is a different principal entirely.
Read endpoints
clamp01(0.7 * fires_1h / 5 + 0.3 * fires_24h / 24). Bands: cold below 0.15, warm below 0.6, hot at 0.6 and up.limit defaults to 50 and is capped at 500; before_id is the pagination cursor.ok:false: a broken chain is a finding, not a fault.action_production_armed.kid is sidecar-v1-{first8 hex of sha256(pubkey)}. Public means public: anyone may verify, only the signer can sign.Admin mutations
Who may call what
ui-snapshot require a bearer token: WATCH_ADMIN_TOKEN or BOOTSTRAP_TOKEN. An empty token means every admin route answers 401.WATCH_CANARY_TENANT pins the canary tenant; other tenants get 403 with single_tenant_violation.problem+json.The three gates
Three separate switches stand between a config file and real-world action. Each gate is explicit, and opening one never opens the next.
WATCH_DISPATCHER_ENABLED lets escalations flow into Council work. This gate may spend money.Gate one is not gate two is not gate three
Loading or enabling a Sentinel is not enabling the dispatcher, and enabling the dispatcher is not arming the producer. If you only flipped the first switch, the gauntlet is watching, recording, and spending nothing.
Quarantine and probation
A Sentinel that cannot fire cleanly gets benched, then eased back under supervision. The numbers are fixed, not vibes.
fails_to_trigger = 2 quarantines a Sentinel.[PROBATION] prefix.Polling and deep Sentinels tick on their cooldown schedule. Fast Sentinels do not tick at all; they are kicked externally when their event source stirs.
Fine print, read before arming anything
[PROBATION]fires are NOT filtered by the CDC sweep and can reach paid Council work unless the dispatcher is disabled. Probation is log-only in spirit, not in billing.watch_firesis hash-chained for tamper evidence but is NOT individually signed, and it is never pruned: the log is unbounded by design, so disk is your problem, not the Sentinel's.force-wakewith no tenant in the body defaults to the sovereign tenant. Diagnostic fires land where you aimed them only if you aimed them.- Polling and deep Sentinels tick on cooldown; Fast Sentinels are kicked externally. A Fast Sentinel that never fires may simply never have been kicked.