phase: 02-operations-maintenance
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: [api.py]
autonomous: true
requirements: [OPS-02]

must_haves:
truths:
- "GET /health returns JSON with db, ollama, and claude status fields"
- "When DB is down, health reports db as unhealthy but does not crash"
- "When Ollama is down, health reports ollama as unhealthy but does not crash"
- "When Claude API key is invalid, health reports claude as unhealthy but does not crash"
artifacts:
- path: "api.py"
provides: "Extended /health endpoint with dependency checks"
contains: "ollama"
key_links:
- from: "api.py /health"
to: "psycopg2.connect"
via: "SELECT 1 probe"
pattern: "SELECT 1"
- from: "api.py /health"
to: "OLLAMA_URL"
via: "httpx GET to Ollama API"
pattern: "httpx.*ollama"
- from: "api.py /health"
to: "anthropic.Anthropic"
via: "models.list or lightweight API call"
pattern: "anthropic"



Extend the existing GET /health endpoint to probe all three dependencies (PostgreSQL, Ollama, Claude API) and return per-component status.

Purpose: OPS-02 requires the health endpoint to show status of all dependencies so the crew can diagnose which component is down.
Output: Updated api.py with rich health check returning {"status": "ok|degraded", "db": "ok|error", "ollama": "ok|error", "claude": "ok|error"}.


@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md


@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md

@app.get("/health")
def health():
    return {"status": "ok"}
DB_URL        = os.environ["DATABASE_URL"]
OLLAMA_URL    = os.environ.get("OLLAMA_URL", "http://localhost:11434")
ANTHROPIC_KEY = os.environ["ANTHROPIC_API_KEY"]
conn = psycopg2.connect(DB_URL)
resp = httpx.post(f"{OLLAMA_URL}/api/embeddings", json={...}, timeout=60)



Task 1: Extend /health with dependency probes
api.py
api.py, query.py, ingest.py

Replace the existing /health endpoint in api.py (lines 80-82) with a comprehensive health check function.

Add imports at the top of api.py (alongside existing imports):
- import httpx
- import psycopg2
- import anthropic

Add module-level env var reads (same pattern as query.py):

DB_URL        = os.environ["DATABASE_URL"]
OLLAMA_URL    = os.environ.get("OLLAMA_URL", "http://localhost:11434")
ANTHROPIC_KEY = os.environ.get("ANTHROPIC_API_KEY", "")

Replace the /health handler with:

  1. DB check: Try psycopg2.connect(DB_URL) then cur.execute("SELECT 1"), close connection. On success: "ok". On any exception: "error" + str(exception) in detail field.

  2. Ollama check: Try httpx.get(f"{OLLAMA_URL}/api/tags", timeout=5). On 200: "ok". On any exception or non-200: "error" + detail.

  3. Claude check: Try anthropic.Anthropic(api_key=ANTHROPIC_KEY).models.list(limit=1). On success: "ok". On any exception: "error" + detail. If ANTHROPIC_KEY is empty string, skip and return "not_configured".

Return JSON:

{
  "status": "ok" or "degraded",
  "components": {
    "db": {"status": "ok|error", "detail": "...only if error..."},
    "ollama": {"status": "ok|error", "detail": "...only if error..."},
    "claude": {"status": "ok|error|not_configured", "detail": "...only if error..."}
  }
}

Top-level status is "ok" only if ALL components are "ok" or "not_configured". Otherwise "degraded".

Each probe MUST be wrapped in its own try/except so one failure does not prevent checking the others. Use short timeouts (5s for Ollama, 5s for DB connect) to avoid slow health checks.


cd /Users/bmt/Documents/RKL-OZM-Chat-Hook-v.0.0 && python -c "import ast; ast.parse(open('api.py').read()); print('syntax ok')" && grep -q 'SELECT 1' api.py && grep -q 'api/tags' api.py && grep -q 'anthropic' api.py && grep -q 'degraded' api.py && echo 'all checks passed'


- grep "SELECT 1" api.py returns a match (DB probe present)
- grep "api/tags" api.py returns a match (Ollama probe present)
- grep "anthropic" api.py returns a match (Claude probe present)
- grep "degraded" api.py returns a match (degraded status logic present)
- grep "components" api.py returns a match (structured response)
- python -c "import ast; ast.parse(open('api.py').read())" succeeds (valid Python)

GET /health returns JSON with db, ollama, and claude component status. Each probe is independent — one failure does not block the others. Top-level status is "ok" when all components healthy, "degraded" otherwise.


- python -c "import ast; ast.parse(open('api.py').read())" succeeds
- /health response contains components.db, components.ollama, components.claude fields
- Each component check is wrapped in its own try/except


GET /health returns structured JSON showing per-component status of DB, Ollama, and Claude API. No single component failure causes a 500 error.

After completion, create `.planning/phases/02-operations-maintenance/02-01-SUMMARY.md`