feat(scheduler): plugin architecture + Doctor health check plugin

- Create ISchedulerJobPlugin abstraction with JobKind routing
- Add SchedulerPluginRegistry for plugin discovery and resolution
- Wrap existing scan logic as ScanJobPlugin (zero behavioral change)
- Extend Schedule model with JobKind (default "scan") and PluginConfig (jsonb)
- Add SQL migrations 007 (job_kind/plugin_config) and 008 (doctor_trends table)
- Implement DoctorJobPlugin replacing standalone doctor-scheduler service
- Add PostgresDoctorTrendRepository for persistent trend storage
- Register Doctor trend endpoints at /api/v1/scheduler/doctor/trends/*
- Seed 3 default Doctor schedules (daily full, hourly quick, weekly compliance)
- Comment out doctor-scheduler container in compose and services-matrix
- Update Doctor architecture docs and AGENTS.md with scheduling migration info

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-04-08 16:24:46 +03:00
parent 53f294400f
commit 908619e739
32 changed files with 1619 additions and 55 deletions

View File

@@ -1606,29 +1606,32 @@ services:
<<: *healthcheck-tcp
labels: *release-labels
doctor-scheduler:
<<: *resources-light
image: stellaops/doctor-scheduler:dev
container_name: stellaops-doctor-scheduler
restart: unless-stopped
depends_on: *depends-infra
environment:
ASPNETCORE_URLS: "http://+:80"
<<: [*kestrel-cert, *router-microservice-defaults, *gc-light]
ConnectionStrings__Default: *postgres-connection
ConnectionStrings__Redis: "cache.stella-ops.local:6379"
Router__Enabled: "${DOCTOR_SCHEDULER_ROUTER_ENABLED:-true}"
Router__Messaging__ConsumerGroup: "doctor-scheduler"
volumes:
- *cert-volume
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/$(hostname)/80'"]
<<: *healthcheck-tcp
networks:
stellaops:
aliases:
- doctor-scheduler.stella-ops.local
labels: *release-labels
# DEPRECATED: doctor-scheduler is replaced by the DoctorJobPlugin in the Scheduler service.
# Scheduling and trend storage are now handled by the Scheduler with jobKind="doctor".
# See: SPRINT_20260408_003_JobEngine_scheduler_plugin_architecture.md
# doctor-scheduler:
# <<: *resources-light
# image: stellaops/doctor-scheduler:dev
# container_name: stellaops-doctor-scheduler
# restart: unless-stopped
# depends_on: *depends-infra
# environment:
# ASPNETCORE_URLS: "http://+:80"
# <<: [*kestrel-cert, *router-microservice-defaults, *gc-light]
# ConnectionStrings__Default: *postgres-connection
# ConnectionStrings__Redis: "cache.stella-ops.local:6379"
# Router__Enabled: "${DOCTOR_SCHEDULER_ROUTER_ENABLED:-true}"
# Router__Messaging__ConsumerGroup: "doctor-scheduler"
# volumes:
# - *cert-volume
# healthcheck:
# test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/$(hostname)/80'"]
# <<: *healthcheck-tcp
# networks:
# stellaops:
# aliases:
# - doctor-scheduler.stella-ops.local
# labels: *release-labels
# --- Slot 27: OpsMemory (src/AdvisoryAI/StellaOps.OpsMemory.WebService) ---
opsmemory-web: