Add the `watchdog/` package (thin Python-3.12 stdlib-only daemon) and the `orchestrator-watchdog` compose service — the brain half of the domain-0 observability pair. F1a (ORCH-099) exposes GET /metrics raw signal; F1b reads it, augments with host / container / dependency probes, runs each signal through a generalised pure decision function (decide(signal_active, prev, now, cooldown), a strict superset of disk_watchdog.decide_action) with per-signal in-memory dedup/throttle/recovery, and alerts over its OWN independent Telegram channel. Key properties (ADR-001): - Observer separated from observed: separate container; /metrics not answering is itself the master `orch_down` alarm (debounced K ticks — no flap on a hiccup). - Strictly read-only: docker.sock GET-only + mounted :ro (double guard), host paths :ro, no DB/disk writes, no process control — self-hosting-safe. - never-raise on three levels (per-source/per-tick/per-send) + WATCHDOG_ENABLED kill-switch (disabled -> inert idle-loop, not exit). - Disk anti-duplicate (D6): disk_watchdog (ORCH-063) stays sole owner of the 85% alert; sidecar carries orch_down + an opt-in 97% ceiling (default off). - NO import from src/** (C-1); src/**, STAGE_TRANSITIONS, QG_CHECKS, check_*, DB schema — untouched. env_file optional so a missing .env.watchdog never breaks `docker compose up` for the prod orchestrator. Tests: tests/watchdog/ (TC-01…TC-13) + full tests/ regression green (TC-14). Docs: CHANGELOG, .env.example canon (WATCHDOG_*); architecture README + adr-0033 authored at the architecture stage. Refs: ORCH-100 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
29 lines
1.1 KiB
Docker
29 lines
1.1 KiB
Docker
# ORCH-100 (FND/F1b): sidecar-watchdog — thin stdlib-only monitoring brain.
|
|
#
|
|
# A separate, deliberately tiny image (NO pip dependencies — Python 3.12 stdlib
|
|
# only, ADR-001 D1): urllib for HTTP/Telegram, a raw HTTP-over-unix-socket client
|
|
# for the read-only docker.sock, shutil/proc for host metrics. Kept thin on a
|
|
# tight host (C-3); mem_limit is enforced in docker-compose.yml (D2).
|
|
#
|
|
# The build context is the REPO ROOT (see docker-compose.yml `build:
|
|
# context: . / dockerfile: watchdog/Dockerfile`) so we can COPY the watchdog/
|
|
# package. src/** is intentionally NOT copied — the sidecar must not import the
|
|
# orchestrator (C-1).
|
|
FROM python:3.12-slim
|
|
|
|
WORKDIR /app
|
|
|
|
# Run as a non-root user; the sidecar only READS (docker.sock :ro, host paths :ro).
|
|
RUN useradd -u 1000 -m -d /home/watchdog -s /bin/bash watchdog
|
|
|
|
# Copy ONLY the sidecar package (no src/, no requirements — stdlib only).
|
|
COPY watchdog/ ./watchdog/
|
|
|
|
ENV PYTHONPATH=/app
|
|
ENV PYTHONUNBUFFERED=1
|
|
|
|
USER watchdog
|
|
|
|
# `python -m watchdog` runs watchdog/__main__.py (the tick loop).
|
|
ENTRYPOINT ["python", "-m", "watchdog"]
|