// File: specs/200-fullstacks/231-hermes-agent/plan.md
// Change Log:
// - 2026-05-29: Initial implementation plan for Hermes Agent (ADR-031 v2.0)

# Implementation Plan: Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge

**Branch**: `231-hermes-agent` | **Date**: 2026-05-29 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `specs/200-fullstacks/231-hermes-agent/spec.md`

---

## Summary

Hermes Agent เป็น standalone NestJS service รันบน ASUSTOR Docker ทำหน้าที่ 2 บทบาทหลัก:
1. **Autonomous Dev Orchestrator** — รับ coding task, delegate ไป Cloud AI sub-agents, รัน self-correction loop, push PR via hermes-bot
2. **Telegram DevOps Bridge** — webhook handler สำหรับ DevOps commands พร้อม allowlist + rate-limit + operations log

Hermes ไม่แตะ DMS production schema หรือ DMS production services ทุกกรณี (FR-017, ADR-031)

---

## Technical Context

**Language/Version**: TypeScript 5.x / Node.js 22 LTS
**Primary Dependencies**:
- NestJS 10 (framework)
- BullMQ 5 (queue: hermes-notification-queue + hermes-orchestration-queue)
- `@anthropic-ai/sdk` + `openai` npm packages (Cloud AI clients)
- `better-sqlite3` (hermes_operations_log SQLite)
- `ioredis` (rate limiting + BullMQ)
- `@qdrant/js-client-rest` (Dev Qdrant client)
- `node-telegram-bot-api` or `telegraf` (Telegram Bot SDK)
- `simple-git` (Git operations via hermes-bot)
- `uuid` v7 (UUIDv7 generation — ADR-019)

**Storage**:
- SQLite (`/volume1/docker/hermes/data/ops.db`) — HermesOperationsLog
- Redis (hermes-redis container) — BullMQ queues + rate limiting
- Dev Qdrant (hermes-qdrant container, port 6334) — codebase embeddings
- File volume (`/volume1/docker/hermes/SOUL.md`) — SOUL.md working journal

**Testing**: Jest (unit + integration); no E2E browser tests required

**Target Platform**: ASUSTOR NAS (Linux ARM/x86) — Docker container, non-Swarm
**Performance Goals**:
- Telegram read-only commands: ≤ 10s response (SC-003)
- Coding task PR creation: ≤ 30 min typical (SC-001)
- Self-correction loop: ≤ 3 iterations (SC-002)

**Constraints**:
- CPU ≤ 2.0 cores, RAM ≤ 4096MB (ASUSTOR resource limits)
- LAN/VPN-only exposure (except Telegram webhook via reverse proxy)
- ห้ามใช้ DMS production Redis, DMS Qdrant, DMS audit_logs
- Cloud AI: ห้ามส่ง production DB query results, document content, user data
- Port 8766 สำหรับ hermes proxy เท่านั้น (ห้ามใช้ 8765 ที่ PaddleOCR ใช้อยู่)

**Scale/Scope**: Single DevOps team tool (2-5 concurrent users); not production DMS service

---

## Constitution Check

_GATE: Must pass before Phase 0 research. Re-check after Phase 1 design._

| Rule | Status | Notes |
|------|--------|-------|
| ADR-019: UUIDv7, no parseInt | ✅ PASS | transactionId ใช้ UUIDv7; ไม่มี parseInt บน UUID |
| ADR-016: Auth/RBAC | ✅ PASS | API Key auth + Telegram allowlist; webhook secret verification |
| ADR-007: Error handling | ✅ PASS | BullMQ retry 3x exponential backoff; ADR-007 error classification |
| ADR-008: BullMQ | ✅ PASS | `hermes-notification-queue` + `hermes-orchestration-queue` |
| ADR-023/023A: AI boundary | ✅ PASS | Cloud AI exception (ADR-031 v2.0 Locked) สำหรับ dev orchestration; ไม่ใช่ DMS document path |
| ADR-009: No migration | ✅ PASS | ไม่มี DMS schema delta; Hermes-owned SQLite ไม่ใช่ DMS DB |
| No `any` TypeScript | ✅ PASS | strict mode; all types explicit |
| No `console.log` | ✅ PASS | NestJS Logger ทั้งหมด |
| Forbidden patterns | ✅ PASS | ไม่มี parseInt(UUID), ไม่ expose INT PK, ไม่มี inline notification |
| File headers | ✅ PASS | ทุก TypeScript file เริ่มด้วย `// File: ...` |
| Data Classification | ✅ PASS | Code/Config/ADR ส่ง Cloud AI ได้; Production data ห้ามส่งออก |
| Failure isolation | ✅ PASS | Hermes ไม่ใช่ DMS dependency; DMS ทำงานได้โดยไม่มี Hermes |

**No constitution violations. Proceed.**

---

## Project Structure

### Documentation (this feature)

```text
specs/200-fullstacks/231-hermes-agent/
├── spec.md              # Feature specification
├── plan.md              # This file
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output
├── quickstart.md        # Phase 1 output
├── contracts/
│   └── hermes-api.yaml  # OpenAPI contract
└── tasks.md             # Phase 2 output
```

### Source Code (new Hermes stack — NOT part of backend/ or frontend/)

```text
hermes/
├── src/
│   ├── orchestrator/
│   │   ├── orchestrator.module.ts
│   │   ├── orchestrator.service.ts          # Autonomous dev loop
│   │   ├── context-loader.service.ts        # Selective context loading
│   │   ├── sub-agent.service.ts             # Cloud AI delegation
│   │   ├── self-correction.service.ts       # Lint/tsc/test loop (max 3 iter)
│   │   └── soul.service.ts                  # SOUL.md journal management
│   ├── integrations/
│   │   ├── telegram/
│   │   │   ├── telegram.module.ts
│   │   │   ├── hermes-telegram-gateway.ts   # Inbound webhook handler
│   │   │   ├── hermes-telegram-dispatcher.ts # BullMQ outbound worker
│   │   │   ├── hermes-devops-command-router.ts # Command routing
│   │   │   └── telegram-rate-limiter.service.ts
│   │   ├── gitea/
│   │   │   ├── gitea.module.ts
│   │   │   └── gitea.service.ts             # Gitea API (read-only + write-with-confirmation)
│   │   └── mcp/
│   │       ├── mcp.module.ts
│   │       └── mcp-server.service.ts        # Exposes hermes MCP tools endpoint
│   ├── proxy/
│   │   ├── proxy.module.ts
│   │   └── proxy.service.ts                 # hermes proxy (OpenAI-compatible, port 8766)
│   ├── operations/
│   │   ├── operations.module.ts
│   │   ├── operations-log.service.ts        # SQLite hermes_operations_log
│   │   └── operations.controller.ts         # /operations/logs API
│   ├── qdrant/
│   │   ├── qdrant.module.ts
│   │   └── dev-qdrant.service.ts            # Dev Qdrant client (port 6334)
│   ├── health/
│   │   ├── health.module.ts
│   │   └── health.controller.ts             # /health endpoint
│   ├── common/
│   │   ├── guards/
│   │   │   ├── api-key.guard.ts             # X-API-Key validation
│   │   │   └── telegram-allowlist.guard.ts  # Allowlist check
│   │   ├── interceptors/
│   │   │   └── transaction.interceptor.ts   # Auto-inject transactionId
│   │   └── utils/
│   │       ├── uuid.util.ts                 # UUIDv7 generation (ADR-019)
│   │       └── secret-redactor.util.ts      # Redact secrets from log payload
│   ├── config/
│   │   └── hermes.config.ts                 # All env vars typed
│   ├── app.module.ts
│   └── main.ts
├── test/
│   ├── unit/
│   │   ├── telegram-gateway.spec.ts
│   │   ├── command-router.spec.ts
│   │   ├── orchestrator.spec.ts
│   │   └── secret-redactor.spec.ts
│   └── integration/
│       └── staged-rollout.spec.ts
├── specs/                                   # Docker compose + config
│   └── 04-Infrastructure-OPS/
│       └── 04-00-docker-compose/
│           └── ASUSTOR/
│               └── hermes/
│                   ├── docker-compose.hermes.yml
│                   ├── docker-compose.hermes-redis.yml
│                   ├── docker-compose.hermes-qdrant.yml
│                   ├── hermes.redis.conf
│                   └── .env.example         # เฉพาะ placeholder ห้าม commit secret จริง
├── .env.example
├── Dockerfile
├── nest-cli.json
├── package.json
└── tsconfig.json
```

**Structure Decision**: Standalone NestJS project (`hermes/`) แยกจาก `backend/` และ `frontend/` ทั้งหมด เพราะ Hermes ไม่ใช่ DMS production service และมี deploy target แยก (ASUSTOR NAS) รวมถึงมี Redis/SQLite/Qdrant ของตัวเอง

---

## Implementation Phases

### Phase 1: Setup & Infrastructure Foundation

- สร้าง `hermes/` project structure (NestJS + TypeScript strict)
- Docker Compose files (hermes agent + hermes-redis + hermes-qdrant)
- Config module (typed env vars + secrets validation)
- HealthController + basic API Key guard

### Phase 2: Core Foundational Services

- OperationsLogService (SQLite + create/read/update)
- SecretRedactorUtil (scan + redact sensitive patterns)
- UuidUtil (UUIDv7 generation)
- TransactionInterceptor (auto-inject transactionId per request)

### Phase 3: US1 — Autonomous Dev Orchestrator (P1)

- ContextLoaderService (selective context loading by task type)
- SubAgentService (Claude Haiku/GPT-4o-mini delegation)
- SelfCorrectionService (lint/tsc/test loop, max 3 iterations)
- OrchestratorService (main development loop coordination)
- OrchestratorController (POST /orchestration/tasks, GET /orchestration/tasks/:id)
- SoulService (SOUL.md read/append/rotate)
- DevQdrantService (hermes-qdrant client, code chunk search)

### Phase 4: US2 — Telegram Read-only Commands (P2)

- TelegramRateLimiterService (Redis-based, 10 req/min/user)
- HermesTelegramGateway (webhook verification, allowlist check, rate limit)
- HermesDevOpsCommandRouter (route read-only commands: /status, /ci_status, /repo_summary)
- GiteaService (read-only: repos, issues, PRs, CI status)
- HermesTelegramDispatcher (BullMQ worker, hermes-notification-queue, retry 3x backoff)

### Phase 5: US3 — Telegram Write-with-Confirmation (P3)

- Write action confirmation flow (HermesDevOpsCommandRouter extension)
- GiteaService write methods (create branch/issue/PR/trigger CI — write token scope)
- Forbidden action blocklist enforcement
- hermes-bot Git identity integration (simple-git + hermes-bot service account)
- Branch pattern validation (hermes/{feat,fix,refactor}-*)
- Operations log write action recording (token identity, target repo/branch)

### Phase 6: US4 — Developer AI Proxy (P4)

- ProxyService (OpenAI-compatible API, port 8766)
- Secret payload detection middleware (reject if production data detected)
- MCP server endpoint (/mcp) for agy + Devin integration
- HermesMemoryMcpTool (expose DMS context for agy recall)
- HermesToolsMcpTool (expose bash/git execution capability)

### Phase 7: US5 — Staged Rollout Tooling (P5)

- Stage acceptance gate checklist scripts (PowerShell/bash)
- Monitoring alerts (DevOps warning vs. production outage separation)
- Failure isolation verification tests
- Rollback documentation finalization

### Phase 8: Polish & Cross-Cutting

- Structured logging with NestJS Logger (no console.log)
- JSDoc for all public classes (Thai comments per AGENTS.md)
- Secret scan validation in CI pipeline
- Docker resource limit verification script
- SOUL.md rotation cron job

---

## Key Technical Decisions

| Decision | Choice | Rationale |
|----------|--------|-----------|
| Hermes stack | Standalone NestJS | แยกจาก DMS backend; same tooling; ทีมรู้จักดี |
| Cloud AI | Anthropic SDK + OpenAI SDK | ADR-031 Cloud AI Exception; model flexibility |
| Operations log | SQLite (better-sqlite3) | Simple, no external service, queryable |
| Rate limiting | Redis-based (ioredis) | Stateless container-safe; shares hermes-redis |
| Git operations | simple-git | Lightweight; TypeScript-native |
| Dev Qdrant | Port 6334 (ASUSTOR) | แยกจาก DMS Qdrant port 6333 (QNAP) |
| Telegram SDK | telegraf or node-telegram-bot-api | ต้อง verify ตอน implementation (ADR-031 note) |
