services:
  boocode:
    build: .
    container_name: boocode
    restart: unless-stopped
    ports:
      - "100.114.205.53:9500:3000"
    env_file: .env
    environment:
      CODECONTEXT_URL: http://codecontext:8080
      CONTAINER_GUIDANCE_FILE: /app/BOOCHAT.md
      DATABASE_URL: postgres://boocode:${POSTGRES_PASSWORD}@boocode_db:5432/boochat
      BOOCODER_URL: http://100.114.205.53:9502
      LLAMA_SIDECAR_URL: http://100.101.41.16:8402
    volumes:
      - /opt:/opt
      - /opt/projects:/opt/projects:rw
      - ./secrets/boocode_gitea:/root/.ssh/id_ed25519:ro
      - ./data:/data
      # v1.13.12: override-mount /opt/skills:/data/skills removed. Skill
      # library now lives in the boocode repo at data/skills/, audited
      # per-batch. The host-level /opt/skills is preserved for other tools
      # (Claude Code, etc.) but boocode reads only from its repo-local
      # data/skills/ tree.
      # v1.12: bind-mount BOOCHAT.md so host-side edits land in the container
      # without a rebuild. system-prompt.ts mtime-watch picks up changes on the
      # next chat turn. Read-only — the chat surface must never write here.
      - /opt/boocode/BOOCHAT.md:/app/BOOCHAT.md:ro
    depends_on:
      - boocode_db
    networks:
      - boocode_net

  booterm:
    build:
      context: .
      dockerfile: apps/booterm/Dockerfile
    container_name: booterm
    restart: unless-stopped
    ports:
      - "100.114.205.53:9501:3000"
    env_file: .env
    environment:
      NODE_ENV: production
      PORT: 3000
      DATABASE_URL: postgres://boocode:${POSTGRES_PASSWORD}@boocode_db:5432/boochat
    volumes:
      - /opt:/opt:rw
      - /home/samkintop:/home/samkintop:rw
    depends_on:
      - boocode_db
    networks:
      - boocode_net

  # v2.1.1: boocoder moved to systemd service on host (boocoder.service).
  # Kept commented for rollback reference.
  # boocoder:
  #   build:
  #     context: .
  #     dockerfile: apps/coder/Dockerfile
  #   container_name: boocoder
  #   restart: unless-stopped
  #   ports:
  #     - "100.114.205.53:9502:3000"
  #   env_file: .env
  #   environment:
  #     CONTAINER_GUIDANCE_FILE: /app/BOOCODER.md
  #     DATABASE_URL: postgres://boocode:${POSTGRES_PASSWORD}@boocode_db:5432/boochat
  #   volumes:
  #     - /opt:/opt:rw
  #     - /opt/projects:/opt/projects:rw
  #     - ./data:/data
  #     - /opt/boocode/BOOCODER.md:/app/BOOCODER.md:ro
  #   depends_on:
  #     - boocode_db
  #   networks:
  #     - boocode_net

  boocode_db:
    image: postgres:16-alpine
    container_name: boocode_db
    restart: unless-stopped
    environment:
      POSTGRES_USER: boocode
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: boochat
    ports:
      - "127.0.0.1:5500:5432"
    volumes:
      - boocode_pgdata:/var/lib/postgresql/data
    networks:
      - boocode_net

  # v1.12 Track B: codecontext sidecar. Stdio MCP server wrapped by a small
  # HTTP shim (see ./codecontext/). No host port — reached from boocode at
  # http://codecontext:8080 over the boocode_net bridge.
  #
  # Mounts /opt:/opt:ro (not just /opt/projects:ro): BooCode projects live
  # at /opt/<slug> on the host, not exclusively under /opt/projects. The
  # mount must cover anywhere a project.path could resolve to. Read-only
  # because codecontext only analyzes — never writes. The model can't
  # arbitrarily set target_dir to a sensitive subtree because the B.2
  # wrappers validate target_dir against project.path before calling the
  # shim, and the shim isn't reachable from outside boocode_net.
  codecontext:
    build:
      context: ./codecontext
    container_name: boocode_codecontext
    ports:
      - "127.0.0.1:8080:8080"
    restart: unless-stopped
    networks:
      - boocode_net
    volumes:
      - /opt:/opt:ro
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s

volumes:
  boocode_pgdata:

networks:
  boocode_net:
    driver: bridge
