690529:1702 ADR-030-230 context aware #09
This commit is contained in:
@@ -1,29 +1,47 @@
|
||||
# ADR-031: NAP-DMS Integration Strategy (Hermes Agent & Telegram Bridge)
|
||||
# ADR-031: Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge (v2.0)
|
||||
|
||||
## Status
|
||||
|
||||
- **Status:** Draft
|
||||
- **Date:** 2026-05-28
|
||||
- **Version:** 2.0 (2026-05-29 — grill-with-docs: Orchestration as primary concern)
|
||||
- **Deciders:** NAP-DMS Architecture Team
|
||||
- **Supersedes:** ADR-031 v1.1 (DevOps Bridge only)
|
||||
|
||||
### Locked Decisions During Grill
|
||||
### Locked Decisions (v1.x — DevOps Bridge Foundation)
|
||||
|
||||
ข้อตกลงด้านล่างถูกล็อคระหว่าง grill session แล้ว แต่ ADR-031 ยังอยู่ในสถานะ Draft จนกว่า scope และ rollout plan จะ stable:
|
||||
ข้อตกลงด้านล่างถูกล็อคตั้งแต่ v1.x และยังคงบังคับใช้ใน v2.0:
|
||||
|
||||
* **Hermes role:** Hermes เป็น Developer Operations Agent / Integration Assistant เท่านั้น ไม่ใช่ production DMS service และไม่ใช่ AI inference boundary ของ DMS
|
||||
* **Database access:** Hermes เชื่อม MariaDB ได้เฉพาะ read-only account หรือ read-only replica สำหรับ schema inspection, metadata diagnostics, และ query verification เท่านั้น
|
||||
* **Document storage:** Hermes ห้าม mount, browse, หรืออ่าน permanent document storage ของ production โดยตรง หากต้องตรวจเอกสารจริงต้องผ่าน DMS Backend API
|
||||
* **Hermes role:** Hermes เป็น Developer Operations Agent / Autonomous Dev Orchestrator ไม่ใช่ production DMS service และไม่ใช่ AI inference boundary ของ DMS
|
||||
* **Database access:** Hermes เชื่อม MariaDB ได้เฉพาะ read-only account สำหรับ schema inspection, metadata diagnostics เท่านั้น
|
||||
* **Document storage:** Hermes ห้าม mount, browse, หรืออ่าน permanent document storage ของ production โดยตรง
|
||||
* **Telegram scope:** Hermes Telegram ใช้สำหรับ DevOps commands เท่านั้น ไม่ใช่ production DMS command channel
|
||||
* **DMS Telegram:** Telegram command สำหรับ query/mutate เอกสารจริงเป็น future separate ADR/spec และต้อง enforce ADR-009/016/019/023A
|
||||
* **Hermes proxy:** `hermes proxy` เป็น Developer AI Proxy only สำหรับ coding/devops assistance ไม่ใช่ DMS AI runtime หรือ document intelligence path
|
||||
* **Telegram writes:** Telegram write actions ต้องมี explicit confirmation; forbidden actions เช่น push ไป `main`/`master`, production deploy, schema migration execution, direct DB writes, และ storage delete ห้ามทำผ่าน Telegram
|
||||
* **Schema rollout:** ADR-031 rollout ไม่เพิ่มหรือแก้ production DMS schema รวมถึงไม่สร้าง `user_telegram_mapping`
|
||||
* **DMS Telegram:** Telegram command สำหรับ query/mutate เอกสารจริงเป็น future separate ADR/spec
|
||||
* **Hermes proxy:** `hermes proxy` เป็น Developer AI Proxy only ไม่ใช่ DMS AI runtime
|
||||
* **Telegram writes:** ต้องมี explicit confirmation; push `main`/`master`, production deploy, schema migration, direct DB writes, storage delete ห้ามทุกกรณี
|
||||
* **Schema rollout:** ADR-031 ไม่เพิ่มหรือแก้ production DMS schema
|
||||
|
||||
### Locked Decisions (v2.0 — Orchestration Layer)
|
||||
|
||||
ข้อตกลงใหม่จาก grill session 2026-05-29:
|
||||
|
||||
* **Cloud AI Exception:** Hermes Orchestrator layer อนุญาต Cloud AI API (Claude/GPT-4o) ได้ — เป็น exception จาก ADR-023A ที่ใช้เฉพาะ DevOps/Dev Orchestration layer เท่านั้น ไม่ใช่ DMS document processing
|
||||
* **Data Classification (Dev-Out Policy):** Code, Config, ADR, Stack trace ส่ง Cloud AI ได้ — Production runtime data จาก DB query (document content, user info, project business data) ห้ามส่งออกทุกกรณี
|
||||
* **Dev Qdrant:** Separate Qdrant instance บน ASUSTOR สำหรับ codebase embedding โดยเฉพาะ — ห้ามใช้ Qdrant instance เดียวกับ DMS document RAG (ADR-023A)
|
||||
* **SOUL.md:** Hermes working journal อยู่ใน container เท่านั้น (`/volume1/docker/hermes/SOUL.md`) ไม่ sync กลับ repo
|
||||
* **Context Source:** Hermes ดึง project context จาก `specs/06-Decision-Records/CONTEXT-ADR-031.md` + `AGENTS.md` โดยตรง ไม่ใช้ Obsidian หรือ external knowledge base
|
||||
* **Sub-agent Delegation:** Hermes orchestrate โดย (1) Cloud sub-agents ใช้ model เล็กกว่า (Claude Haiku/GPT-4o-mini) สำหรับ code generation tasks และ (2) MCP invocations ไปยัง Windsurf/agy ที่มีอยู่แล้ว
|
||||
* **Git Identity:** Hermes ใช้ Gitea service account (`hermes-bot`) push เฉพาะ `hermes/*` branches — ห้าม push ตรง `main`/`develop` ทุกกรณี — ทุก change ต้องผ่าน PR ที่ human approve
|
||||
|
||||
## Context
|
||||
|
||||
การตั้งค่าระบบ **Hermes Agent** ในโปรเจกต์ **NAP-DMS (LCBP3)** เวอร์ชัน 1.9.0 เพื่อเชื่อมต่อกับโครงสร้างพื้นฐานเดิมและขยายขีดความสามารถผ่าน Telegram Bridge สำหรับการแจ้งเตือนและการสั่งงานผ่านระบบ Command
|
||||
การตั้งค่าระบบ **Hermes Agent** ในโปรเจกต์ **NAP-DMS (LCBP3)** เพื่อทำหน้าที่เป็น **Autonomous Development Loop Orchestrator** — ควบคุมงาน AI Coding ทั้งหมด วาง Roadmap จ่ายงานให้ sub-agents ตรวจสอบผลลัพธ์ และสร้าง PR สำหรับ human review
|
||||
|
||||
Hermes Agent ถูกนิยามเป็น **Developer Operations Agent / Integration Assistant** สำหรับงานพัฒนา, ตรวจสอบ, ประสานเครื่องมือ, และช่วยสั่งงาน DevOps เท่านั้น ไม่ใช่ production DMS service และไม่ใช่ AI inference boundary ของ DMS ตาม ADR-023/ADR-023A
|
||||
ใน v2.0 Hermes มี 2 primary roles:
|
||||
1. **Autonomous Dev Orchestrator** (primary) — คุม development loop ตั้งแต่ requirement จนถึง PR
|
||||
2. **Telegram DevOps Bridge** (subsystem) — DevOps commands, CI status, Gitea notifications
|
||||
|
||||
Hermes ไม่ใช่ production DMS service และไม่ใช่ DMS AI inference boundary (ADR-023/ADR-023A) แต่ได้รับ **Cloud AI exception** สำหรับ dev orchestration layer โดยเฉพาะ พร้อม Data Classification Policy ที่ชัดเจน
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -58,6 +76,166 @@ Hermes Agent ถูกนิยามเป็น **Developer Operations Agent /
|
||||
|
||||
---
|
||||
|
||||
## Orchestration Architecture (v2.0 — Primary Concern)
|
||||
|
||||
### Overview: Autonomous Development Loop
|
||||
|
||||
Hermes ทำหน้าที่เป็น "Lead Developer" / "Conductor" ที่คุม development loop ทั้งหมด โดยไม่ลงไปเขียนโค้ดทุกบรรทัดเอง แต่วางแผน จ่ายงาน ตรวจสอบผลลัพธ์ และสร้าง PR:
|
||||
|
||||
```
|
||||
[Developer / Telegram Command]
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Hermes Orchestrator (Flagship Cloud AI) │
|
||||
│ Claude / GPT-4o │
|
||||
│ Context: CONTEXT-ADR-031.md + AGENTS.md │
|
||||
│ Memory: SOUL.md (container-local) │
|
||||
│ Search: Dev Qdrant (ASUSTOR) │
|
||||
└──────────┬──────────────────────────────┘
|
||||
│
|
||||
┌───────┴────────┐
|
||||
▼ ▼
|
||||
[Cloud Sub-agents] [MCP Tool Invocations]
|
||||
Claude Haiku / Windsurf / agy / Codex
|
||||
GPT-4o-mini (existing tools, no new models)
|
||||
│ ▼
|
||||
└────────┬───────
|
||||
▼
|
||||
[Self-Correction Loop]
|
||||
npm run lint / jest / tsc
|
||||
→ Error? Re-delegate to sub-agent
|
||||
→ Pass? Continue
|
||||
│
|
||||
▼
|
||||
[Git: hermes/* branch]
|
||||
hermes-bot commits
|
||||
Creates PR → Human Review & Approve
|
||||
```
|
||||
|
||||
### Step 1: Requirement & Context Assembly
|
||||
|
||||
Hermes โหลด context แบบ **selective** ตาม task type เพื่อลด token ที่ส่งไป Cloud AI:
|
||||
|
||||
| Task Type | Context ที่โหลด |
|
||||
|-----------|----------------|
|
||||
| DevOps / CI / Git | `CONTEXT-ADR-031.md` + `AGENTS.md` |
|
||||
| DMS feature coding | `CONTEXT-ADR-031.md` + `AGENTS.md` + `CONTEXT.md` |
|
||||
| Schema / DB work | `CONTEXT-ADR-031.md` + `AGENTS.md` + `CONTEXT.md` + schema SQL (read-only) |
|
||||
| Bug fix / refactor | `CONTEXT-ADR-031.md` + `AGENTS.md` + Dev Qdrant (code patterns) |
|
||||
|
||||
**Sources:**
|
||||
- `specs/06-Decision-Records/CONTEXT-ADR-031.md` — agent rules, project identity, tooling, infra paths
|
||||
- `CONTEXT.md` (root) — domain terminology (Correspondence, RFA, Workflow Engine, AI concepts) — โหลดเฉพาะ DMS feature tasks
|
||||
- `AGENTS.md` — TypeScript rules, forbidden patterns (no `any`, no `parseInt` on UUID), ADR references
|
||||
- Dev Qdrant (ASUSTOR) — semantic code search หา reference patterns จาก codebase embeddings
|
||||
|
||||
**ห้ามดึง** production runtime data (DB query results, document content, user data) เข้า cloud AI context
|
||||
|
||||
### Step 2: Semantic Code Search (Dev Qdrant)
|
||||
|
||||
Hermes ใช้ Qdrant instance แยก (บน ASUSTOR, ไม่ใช่ DMS Qdrant) ทำ semantic search หา reference patterns ใน codebase:
|
||||
|
||||
```yaml
|
||||
# docker-compose.hermes-qdrant.yml (ASUSTOR — แยกจาก DMS)
|
||||
services:
|
||||
hermes-qdrant:
|
||||
image: qdrant/qdrant:latest
|
||||
container_name: hermes-qdrant
|
||||
volumes:
|
||||
- hermes_qdrant_data:/qdrant/storage
|
||||
ports:
|
||||
- "6334:6333" # port แยกจาก DMS Qdrant (:6333)
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
```
|
||||
|
||||
Collection: `lcbp3_code_chunks` — indexed by `repoName` + `moduleName` (ไม่ใช่ `projectPublicId` ซึ่งเป็น DMS document isolation)
|
||||
|
||||
### Step 3: Sub-agent Delegation
|
||||
|
||||
Hermes แตกงานเป็น tasks แล้ว delegate ผ่าน 2 channels:
|
||||
|
||||
**Channel A — Cloud Sub-agents (Code Generation):**
|
||||
```
|
||||
Orchestrator (Claude/GPT-4o)
|
||||
→ "เขียน NestJS service สำหรับ X"
|
||||
→ Sub-agent (Claude Haiku / GPT-4o-mini)
|
||||
→ Returns code diff
|
||||
→ Orchestrator validates against AGENTS.md rules
|
||||
```
|
||||
|
||||
**Channel B — MCP Tool Invocations (File Execution):**
|
||||
```
|
||||
Orchestrator
|
||||
→ MCP hermes-tools: bash/git operations บน ASUSTOR
|
||||
→ MCP mariadb: schema lookup (read-only)
|
||||
→ MCP gitea: PR/issue management
|
||||
→ Triggers Windsurf/agy ถ้า complex scaffolding needed
|
||||
```
|
||||
|
||||
**Data Classification Enforcement:**
|
||||
| ส่งได้ | ห้ามส่ง |
|
||||
|--------|---------|
|
||||
| Code snippets, patterns | Production DB query results |
|
||||
| ADR/spec content | Document content (title, body) |
|
||||
| Stack traces, error output | User data, project names from DB |
|
||||
| Config files, tsconfig | API keys, tokens, passwords |
|
||||
| Schema structure (column names) | Storage paths ที่มี PII |
|
||||
|
||||
### Step 4: Self-Correction Loop
|
||||
|
||||
โค้ดที่ sub-agent ส่งกลับมาต้องผ่าน validation ก่อนใช้:
|
||||
|
||||
```bash
|
||||
# Hermes runs via MCP hermes-tools
|
||||
npm run lint # ESLint — ต้องผ่านทุก rule
|
||||
npx tsc --noEmit # TypeScript strict mode
|
||||
npm test -- --passWithNoTests # Jest tests ที่เกี่ยวข้อง
|
||||
```
|
||||
|
||||
ถ้าพบ error → Hermes วิเคราะห์ output → ส่งกลับให้ sub-agent แก้ไข (max 3 iterations)
|
||||
ถ้า iteration > 3 → หยุดและแจ้ง developer ผ่าน Telegram
|
||||
|
||||
### Step 5: Git Identity & PR Flow
|
||||
|
||||
```
|
||||
hermes-bot commits → hermes/feat-{task-id} branch
|
||||
├─ git config user.name "Hermes Bot"
|
||||
├─ git config user.email "hermes-bot@np-dms.work"
|
||||
├─ commit message: "feat(hermes): {task description}\n\nOrchestrated by Hermes ADR-031 v2.0"
|
||||
└─ push → Gitea → Create PR → assign to developer
|
||||
```
|
||||
|
||||
**Git Identity Rules:**
|
||||
- Service account: `hermes-bot` (Gitea, least privilege, write token เฉพาะ feature branches)
|
||||
- Branch pattern: `hermes/feat-*`, `hermes/fix-*`, `hermes/refactor-*`
|
||||
- ห้าม push ตรง `main`, `develop`, `release/*` ทุกกรณี
|
||||
- PR ต้องผ่าน CI (lint + test) ก่อน merge
|
||||
- Human ต้อง review และ approve ก่อน merge เสมอ — ห้าม auto-merge
|
||||
|
||||
### SOUL.md — Hermes Working Journal
|
||||
|
||||
`/volume1/docker/hermes/SOUL.md` เก็บ per-session working memory ของ Hermes:
|
||||
|
||||
```markdown
|
||||
## Session 2026-05-29T10:30
|
||||
Task: scaffold correspondence search feature
|
||||
Context loaded: CONTEXT-ADR-031.md, backend/src/modules/correspondence/
|
||||
Sub-agents delegated: 2 code generation calls
|
||||
Iterations: 1 (lint pass first try)
|
||||
PR created: hermes/feat-correspondence-search → #142
|
||||
Status: DONE
|
||||
```
|
||||
|
||||
- ไม่ commit ลง repo — อยู่ใน container volume เท่านั้น
|
||||
- Hermes อ่าน SOUL.md ต้น session เพื่อ resume context
|
||||
- Rotate ทุก 30 วัน หรือ manual clear
|
||||
|
||||
---
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. Infrastructure Configuration
|
||||
@@ -801,6 +979,7 @@ ADR-031 ต้อง rollout แบบเป็น stage เพื่อลด
|
||||
- ADR-016: Security & Authentication
|
||||
- ADR-019: Hybrid Identifier Strategy (UUIDv7)
|
||||
- ADR-023/ADR-023A: Unified AI Architecture และ AI isolation boundary
|
||||
- ADR-031 v2.0: Cloud AI exception สำหรับ Hermes dev orchestration layer (ดู Locked Decisions v2.0)
|
||||
|
||||
---
|
||||
|
||||
@@ -812,3 +991,5 @@ ADR-031 ต้อง rollout แบบเป็น stage เพื่อลด
|
||||
| 2026-05-28 | 1.1.0 | Added sections 4–6 from CONTEXT-ADR-031-Added-2: Hermes Interface Modes, agy+Hermes MCP Integration, Deploy Prerequisites; fixed port conflict (hermes proxy :8766, not :8765) |
|
||||
| 2026-05-29 | 1.1.1 | Aligned with CONTEXT-ADR-031.md grill-with-docs: fixed monorepo structure (flat layout), corrected file paths, updated repo URL to git.np-dms.work, added AGENTS.md v1.9.7 reference |
|
||||
| 2026-05-29 | 1.1.2 | Linked root CONTEXT.md with specs/CONTEXT-ADR-031.md; fixed setup-context.sh paths; updated Windsurf/agy/Hermes symlink targets |
|
||||
| 2026-05-29 | 2.0.0 | **v2.0 Rewrite** — grill-with-docs: Orchestration as primary concern; Added Autonomous Dev Loop architecture; Cloud AI exception (Data Classification Policy C); Separate Dev Qdrant on ASUSTOR; SOUL.md container-local journal; Sub-agent delegation (Cloud+MCP); Git identity hermes-bot + hermes/* branches + PR-only flow |
|
||||
| 2026-05-29 | 2.0.1 | Step 1 context assembly: เพิ่ม `CONTEXT.md` (root domain terminology) เป็น selective context source สำหรับ DMS feature coding และ Schema/DB work tasks |
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Specification Quality Checklist: Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2026-05-29
|
||||
**Feature**: [spec.md](../spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain (ADR-031 v2.0 provides all decisions locked)
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable (SC-001 through SC-010)
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined (US1–US5, 5 scenarios each)
|
||||
- [x] Edge cases are identified (10 edge cases)
|
||||
- [x] Scope is clearly bounded (Out of Scope section present)
|
||||
- [x] Dependencies and assumptions identified (Assumptions section present)
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria (FR-001 through FR-020)
|
||||
- [x] User scenarios cover primary flows (Orchestration, Telegram Read, Telegram Write, Proxy, Staged Rollout)
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- Spec derived from ADR-031 v2.0 (2026-05-29) — Locked Decisions are authoritative
|
||||
- Cloud AI exception scope clearly bounded to dev orchestration layer only
|
||||
- Failure isolation (SC-004) is the most critical non-functional requirement
|
||||
- Staged rollout (FR-015, SC-007) is prerequisite to any production deployment
|
||||
- All items pass — spec is ready for clarification and planning phases
|
||||
@@ -0,0 +1,339 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Hermes Agent API
|
||||
description: |
|
||||
Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge
|
||||
Feature: 231-hermes-agent | ADR-031 v2.0
|
||||
|
||||
IMPORTANT:
|
||||
- All endpoints are LAN/VPN-only (never public internet)
|
||||
- Telegram webhook endpoint is the only exception (via reverse proxy with TLS)
|
||||
- Authentication: X-API-Key header for all non-webhook endpoints
|
||||
- All responses include transactionId for traceability
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: NAP-DMS Architecture Team
|
||||
|
||||
servers:
|
||||
- url: http://{ASUSTOR_IP}:8080/api/v1
|
||||
description: Hermes Agent API (LAN/VPN only)
|
||||
variables:
|
||||
ASUSTOR_IP:
|
||||
default: "192.168.10.X"
|
||||
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
ApiKeyAuth:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: X-API-Key
|
||||
description: HERMES_PROXY_API_KEY — stored in ASUSTOR secret store
|
||||
|
||||
schemas:
|
||||
TransactionId:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUIDv7 transaction identifier (ADR-019)
|
||||
example: "019505a1-7c3e-7000-8000-abc123def456"
|
||||
|
||||
HermesStatus:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [HEALTHY, DEGRADED, DOWN]
|
||||
version:
|
||||
type: string
|
||||
uptime:
|
||||
type: number
|
||||
queues:
|
||||
type: object
|
||||
properties:
|
||||
notification:
|
||||
type: object
|
||||
properties:
|
||||
waiting: { type: number }
|
||||
active: { type: number }
|
||||
failed: { type: number }
|
||||
orchestration:
|
||||
type: object
|
||||
properties:
|
||||
waiting: { type: number }
|
||||
active: { type: number }
|
||||
failed: { type: number }
|
||||
soulMdLastEntry:
|
||||
type: string
|
||||
description: ISO datetime of last SOUL.md session entry
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
OperationsLogEntry:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
operatorIdentity:
|
||||
type: string
|
||||
commandType:
|
||||
type: string
|
||||
enum: [TELEGRAM_INBOUND, TELEGRAM_OUTBOUND, ORCHESTRATION_TASK, GIT_WRITE, PROXY_REQUEST]
|
||||
targetSystem:
|
||||
type: string
|
||||
commandSummary:
|
||||
type: string
|
||||
description: Redacted command description
|
||||
status:
|
||||
type: string
|
||||
enum: [PENDING, IN_PROGRESS, COMPLETED, FAILED, REJECTED]
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
completedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
errorClassification:
|
||||
type: string
|
||||
nullable: true
|
||||
|
||||
OrchestrationTaskRequest:
|
||||
type: object
|
||||
required: [description, taskType, telegramChatId]
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
description: Coding task description (no production data)
|
||||
taskType:
|
||||
type: string
|
||||
enum: [DEVOPS, DMS_FEATURE, SCHEMA_DB, BUG_FIX]
|
||||
telegramChatId:
|
||||
type: string
|
||||
description: Chat ID for progress/result notifications
|
||||
|
||||
OrchestrationTaskResponse:
|
||||
type: object
|
||||
properties:
|
||||
taskId:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
status:
|
||||
type: string
|
||||
enum: [QUEUED, CONTEXT_LOADING, SUB_AGENT_DELEGATED, SELF_CORRECTION, PR_CREATED, DONE, ESCALATED, FAILED]
|
||||
prUrl:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Gitea PR URL (populated when status=PR_CREATED or DONE)
|
||||
branchName:
|
||||
type: string
|
||||
nullable: true
|
||||
|
||||
TelegramWebhookPayload:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: object
|
||||
properties:
|
||||
from:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: integer }
|
||||
username: { type: string }
|
||||
text: { type: string }
|
||||
chat:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: integer }
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
transactionId:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
|
||||
paths:
|
||||
/health:
|
||||
get:
|
||||
summary: Hermes health check
|
||||
description: Returns current health status of Hermes Agent and its subsystems
|
||||
security: []
|
||||
operationId: getHealth
|
||||
tags: [System]
|
||||
responses:
|
||||
'200':
|
||||
description: Health status
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/HermesStatus'
|
||||
|
||||
/telegram/webhook:
|
||||
post:
|
||||
summary: Telegram webhook inbound handler
|
||||
description: |
|
||||
Receives Telegram Bot webhook updates.
|
||||
MUST be behind reverse proxy with TLS.
|
||||
MUST verify X-Telegram-Bot-Api-Secret-Token header.
|
||||
DevOps commands only — no DMS document operations.
|
||||
security: []
|
||||
operationId: handleTelegramWebhook
|
||||
tags: [Telegram]
|
||||
parameters:
|
||||
- name: X-Telegram-Bot-Api-Secret-Token
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Telegram webhook secret for request verification
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TelegramWebhookPayload'
|
||||
responses:
|
||||
'200':
|
||||
description: Webhook processed (command dispatched or acknowledged)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
transactionId:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
status:
|
||||
type: string
|
||||
enum: [DISPATCHED, REJECTED, ACKNOWLEDGED]
|
||||
'401':
|
||||
description: Invalid webhook secret token
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'429':
|
||||
description: Rate limit exceeded
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
|
||||
/orchestration/tasks:
|
||||
post:
|
||||
summary: Submit autonomous coding task
|
||||
description: |
|
||||
Submit a coding task for Hermes to orchestrate via sub-agents.
|
||||
NEVER include production document content, DB query results, or secrets in task description.
|
||||
operationId: submitOrchestrationTask
|
||||
tags: [Orchestration]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OrchestrationTaskRequest'
|
||||
responses:
|
||||
'202':
|
||||
description: Task queued successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OrchestrationTaskResponse'
|
||||
'401':
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
|
||||
/orchestration/tasks/{taskId}:
|
||||
get:
|
||||
summary: Get orchestration task status
|
||||
operationId: getOrchestrationTask
|
||||
tags: [Orchestration]
|
||||
parameters:
|
||||
- name: taskId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
responses:
|
||||
'200':
|
||||
description: Task status
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OrchestrationTaskResponse'
|
||||
'404':
|
||||
description: Task not found
|
||||
|
||||
/operations/logs:
|
||||
get:
|
||||
summary: Query Hermes operations log
|
||||
description: Returns paginated DevOps operations log entries. Admin only.
|
||||
operationId: getOperationsLog
|
||||
tags: [Operations]
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 50
|
||||
maximum: 200
|
||||
- name: offset
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
- name: status
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [PENDING, IN_PROGRESS, COMPLETED, FAILED, REJECTED]
|
||||
- name: commandType
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Operations log entries
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/OperationsLogEntry'
|
||||
total:
|
||||
type: integer
|
||||
offset:
|
||||
type: integer
|
||||
|
||||
/operations/logs/{transactionId}:
|
||||
get:
|
||||
summary: Get specific operation by transactionId
|
||||
description: Used by Telegram /status command to track DevOps transactions
|
||||
operationId: getOperationByTransactionId
|
||||
tags: [Operations]
|
||||
parameters:
|
||||
- name: transactionId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
responses:
|
||||
'200':
|
||||
description: Operation details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OperationsLogEntry'
|
||||
'404':
|
||||
description: Transaction not found
|
||||
@@ -0,0 +1,149 @@
|
||||
// File: specs/200-fullstacks/231-hermes-agent/data-model.md
|
||||
// Change Log:
|
||||
// - 2026-05-29: Initial data model for Hermes Agent
|
||||
|
||||
# Data Model: Hermes Agent
|
||||
|
||||
**Feature**: 231-hermes-agent | **Date**: 2026-05-29
|
||||
|
||||
> **Important**: Hermes ไม่เพิ่มหรือแก้ DMS production schema ทุกกรณี (ADR-031, FR-017)
|
||||
> Data model นี้ทั้งหมดอยู่ใน **Hermes-owned storage** (SQLite / container volume) ไม่ใช่ DMS MariaDB
|
||||
|
||||
---
|
||||
|
||||
## 1. HermesOperationsLog (SQLite table: `hermes_operations_log`)
|
||||
|
||||
บันทึก inbound/outbound DevOps operations ทุก transaction ของ Hermes
|
||||
|
||||
| Field | Type | Constraints | Description |
|
||||
|-------|------|-------------|-------------|
|
||||
| `id` | TEXT (UUIDv7) | PRIMARY KEY | Transaction ID — ใช้ UUIDv7 ตาม ADR-019 |
|
||||
| `operator_identity` | TEXT | NOT NULL | Telegram user ID หรือ CLI session identity |
|
||||
| `command_type` | TEXT | NOT NULL | เช่น `TELEGRAM_INBOUND`, `TELEGRAM_OUTBOUND`, `ORCHESTRATION_TASK`, `GIT_WRITE` |
|
||||
| `target_system` | TEXT | NOT NULL | เช่น `TELEGRAM`, `GITEA`, `CLOUD_AI`, `DEV_QDRANT` |
|
||||
| `command_summary` | TEXT | NOT NULL | Redacted command description (ห้ามมี secret/token/sensitive path) |
|
||||
| `status` | TEXT | NOT NULL | `PENDING` / `IN_PROGRESS` / `COMPLETED` / `FAILED` / `REJECTED` |
|
||||
| `created_at` | DATETIME | NOT NULL DEFAULT CURRENT_TIMESTAMP | |
|
||||
| `completed_at` | DATETIME | NULLABLE | |
|
||||
| `error_classification` | TEXT | NULLABLE | เช่น `AUTH_FAILURE`, `RATE_LIMIT`, `FORBIDDEN_ACTION`, `EXTERNAL_API_ERROR` |
|
||||
| `gitea_token_identity` | TEXT | NULLABLE | Token scope/identity สำหรับ Git write actions (ไม่ใช่ token value) |
|
||||
| `target_repo` | TEXT | NULLABLE | สำหรับ Git write actions |
|
||||
| `target_branch` | TEXT | NULLABLE | สำหรับ Git write actions |
|
||||
|
||||
**Retention**: 90 วัน แล้ว archive/delete ตาม DevOps log policy
|
||||
**Access**: Read เฉพาะ admin/operator ที่จำเป็น
|
||||
**Redaction**: `command_summary` ต้องผ่าน secret scanner ก่อน insert
|
||||
|
||||
---
|
||||
|
||||
## 2. HermesRateLimitState (Redis key pattern)
|
||||
|
||||
| Key Pattern | Value | TTL | Description |
|
||||
|-------------|-------|-----|-------------|
|
||||
| `hermes:telegram:{telegramUserId}` | INT (request count) | 60s | Rate limit counter per user; expire ทุก 60 วินาที |
|
||||
|
||||
---
|
||||
|
||||
## 3. HermesBullMQJobs (Redis via `hermes-notification-queue`)
|
||||
|
||||
### Job: `telegram-devops-outbound`
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `transactionId` | string (UUIDv7) | Reference ID for tracking |
|
||||
| `chatId` | string | Telegram chat ID |
|
||||
| `message` | string | Outbound message text (ไม่มี secret/PII) |
|
||||
| `retryCount` | number | Current retry count (max 3) |
|
||||
|
||||
---
|
||||
|
||||
## 4. HermesOrchestrationTask (Redis via `hermes-orchestration-queue`)
|
||||
|
||||
### Job: `orchestration-task`
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `taskId` | string (UUIDv7) | Task tracking ID |
|
||||
| `taskType` | `DEVOPS` / `DMS_FEATURE` / `SCHEMA_DB` / `BUG_FIX` | กำหนด context loading strategy |
|
||||
| `description` | string | Task description (no production data) |
|
||||
| `contextSources` | string[] | Context files to load |
|
||||
| `maxIterations` | number | Self-correction loop limit (default: 3) |
|
||||
| `telegramChatId` | string | สำหรับ progress/result notification |
|
||||
| `createdAt` | string (ISO 8601) | |
|
||||
|
||||
---
|
||||
|
||||
## 5. SOUL.md (Container File: `/volume1/docker/hermes/SOUL.md`)
|
||||
|
||||
ไม่ใช่ DB table แต่เป็น plain Markdown file working journal ใน container volume
|
||||
|
||||
**Structure per session entry**:
|
||||
```markdown
|
||||
## Session {ISO_DATETIME}
|
||||
Task: {task description}
|
||||
TaskType: {DEVOPS|DMS_FEATURE|SCHEMA_DB|BUG_FIX}
|
||||
Context loaded: {comma-separated context files}
|
||||
Sub-agents delegated: {count} code generation calls
|
||||
Iterations: {count} ({result of last iteration})
|
||||
PR created: {branch} → #{pr_number}
|
||||
Status: {DONE|ESCALATED|FAILED}
|
||||
```
|
||||
|
||||
**File management**:
|
||||
- Read at session start for context resumption
|
||||
- Append only (never overwrite previous entries)
|
||||
- Rotate (clear and archive) every 30 days or manual clear
|
||||
- Never synced to repo — container volume only
|
||||
|
||||
---
|
||||
|
||||
## 6. DevQdrantCollection (`lcbp3_code_chunks` on ASUSTOR:6334)
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string (UUID) | Chunk ID |
|
||||
| `repoName` | string | Repository name (e.g., `lcbp3`) |
|
||||
| `moduleName` | string | Module path (e.g., `backend/src/modules/correspondence`) |
|
||||
| `filePath` | string | Relative file path |
|
||||
| `chunkIndex` | number | Chunk position in file |
|
||||
| `content` | string | Code chunk text |
|
||||
| `vector` | float[] | nomic-embed-text embedding (768 dimensions) |
|
||||
|
||||
> **ไม่ใช้ `projectPublicId` filter** (ซึ่งเป็น DMS document isolation key) — ใช้ `repoName` + `moduleName` แทน ตาม ADR-031 v2.0
|
||||
|
||||
---
|
||||
|
||||
## Entity Relationships
|
||||
|
||||
```
|
||||
HermesAgent
|
||||
├── orchestrates → HermesOrchestrationTask (via hermes-orchestration-queue)
|
||||
│ ├── delegates → HermesSubAgent (Cloud AI: Claude Haiku / GPT-4o-mini)
|
||||
│ ├── searches → DevQdrantCollection (code patterns)
|
||||
│ └── records → SOUL.md (session journal)
|
||||
└── bridges → HermesTelegramGateway
|
||||
├── validates → HermesRateLimitState (Redis)
|
||||
├── records → HermesOperationsLog (SQLite)
|
||||
└── dispatches → HermesBullMQJobs (hermes-notification-queue)
|
||||
└── sends → Telegram API
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State Transitions: HermesOperationsLog.status
|
||||
|
||||
```
|
||||
PENDING → IN_PROGRESS → COMPLETED
|
||||
→ FAILED
|
||||
→ REJECTED (allowlist/rate-limit/forbidden-action check)
|
||||
```
|
||||
|
||||
## State Transitions: HermesOrchestrationTask
|
||||
|
||||
```
|
||||
QUEUED → CONTEXT_LOADING → SUB_AGENT_DELEGATED
|
||||
→ SELF_CORRECTION (max 3 iterations)
|
||||
→ PR_CREATED → DONE
|
||||
→ ESCALATED (>3 iterations, notify Developer)
|
||||
→ FAILED
|
||||
```
|
||||
@@ -0,0 +1,258 @@
|
||||
// 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 + Windsurf 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) |
|
||||
@@ -0,0 +1,200 @@
|
||||
// File: specs/200-fullstacks/231-hermes-agent/quickstart.md
|
||||
// Change Log:
|
||||
// - 2026-05-29: Initial quickstart / verification guide for Hermes Agent staged rollout
|
||||
|
||||
# Quickstart: Hermes Agent Staged Rollout
|
||||
|
||||
**Feature**: 231-hermes-agent | **Date**: 2026-05-29
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [ ] ASUSTOR NAS with Docker support (ADM + Docker add-on)
|
||||
- [ ] ASUSTOR IP confirmed (default: `192.168.10.X` — run `df -h` to confirm share paths)
|
||||
- [ ] Gitea `hermes-bot` service account created with read-only token (write token created separately for Stage 4)
|
||||
- [ ] Telegram bot created via @BotFather → bot token available
|
||||
- [ ] Cloud AI API keys (Claude/Anthropic + OpenAI) stored in ASUSTOR secret store
|
||||
- [ ] inter-VLAN routing confirmed: ASUSTOR → QNAP (MariaDB :3306, Gitea :3000) — required for Stage 2+
|
||||
|
||||
---
|
||||
|
||||
## Stage 0 — Documentation Only (Architecture Team approval required)
|
||||
|
||||
**Goal**: ADR boundary reviewed, locked decisions captured, no deploy files applied
|
||||
|
||||
Verification gate:
|
||||
- [ ] ADR-031 v2.0 reviewed and all Locked Decisions confirmed
|
||||
- [ ] No SQL delta files created
|
||||
- [ ] No docker-compose files applied to ASUSTOR
|
||||
|
||||
✅ **Gate passed** → advance to Stage 1
|
||||
|
||||
---
|
||||
|
||||
## Stage 1 — Hermes Container LAN-only (DevOps/Admin approval)
|
||||
|
||||
```bash
|
||||
# บน ASUSTOR shell (SSH ก่อน)
|
||||
ssh admin@<ASUSTOR_IP>
|
||||
|
||||
# ขึ้น stack (hermes-redis + hermes-agent)
|
||||
cd /volume1/docker/hermes
|
||||
docker compose -f docker-compose.hermes.yml up -d
|
||||
|
||||
# Verify resource limits enforce จริง
|
||||
docker inspect hermes_agent_lcbp3 | grep -E '"Memory"|"NanoCpus"'
|
||||
docker stats hermes_agent_lcbp3 --no-stream
|
||||
```
|
||||
|
||||
Verification gate:
|
||||
- [ ] Container running: `docker ps | grep hermes_agent_lcbp3`
|
||||
- [ ] LAN/VPN-only: Hermes `:8080`, `:8766`, `/mcp` ไม่ accessible จาก public internet
|
||||
- [ ] Redis แยกจาก DMS: `docker network inspect lcbp3 | grep hermes-redis` (ต้องอยู่ใน network แยก หรือ isolate ด้วย ACL)
|
||||
- [ ] CPU ≤ 2.0 cores, RAM ≤ 4096MB enforce จาก `docker inspect`
|
||||
|
||||
✅ **Gate passed** → advance to Stage 2
|
||||
|
||||
---
|
||||
|
||||
## Stage 2 — Read-only Diagnostics (DBA/Security + DevOps approval)
|
||||
|
||||
```bash
|
||||
# ทดสอบ MariaDB read-only connection (ไม่ควร write ได้)
|
||||
docker exec hermes_agent_lcbp3 node -e "
|
||||
const mysql = require('mysql2');
|
||||
const conn = mysql.createConnection({
|
||||
host: process.env.HERMES_MARIADB_READONLY_HOST,
|
||||
user: process.env.HERMES_MARIADB_READONLY_USER,
|
||||
password: process.env.HERMES_MARIADB_READONLY_PASSWORD,
|
||||
database: process.env.HERMES_MARIADB_READONLY_DATABASE
|
||||
});
|
||||
conn.query('SHOW TABLES', (err, rows) => { console.log(rows); conn.end(); });
|
||||
"
|
||||
|
||||
# ทดสอบ write ต้องล้มเหลว
|
||||
# (INSERT statement should return error with read-only user)
|
||||
```
|
||||
|
||||
Verification gate:
|
||||
- [ ] Read-only DB grant verified: SELECT pass, INSERT/UPDATE/DELETE fail
|
||||
- [ ] Masked/redacted fields verified: no document content, user passwords, storage paths in query results
|
||||
- [ ] Gitea read-only token verified: GET repos/issues/PRs pass, POST/PATCH/DELETE fail
|
||||
- [ ] No direct storage mount: `docker inspect hermes_agent_lcbp3 | grep Mounts` — no permanent storage paths
|
||||
|
||||
✅ **Gate passed** → advance to Stage 3
|
||||
|
||||
---
|
||||
|
||||
## Stage 3 — Telegram Read-only DevOps (DevOps/Security approval)
|
||||
|
||||
```bash
|
||||
# ทดสอบ webhook secret verification
|
||||
curl -X POST http://localhost:8080/api/v1/telegram/webhook \
|
||||
-H "X-Telegram-Bot-Api-Secret-Token: WRONG_SECRET" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message":{"from":{"id":123},"text":"/status","chat":{"id":123}}}' \
|
||||
# ต้องได้ 401 Unauthorized
|
||||
|
||||
# ทดสอบ allowlist rejection
|
||||
curl -X POST http://localhost:8080/api/v1/telegram/webhook \
|
||||
-H "X-Telegram-Bot-Api-Secret-Token: ${HERMES_TELEGRAM_WEBHOOK_SECRET}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message":{"from":{"id":999999999},"text":"/status","chat":{"id":999999999}}}' \
|
||||
# ต้องได้ rejected (user ไม่อยู่ใน allowlist)
|
||||
|
||||
# ทดสอบ /ci_status จาก authorized user
|
||||
# (ส่งผ่าน Telegram จริง หรือ simulate ด้วย authorized user ID)
|
||||
```
|
||||
|
||||
Verification gate:
|
||||
- [ ] Telegram allowlist verified: non-allowlisted user rejected 100%
|
||||
- [ ] Webhook secret verified: wrong secret → 401
|
||||
- [ ] Rate limit verified: >10 requests/minute from same user → rejected
|
||||
- [ ] `hermes_operations_log` captures inbound/outbound transactions with transactionId
|
||||
- [ ] `/ci_status`, `/repo_summary`, `/status`, `/audit_summary` return correct data
|
||||
|
||||
✅ **Gate passed** → advance to Stage 4
|
||||
|
||||
---
|
||||
|
||||
## Stage 4 — Write-with-Confirmation DevOps (Architecture + Security + Repo Owner approval)
|
||||
|
||||
```bash
|
||||
# ทดสอบ forbidden action blocker
|
||||
# ส่งคำสั่ง "push to main" ผ่าน Telegram
|
||||
# ต้องได้ rejection message โดยไม่มีการดำเนินการใดๆ
|
||||
|
||||
# ทดสอบ confirmation flow
|
||||
# ส่ง "เตรียม branch proposal สำหรับ fix/test-issue"
|
||||
# → Hermes แสดง summary + ขอ confirmation
|
||||
# → ยืนยัน
|
||||
# → ตรวจสอบ Gitea: branch hermes/fix-test-issue ถูกสร้าง
|
||||
# → ตรวจสอบ hermes_operations_log: มี entry พร้อม transactionId
|
||||
|
||||
# ทดสอบ hermes-bot token scope
|
||||
git -c http.extraHeader="Authorization: token ${HERMES_BOT_WRITE_TOKEN}" \
|
||||
push gitea-origin main
|
||||
# ต้องได้ 403 Forbidden (branch protection + token scope block)
|
||||
```
|
||||
|
||||
Verification gate:
|
||||
- [ ] Explicit confirmation flow verified: write action requires confirmation before executing
|
||||
- [ ] Forbidden action blocklist verified: push main/develop, production deploy, schema migration, direct DB write → rejected
|
||||
- [ ] Branch protection + Gitea token scope verified: hermes-bot cannot push to main/develop
|
||||
- [ ] `hermes_operations_log` records token identity, target repo/branch for all write actions
|
||||
|
||||
✅ **Gate passed** → advance to Stage 5
|
||||
|
||||
---
|
||||
|
||||
## Stage 5 — Developer AI Proxy (Architecture + Security approval)
|
||||
|
||||
```powershell
|
||||
# บน Windows PowerShell — ทดสอบ hermes proxy
|
||||
$env:OPENAI_BASE_URL = "http://<ASUSTOR_IP>:8766/v1"
|
||||
$env:OPENAI_API_KEY = "<HERMES_PROXY_API_KEY>"
|
||||
|
||||
# ทดสอบ basic coding request (no production data)
|
||||
codex "scaffold NestJS module for health check"
|
||||
# ต้องได้ response พร้อม DMS context
|
||||
|
||||
# ทดสอบ secret payload rejection
|
||||
# ส่ง payload ที่มี "password: secret123" หรือ storage path
|
||||
# ต้องได้ rejected + redact ใน log
|
||||
```
|
||||
|
||||
Verification gate:
|
||||
- [ ] Proxy LAN/VPN-only: port 8766 ไม่ accessible จาก public internet
|
||||
- [ ] No secrets/document payload: test payload ที่มี token/password/storage path ถูก reject และ redact ใน log
|
||||
- [ ] Proxy ไม่ wired เข้า DMS AI runtime หรือ DMS document intelligence path
|
||||
- [ ] Wrong API key → 401
|
||||
|
||||
✅ **All stages complete** → Hermes fully operational
|
||||
|
||||
---
|
||||
|
||||
## Rollback Procedures
|
||||
|
||||
| Stage | Rollback |
|
||||
|-------|---------|
|
||||
| Stage 1 | `docker compose -f docker-compose.hermes.yml down`; verify DMS production unaffected |
|
||||
| Stage 2 | Revoke DB/Gitea read-only credentials via Gitea admin; disable MCP servers; confirm no storage mount |
|
||||
| Stage 3 | `curl -X DELETE "https://api.telegram.org/bot{TOKEN}/deleteWebhook"`; revoke bot token if needed |
|
||||
| Stage 4 | Revoke Gitea write token via Gitea admin; disable write commands in Hermes config |
|
||||
| Stage 5 | Unset `OPENAI_BASE_URL` on all clients; stop hermes proxy; revoke proxy API key |
|
||||
|
||||
---
|
||||
|
||||
## Health Check Endpoints
|
||||
|
||||
```bash
|
||||
# Hermes health (Stage 1+)
|
||||
curl http://<ASUSTOR_IP>:8080/api/v1/health
|
||||
|
||||
# hermes proxy health (Stage 5)
|
||||
curl http://<ASUSTOR_IP>:8766/v1/models
|
||||
|
||||
# Dev Qdrant health (if deployed)
|
||||
curl http://<ASUSTOR_IP>:6334/healthz
|
||||
```
|
||||
@@ -0,0 +1,103 @@
|
||||
// File: specs/200-fullstacks/231-hermes-agent/research.md
|
||||
// Change Log:
|
||||
// - 2026-05-29: Phase 0 research — all unknowns resolved from ADR-031 v2.0
|
||||
|
||||
# Research: Hermes Agent
|
||||
|
||||
**Feature**: 231-hermes-agent | **Date**: 2026-05-29
|
||||
|
||||
---
|
||||
|
||||
## R-001: Hermes Stack / Runtime
|
||||
|
||||
**Decision**: NestJS (TypeScript) บน Node.js 22 — เช่นเดียวกับ DMS backend เพื่อ reuse tooling, tsconfig, ESLint, Jest
|
||||
**Rationale**: ทีมรู้จัก NestJS ดีแล้ว; BullMQ ใช้ร่วม npm package ได้; TypeScript strict mode enforce ตาม AGENTS.md
|
||||
**Alternatives considered**:
|
||||
- Python FastAPI — reuse Ollama/ML code แต่ทีมหลักเป็น TypeScript/NestJS
|
||||
- Go — performance ดีกว่าแต่ไม่มี BullMQ native และทีมไม่คุ้นเคย
|
||||
|
||||
---
|
||||
|
||||
## R-002: Cloud AI Provider & Model Selection
|
||||
|
||||
**Decision**: Claude Sonnet (orchestration) / Claude Haiku (sub-agents) เป็น primary; GPT-4o / GPT-4o-mini เป็น fallback
|
||||
**Rationale**: ADR-031 v2.0 Locked Decision — Cloud AI Exception สำหรับ dev orchestration layer โดยเฉพาะ; ใช้ model ขนาดเล็กกว่าสำหรับ sub-agents เพื่อลด cost
|
||||
**Alternatives considered**:
|
||||
- Ollama only (Gemma4/gemma2) — ไม่ได้รับ exception จาก ADR-023A สำหรับ dev orchestration; context window จำกัด; ไม่เหมาะกับ orchestration workload ขนาดใหญ่
|
||||
- GPT-4o only — ราคาสูงกว่าถ้าใช้ทุก request
|
||||
|
||||
---
|
||||
|
||||
## R-003: Dev Qdrant Isolation
|
||||
|
||||
**Decision**: Separate Qdrant instance บน ASUSTOR port 6334 (container: `hermes-qdrant`); collection `lcbp3_code_chunks` indexed by `repoName` + `moduleName`
|
||||
**Rationale**: ADR-031 v2.0 Locked — ห้ามใช้ Qdrant instance เดียวกับ DMS document RAG (port 6333 บน QNAP ADR-023A); separation ป้องกัน cross-contamination
|
||||
**Alternatives considered**:
|
||||
- Shared DMS Qdrant — ปฏิเสธ: ADR-031 v2.0 explicit lock; DMS Qdrant ใช้ `projectPublicId` filter สำหรับ document isolation ซึ่งไม่เหมาะกับ code chunks
|
||||
|
||||
---
|
||||
|
||||
## R-004: BullMQ Queue Architecture
|
||||
|
||||
**Decision**: `hermes-notification-queue` เป็น queue หลักสำหรับ outbound Telegram; `hermes-orchestration-queue` สำหรับ async dev tasks; ใช้ Redis instance แยก (`hermes-redis` container)
|
||||
**Rationale**: ADR-031 Redis Isolation Policy — ห้ามใช้ DMS production Redis (อาจ evict DMS BullMQ/lock/cache keys ถ้าใช้ `allkeys-lru`); queue names ขึ้นต้น `hermes-`
|
||||
**Alternatives considered**:
|
||||
- Shared DMS Redis — ปฏิเสธ: ADR-031 explicit policy; ถ้าจำเป็นต้องแชร์ต้องมี keyPrefix แยก, DB index แยก, ACL user แยก
|
||||
|
||||
---
|
||||
|
||||
## R-005: hermes_operations_log Storage
|
||||
|
||||
**Decision**: SQLite database ภายใน Hermes container volume (`/volume1/docker/hermes/data/ops.db`) — เริ่มต้นง่าย, ไม่ต้อง external service, เพียงพอสำหรับ DevOps audit trail
|
||||
**Rationale**: ADR-031 — ต้องอยู่ใน Hermes-owned storage เท่านั้น; ไม่ใช่ DMS `audit_logs`; single-operator DevOps tool ไม่ต้องการ high-concurrency DB
|
||||
**Alternatives considered**:
|
||||
- Postgres volume ภายใน Hermes stack — option ถ้า ops volume เติบโต แต่ SQLite เพียงพอสำหรับ Stage 1-4
|
||||
- Structured log files + ship to log collector — viable แต่ SQLite ง่ายกว่าสำหรับ query ด้วย `/status <transactionId>`
|
||||
|
||||
---
|
||||
|
||||
## R-006: SOUL.md เป็น Session Memory
|
||||
|
||||
**Decision**: Plain Markdown file ภายใน container volume `/volume1/docker/hermes/SOUL.md`; Hermes อ่านต้น session และ append per-session entry; rotate ทุก 30 วัน
|
||||
**Rationale**: ADR-031 v2.0 Locked — ไม่ sync ลง repo ทุกกรณี; container-local เท่านั้น; ไม่ใช้ Obsidian หรือ external knowledge base
|
||||
**Alternatives considered**:
|
||||
- Redis-based session memory — volatile และ restart ทำให้ข้อมูลหาย
|
||||
- Gitea wiki/issue — sync ลง repo ซึ่งขัดกับ ADR-031 locked decision
|
||||
|
||||
---
|
||||
|
||||
## R-007: Telegram Webhook Security
|
||||
|
||||
**Decision**: Verify `X-Telegram-Bot-Api-Secret-Token` header ทุก request; enforce allowlist (`HERMES_TELEGRAM_ALLOWED_USER_IDS`); Redis-based rate limit 10 req/min/user; expose webhook เฉพาะ LAN หรือผ่าน reverse proxy ที่มี TLS + Telegram secret verification
|
||||
**Rationale**: ป้องกัน spoofed requests; ป้องกัน unauthorized DevOps access; ป้องกัน spam/DoS ตาม ADR-031 security requirements
|
||||
**Alternatives considered**:
|
||||
- IP allowlist only — ไม่เพียงพอถ้า Telegram ใช้ dynamic IPs
|
||||
- No rate limiting — risk ของ spam/DoS จาก compromised Telegram account
|
||||
|
||||
---
|
||||
|
||||
## R-008: Git Identity & PR Flow
|
||||
|
||||
**Decision**: `hermes-bot` Gitea service account (least privilege); write token scope: create branch/issue/PR/trigger CI เท่านั้น (ไม่ใช่ admin token); branch pattern `hermes/{feat,fix,refactor}-*`; ห้าม push main/develop; ต้องผ่าน CI ก่อน merge; human approve required
|
||||
**Rationale**: ADR-031 v2.0 Locked — ทุก change ผ่าน PR ที่ human review เท่านั้น; ป้องกัน accidental direct push to protected branches
|
||||
**Alternatives considered**:
|
||||
- Hermes push ตรง develop — ปฏิเสธ: ADR-031 explicit lock; repo gate compliance
|
||||
- Admin token — ปฏิเสธ: ADR-031 explicit prohibition; least privilege principle
|
||||
|
||||
---
|
||||
|
||||
## R-009: Resource Limits บน ASUSTOR (non-Swarm Docker)
|
||||
|
||||
**Decision**: กำหนด fallback resource limits ทั้งใน `deploy.resources` (Swarm syntax) และ top-level `cpus`/`mem_limit` (non-Swarm syntax) เพื่อให้ enforce บน ASUSTOR ADM Docker; verify ด้วย `docker inspect` และ `docker stats`
|
||||
**Rationale**: ADR-031 note — `deploy.resources` อาจถูก ignore ใน non-Swarm Docker บน ASUSTOR; ต้อง verify จาก runtime ไม่ใช่ compose file เท่านั้น
|
||||
**Alternatives considered**:
|
||||
- Swarm mode บน ASUSTOR — ไม่จำเป็นสำหรับ single-node DevOps tool; เพิ่ม complexity โดยไม่จำเป็น
|
||||
|
||||
---
|
||||
|
||||
## R-010: Context Loading Strategy (Selective Context)
|
||||
|
||||
**Decision**: Hermes โหลด context แบบ selective ตาม task type เพื่อลด token ที่ส่งไป Cloud AI: DevOps task → CONTEXT-ADR-031+AGENTS.md; DMS feature coding → +CONTEXT.md; Schema/DB → +schema SQL (read-only); Bug fix → +Dev Qdrant search results
|
||||
**Rationale**: ADR-031 v2.0 — ลด cost ของ Cloud AI; ป้องกันส่ง production DB query results เข้า Cloud AI context (Data Classification Policy)
|
||||
**Alternatives considered**:
|
||||
- โหลด CONTEXT.md ทุก request — เพิ่ม token cost; ไม่จำเป็นสำหรับ pure DevOps queries
|
||||
@@ -0,0 +1,220 @@
|
||||
// File: specs/200-fullstacks/231-hermes-agent/spec.md
|
||||
// Change Log:
|
||||
// - 2026-05-29: Initial specification derived from ADR-031 v2.0
|
||||
|
||||
# Feature Specification: Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge
|
||||
|
||||
**Feature Branch**: `231-hermes-agent`
|
||||
**Created**: 2026-05-29
|
||||
**Status**: Draft
|
||||
**Category**: 200-fullstacks
|
||||
**Input**: ADR-031 v2.0 (specs/06-Decision-Records/ADR-031-hermes-agent-telegram-devops-bridge.md)
|
||||
|
||||
## Overview
|
||||
|
||||
Hermes Agent เป็น Autonomous Development Loop Orchestrator และ Telegram DevOps Bridge ที่รันบน ASUSTOR NAS แบบ always-on โดยทำหน้าที่ 2 roles หลัก:
|
||||
|
||||
1. **Autonomous Dev Orchestrator** (primary) — รับ coding task จาก Developer ผ่าน Telegram/CLI, โหลด context, วางแผน, จ่ายงานให้ sub-agents (Cloud AI), รัน self-correction loop (lint/tsc/test), และสร้าง PR ใน Gitea สำหรับ human review
|
||||
2. **Telegram DevOps Bridge** (subsystem) — รับ DevOps commands ผ่าน Telegram bot สำหรับ read-only queries (CI status, repo summary) และ write-with-confirmation actions (create branch/issue/PR/trigger CI)
|
||||
|
||||
Hermes **ไม่ใช่** production DMS service, ไม่ใช่ DMS AI inference boundary, และไม่แตะ production DMS schema ทุกกรณี
|
||||
|
||||
---
|
||||
|
||||
## Clarifications
|
||||
|
||||
### Session 2026-05-29
|
||||
|
||||
Ambiguity scan ran across all 10 taxonomy categories. All categories scored **Clear** — ADR-031 v2.0 Locked Decisions (grill-with-docs 2026-05-29) pre-resolve every design choice that would otherwise require clarification:
|
||||
|
||||
- Q: Cloud AI scope (which AI services allowed for Hermes?) → A: Claude/GPT-4o for orchestration + Haiku/GPT-4o-mini for sub-agents; DMS document processing remains ADR-023A Ollama-only (Cloud AI Exception, ADR-031 v2.0 Locked)
|
||||
- Q: Dev Qdrant isolation (shared with DMS Qdrant?) → A: Separate instance on ASUSTOR port 6334, collection `lcbp3_code_chunks` indexed by `repoName`+`moduleName` — never shared with DMS Qdrant port 6333 (ADR-031 v2.0 Locked)
|
||||
- Q: SOUL.md persistence (repo vs. container?) → A: Container volume only (`/volume1/docker/hermes/SOUL.md`), never synced to repo, rotated every 30 days (ADR-031 v2.0 Locked)
|
||||
- Q: hermes proxy port (conflict with PaddleOCR?) → A: Port 8766 for hermes proxy; port 8765 is reserved for PaddleOCR sidecar per ADR-023A (ADR-031 v1.1.1 fix)
|
||||
- Q: hermes_operations_log location (DMS audit_logs?) → A: Hermes-owned store only (SQLite/Postgres volume or structured log), never writes to DMS `audit_logs` (ADR-031 v2.0 Locked)
|
||||
|
||||
**Coverage Summary**: Functional Scope ✅ | Domain & Data Model ✅ | Interaction & UX ✅ | Non-Functional ✅ | Integration ✅ | Edge Cases ✅ | Constraints ✅ | Terminology ✅ | Completion Signals ✅
|
||||
|
||||
No questions asked. Proceeding directly to `/speckit-plan`.
|
||||
|
||||
---
|
||||
|
||||
## User Scenarios & Testing _(mandatory)_
|
||||
|
||||
### User Story 1 — Autonomous Coding Task Orchestration (Priority: P1)
|
||||
|
||||
Developer ส่ง coding task เช่น "scaffold NestJS module for X" ผ่าน Telegram หรือ CLI แล้ว Hermes โหลด project context, วางแผน, แตกงาน, delegate ไปยัง sub-agents, รัน lint/tsc/test self-correction loop, และสร้าง PR ใน Gitea branch `hermes/feat-*` สำหรับ Developer review/approve
|
||||
|
||||
**Why this priority**: เป็น core value ของ Hermes — ช่วยให้ Developer สั่งงาน coding จากที่ไหนก็ได้โดยไม่ต้องเปิด IDE และได้รับ PR ที่พร้อม review ภายในเวลาอันสั้น
|
||||
|
||||
**Independent Test**: Developer ส่ง Telegram message "scaffold NestJS module for repository diagnostics" → Hermes ส่งกลับ PR link ใน Gitea branch `hermes/feat-*` ที่ผ่าน lint/tsc
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Developer อยู่ใน Telegram allowlist, **When** ส่ง coding task, **Then** Hermes โหลด context ที่เหมาะกับ task type (selective loading), วางแผน, delegate sub-agent, รัน lint/tsc/test
|
||||
2. **Given** sub-agent ส่งโค้ดที่ lint ล้มเหลว, **When** Hermes รัน self-correction, **Then** ส่งกลับไปให้ sub-agent แก้ไขสูงสุด 3 iterations ก่อนหยุดและแจ้ง Developer
|
||||
3. **Given** โค้ดผ่าน lint/tsc/test ทุก check, **When** Hermes push, **Then** commit ลง `hermes/feat-{task-id}` branch โดย `hermes-bot` service account แล้วสร้าง PR พร้อม assign to Developer
|
||||
4. **Given** Hermes ต้องการ code patterns จาก codebase, **When** ค้นหา, **Then** ใช้ Dev Qdrant (ASUSTOR) ที่แยกจาก DMS Qdrant เท่านั้น
|
||||
5. **Given** task เสร็จสิ้น, **When** Hermes บันทึก session, **Then** เขียนลง SOUL.md ภายใน container เท่านั้น (ไม่ sync ลง repo)
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 — Telegram Read-only DevOps Commands (Priority: P2)
|
||||
|
||||
DevOps engineer/Developer ส่ง read-only commands ผ่าน Telegram เช่น `/ci_status`, `/repo_summary`, `/status`, `/audit_summary` และรับผลลัพธ์กลับมาทันทีโดยไม่มีผลข้างเคียงต่อระบบ
|
||||
|
||||
**Why this priority**: ช่วยให้ทีมตรวจสอบสถานะ CI/repo จากมือถือโดยไม่ต้องเปิด Gitea UI — ลด context switching และเพิ่ม DevOps visibility
|
||||
|
||||
**Independent Test**: ส่ง `/ci_status` ใน Telegram → รับสถานะ CI ล่าสุดจาก Gitea กลับมาภายใน 10 วินาที พร้อม reference transactionId
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Telegram user อยู่ใน allowlist, **When** ส่ง `/ci_status`, **Then** Hermes ดึงสถานะ CI ล่าสุดจาก Gitea แล้วตอบกลับพร้อม `[Ref: {transactionId}]`
|
||||
2. **Given** Telegram user ไม่อยู่ใน allowlist, **When** ส่ง command ใดก็ตาม, **Then** Hermes ปฏิเสธ request และไม่ดำเนินการใดๆ
|
||||
3. **Given** Telegram webhook request เข้ามา, **When** ตรวจสอบ `X-Telegram-Bot-Api-Secret-Token` ไม่ตรง, **Then** reject request ทันที
|
||||
4. **Given** Telegram user ส่ง request เกิน rate limit (>10 ต่อนาที), **When** Hermes ตรวจสอบ Redis counter, **Then** ปฏิเสธ request และแจ้ง user
|
||||
5. **Given** command ทุกประเภท, **When** รับ/ส่งข้อมูล, **Then** บันทึก inbound/outbound ใน `hermes_operations_log` พร้อม transactionId ทันที
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 — Telegram Write-with-Confirmation DevOps Actions (Priority: P3)
|
||||
|
||||
DevOps engineer ส่ง action commands ผ่าน Telegram เช่น "เตรียม branch/PR proposal สำหรับ fix/ci-pnpm-cache" — Hermes ขอ explicit confirmation ก่อนดำเนินการ และบันทึก transactionId ทุกขั้นตอน
|
||||
|
||||
**Why this priority**: ช่วยให้ทีมสั่งงาน DevOps actions จากมือถือได้อย่างปลอดภัยด้วย human confirmation gate ป้องกัน accidental changes
|
||||
|
||||
**Independent Test**: ส่ง "สร้าง branch proposal สำหรับ fix/ci-cache" → Hermes แสดง summary + ขอ confirmation → ยืนยัน → Hermes สร้าง branch ใน Gitea + บันทึก hermes_operations_log + แจ้ง PR created
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Developer ส่ง write action command, **When** Hermes รับ, **Then** แสดง action summary และขอ explicit confirmation ก่อนดำเนินการ
|
||||
2. **Given** Developer ยืนยัน action, **When** Hermes ดำเนิน, **Then** ใช้ Gitea write token ที่แยกและมี scope แคบ (ไม่ใช่ admin token) สำหรับ create branch/issue/PR/trigger CI เท่านั้น
|
||||
3. **Given** action สำเร็จหรือล้มเหลว, **When** สิ้นสุด, **Then** บันทึก `transactionId`, token identity, target repo/branch, และผลลัพธ์ใน `hermes_operations_log`
|
||||
4. **Given** command ที่เป็น forbidden action (push main/develop, production deploy, schema migration, destructive ops, direct DB write), **When** รับ command ดังกล่าว, **Then** Hermes ปฏิเสธทุกกรณี ไม่ว่าจะผ่าน confirmation หรือไม่
|
||||
5. **Given** Developer ยืนยัน create branch, **When** สร้างสำเร็จ, **Then** branch pattern ต้องเป็น `hermes/feat-*`, `hermes/fix-*`, หรือ `hermes/refactor-*` เท่านั้น
|
||||
|
||||
---
|
||||
|
||||
### User Story 4 — Developer AI Proxy (hermes proxy) (Priority: P4)
|
||||
|
||||
Developer บน laptop ใช้ Codex CLI หรือ agy โดยชี้ `OPENAI_BASE_URL` ไปยัง `hermes proxy` (port 8766 บน ASUSTOR) เพื่อใช้ Hermes เป็น Developer AI Proxy สำหรับ coding/devops assistance เท่านั้น
|
||||
|
||||
**Why this priority**: ช่วยให้ CLI tools บน laptop (Codex, agy via MCP) เชื่อมกับ Hermes context บน ASUSTOR ได้ โดยใช้ infrastructure ที่มีอยู่แล้ว
|
||||
|
||||
**Independent Test**: บน Windows PowerShell ตั้ง `$env:OPENAI_BASE_URL = "http://<ASUSTOR_IP>:8766/v1"` → รัน `codex "scaffold NestJS module"` → ได้รับ response ที่มี DMS context
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Developer ตั้ง OPENAI_BASE_URL ชี้ไป hermes proxy, **When** ส่ง coding/devops request, **Then** hermes proxy รับและ forward ไป Cloud AI พร้อม DMS context
|
||||
2. **Given** proxy รับ payload ที่คล้าย production document content, secret, token, password, หรือ storage path, **When** ตรวจพบ, **Then** ถือเป็น security incident, redact log ทันที, และ reject request
|
||||
3. **Given** hermes proxy ใช้ port 8766, **When** deploy, **Then** ต้องไม่ conflict กับ PaddleOCR sidecar (port 8765) ตาม ADR-023A
|
||||
4. **Given** hermes proxy รับ request ใดก็ตาม, **When** ประมวลผล, **Then** expose เฉพาะ LAN/VPN เท่านั้น ห้ามเปิด public internet
|
||||
5. **Given** Developer ใช้ agy กับ Hermes MCP, **When** เรียก `mcp_hermes-memory_recall`, **Then** Hermes ส่ง DMS context กลับมาโดยไม่มี production document payload หรือ DB query results
|
||||
|
||||
---
|
||||
|
||||
### User Story 5 — Staged Rollout & Health Monitoring (Priority: P5)
|
||||
|
||||
Admin deploy Hermes ผ่าน staged rollout (Stage 0-5) โดยแต่ละ stage มี acceptance gate ที่ต้องผ่านก่อนขึ้น stage ถัดไป และมี monitoring ที่แยก Hermes health ออกจาก DMS production health
|
||||
|
||||
**Why this priority**: รับประกันว่า Hermes ถูก deploy อย่างปลอดภัยแบบ incremental และการล่มของ Hermes ไม่ส่งผลกระทบต่อ DMS production ทุกกรณี
|
||||
|
||||
**Independent Test**: ปิด Hermes container แล้วตรวจสอบว่า DMS frontend/backend/Workflow Engine/AI pipeline ยังทำงานปกติ 100%
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Admin ต้องการ deploy Hermes, **When** เริ่ม Stage 1, **Then** Hermes container รันแบบ LAN/VPN-only ด้วย Redis/log store แยกจาก DMS production Redis
|
||||
2. **Given** Stage acceptance gate ยังไม่ผ่าน, **When** Admin พยายาม deploy Stage ถัดไป, **Then** ระบบหรือ process บล็อกไว้จน gate ผ่าน
|
||||
3. **Given** Hermes container ล่ม, **When** ตรวจสอบ DMS production, **Then** DMS frontend/backend/Workflow Engine/AI pipeline ทำงานตามปกติ 100% (failure isolation)
|
||||
4. **Given** Hermes down หรือ Telegram Bridge down, **When** Monitoring แจ้งเตือน, **Then** alert เป็น DevOps warning ไม่ใช่ production DMS outage alert
|
||||
5. **Given** resource limits กำหนดไว้ใน Docker Compose (CPU 2.0, RAM 4GB limit / 2GB reservation), **When** deploy บน ASUSTOR, **Then** verified ด้วย `docker inspect` และ `docker stats` ว่า runtime enforce จริง
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- Hermes sub-agent ล้มเหลวหลัง 3 iterations — หยุดงานและแจ้ง Developer ผ่าน Telegram พร้อม error detail; ไม่สร้าง PR ที่มีโค้ดผิด
|
||||
- SOUL.md ขนาดใหญ่เกินไปหลัง 30 วัน — Rotate/clear ตาม schedule; Hermes resume context จาก SOUL.md ต้น session
|
||||
- hermes-bot ถูก revoke token — ทุก write action ล้มเหลว gracefully พร้อมแจ้ง Developer; read-only commands ยังใช้ token แยกได้
|
||||
- ASUSTOR restart — Hermes Redis (AOF persistence) recover queue jobs; SOUL.md อยู่ใน container volume ปลอดภัย
|
||||
- Telegram API ล่ม — BullMQ retry 3 ครั้งด้วย exponential backoff ก่อน dead-letter
|
||||
- Developer ส่ง secret/token จริงผ่าน Telegram command — Hermes redact ออกจาก log ทันที ไม่ forward ไป Cloud AI
|
||||
- Dev Qdrant (ASUSTOR) ล่ม — Hermes fallback ไป context-only mode (ไม่มี semantic search) โดย DMS Qdrant ไม่ถูกแตะ
|
||||
- hermes proxy รับ production document payload — Security incident: redact, reject, alert
|
||||
- inter-VLAN routing ยังไม่เปิด (ASUSTOR → QNAP) — Stage 2+ ไม่สามารถ deploy ได้; Hermes แสดง error ชัดเจนว่า network path blocked
|
||||
- hermes-bot พยายาม push ตรง main/develop — Git server-side branch protection block ทุกกรณี
|
||||
|
||||
---
|
||||
|
||||
## Requirements _(mandatory)_
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: Hermes MUST run as an isolated Docker container on ASUSTOR NAS (CPU ≤ 2 cores, RAM ≤ 4GB) within LAN/VPN boundary เท่านั้น
|
||||
- **FR-002**: Hermes MUST implement Autonomous Dev Orchestration loop: load selective context → plan → delegate to Cloud sub-agents → self-correction (lint/tsc/test, max 3 iterations) → commit via hermes-bot → create PR
|
||||
- **FR-003**: Hermes MUST use Cloud AI (Claude/GPT-4o for orchestration, Claude Haiku/GPT-4o-mini for sub-agents) เฉพาะ dev orchestration layer — ไม่ใช่ DMS document processing
|
||||
- **FR-004**: Data Classification Policy MUST be enforced: Code/Config/ADR/Stack trace ส่ง Cloud AI ได้ — Production runtime data (document content, user info, project business data จาก DB) ห้ามส่งออกทุกกรณี
|
||||
- **FR-005**: Hermes MUST maintain a separate Dev Qdrant instance on ASUSTOR (collection: `lcbp3_code_chunks`, indexed by `repoName`+`moduleName`) ห้ามใช้ DMS Qdrant instance
|
||||
- **FR-006**: Hermes MUST maintain SOUL.md working journal ภายใน container volume เท่านั้น (ไม่ sync ลง repo, rotate ทุก 30 วัน)
|
||||
- **FR-007**: Hermes MUST load selective context ตาม task type: DevOps → CONTEXT-ADR-031+AGENTS.md; DMS feature → +CONTEXT.md; Schema/DB → +schema SQL; Bug fix → +Dev Qdrant
|
||||
- **FR-008**: Hermes MUST enforce Git Identity rules: ใช้ `hermes-bot` service account, push เฉพาะ `hermes/*` branches, ห้าม push main/develop/release ทุกกรณี, ทุก change ต้องผ่าน PR ที่ human approve
|
||||
- **FR-009**: Hermes Telegram MUST verify `X-Telegram-Bot-Api-Secret-Token` ทุก webhook request
|
||||
- **FR-010**: Hermes Telegram MUST enforce allowlist (`HERMES_TELEGRAM_ALLOWED_USER_IDS`) สำหรับ DevOps commands ทุกระดับ
|
||||
- **FR-011**: Hermes Telegram MUST apply Redis-based rate limiting (default: 10 requests/minute/user)
|
||||
- **FR-012**: Hermes MUST queue all outbound Telegram notifications ผ่าน BullMQ queue `hermes-notification-queue` พร้อม retry 3 ครั้ง exponential backoff
|
||||
- **FR-013**: Hermes MUST record every inbound/outbound operation ใน `hermes_operations_log` ด้วย transactionId (UUIDv7), operator identity, command type, target system, status, timestamps — ห้ามเขียนลง DMS `audit_logs`
|
||||
- **FR-014**: Hermes operations log MUST redact command payload ที่อาจมี secret, token, sensitive file path, หรือ production document content
|
||||
- **FR-015**: Hermes MUST implement 6-stage gated rollout (Stage 0–5) โดยห้ามข้ามไปยัง stage ที่สูงกว่าโดยยังไม่ผ่าน acceptance gate
|
||||
- **FR-016**: Hermes failure MUST NOT affect DMS production: frontend, backend, Workflow Engine, AI pipeline, and user-facing app ต้องทำงานตามปกติเมื่อ Hermes ล่ม
|
||||
- **FR-017**: Hermes MUST NOT add or modify any DMS production schema (no SQL delta, no migration, no `user_telegram_mapping` creation)
|
||||
- **FR-018**: `hermes proxy` MUST expose OpenAI-compatible API (port 8766) สำหรับ Developer AI Proxy เท่านั้น (ห้ามใช้ port 8765 ที่ PaddleOCR sidecar ใช้อยู่)
|
||||
- **FR-019**: Hermes MUST use separate Redis instance/volume จาก DMS production Redis; queue names ต้องขึ้นต้นด้วย `hermes-`
|
||||
- **FR-020**: All secrets (Telegram bot token, webhook secret, Gitea token, DB credential, proxy API key) MUST be stored ภายนอก repo ใน ASUSTOR secret store พร้อม rotation plan
|
||||
|
||||
### Key Entities
|
||||
|
||||
- **HermesAgent**: Docker container orchestrator รันบน ASUSTOR ควบคุม Development Loop ทั้งหมด
|
||||
- **HermesTelegramGateway**: รับ inbound Telegram webhook, ตรวจสอบ allowlist + webhook secret + rate limit, forward ไปยัง DevOps Command Router
|
||||
- **HermesTelegramDispatcher**: BullMQ Worker ดึงงานจาก `hermes-notification-queue` เพื่อส่ง outbound Telegram message พร้อม transactionId reference
|
||||
- **HermesDevOpsCommandRouter**: Route และ execute DevOps commands ตาม permission tier (read-only / write-with-confirmation / forbidden)
|
||||
- **HermesOperationsLog**: Hermes-owned log store (SQLite หรือ structured log) บันทึก inbound/outbound DevOps operations พร้อม transactionId และ redacted payload
|
||||
- **HermesSubAgent**: Cloud AI delegate (Claude Haiku / GPT-4o-mini) รับ code generation task จาก Orchestrator และส่ง code diff กลับ
|
||||
- **SOUL.md**: Container-local working journal บันทึก per-session task context, delegated sub-agents, iterations, PR results
|
||||
- **DevQdrant**: Qdrant instance บน ASUSTOR (port 6334) สำหรับ codebase embeddings เท่านั้น — collection `lcbp3_code_chunks`
|
||||
- **HermesProxy**: OpenAI-compatible API proxy (port 8766) สำหรับ Codex CLI / agy MCP integration
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria _(mandatory)_
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: Developer สามารถรับ PR link จาก Hermes ภายใน 30 นาที สำหรับ typical feature scaffolding task (เมื่อ sub-agent ผ่าน lint/tsc ใน iteration แรก)
|
||||
- **SC-002**: Self-correction loop แก้ lint/tsc/test failures ได้ภายใน 3 iterations ≥ 80% ของกรณีก่อนที่จะ escalate ไป Developer
|
||||
- **SC-003**: Telegram read-only commands (`/ci_status`, `/repo_summary`, `/status`) ตอบกลับภายใน 10 วินาที ≥ 95% ของ requests
|
||||
- **SC-004**: DMS production availability (frontend/backend/Workflow Engine) ไม่ได้รับผลกระทบเมื่อ Hermes container ล่ม (0% downtime attributable to Hermes)
|
||||
- **SC-005**: 100% ของ Telegram requests จาก non-allowlisted users ถูก reject โดยไม่มีการดำเนินการใดๆ
|
||||
- **SC-006**: 100% ของ DevOps write actions มี transactionId บันทึกใน `hermes_operations_log` ก่อนดำเนิน action
|
||||
- **SC-007**: All 6 rollout stage acceptance gates ผ่าน verification ก่อน advance ไปยัง stage ถัดไป ไม่มีกรณี skip gate
|
||||
- **SC-008**: ไม่พบ production document content, DB query results, secrets, หรือ storage paths ใน Cloud AI request payloads (verified จาก proxy request logs)
|
||||
- **SC-009**: hermes-bot ไม่มี push access ไปยัง `main`, `develop`, หรือ `release/*` branches (verified โดย Gitea branch protection + token scope test)
|
||||
- **SC-010**: `hermes_operations_log` redacts ทุก payload ที่ตรวจพบ secret/token/sensitive-path ก่อนบันทึก (verified โดย secret scan ของ log output)
|
||||
|
||||
---
|
||||
|
||||
## Assumptions
|
||||
|
||||
- ADR-031 v2.0 Locked Decisions ทั้งหมดใช้บังคับและไม่อยู่ในขอบเขตที่เปลี่ยนได้โดย spec นี้
|
||||
- Cloud AI exception (Claude/GPT-4o) สำหรับ Hermes dev orchestration layer ได้รับการอนุมัติแล้วใน ADR-031 v2.0
|
||||
- ASUSTOR NAS มี Docker รองรับ resource limits (cpus/mem_limit); verified ด้วย `docker inspect`/`docker stats` ตาม ADR note
|
||||
- Gitea `hermes-bot` service account และ Telegram bot ต้องถูกสร้างแยกต่างหากก่อน Stage 1/3
|
||||
- inter-VLAN routing จาก ASUSTOR ไปยัง QNAP (MariaDB :3306, Gitea :3000) ต้องเปิดก่อน Stage 2
|
||||
- DMS production Qdrant (ADR-023A, port 6333) และ Dev Qdrant (Hermes, port 6334) เป็นคนละ instance
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Production DMS Telegram commands (query/mutate documents, Workflow Engine actions) — ต้องเป็น ADR/spec แยก
|
||||
- `user_telegram_mapping` table สำหรับ DMS — ห้ามสร้างใน ADR-031 rollout
|
||||
- DMS production schema changes ทุกกรณี
|
||||
- Direct integration ระหว่าง Hermes และ DMS BullMQ/Redis/Qdrant/Ollama
|
||||
- Hermes เป็น DMS AI runtime path (ใช้ DMS Ollama pipeline ตาม ADR-023/023A)
|
||||
@@ -0,0 +1,274 @@
|
||||
// File: specs/200-fullstacks/231-hermes-agent/tasks.md
|
||||
// Change Log:
|
||||
// - 2026-05-29: Initial task list for Hermes Agent (ADR-031 v2.0)
|
||||
|
||||
# Tasks: Hermes Agent — Autonomous Dev Orchestrator & Telegram DevOps Bridge
|
||||
|
||||
**Input**: Design documents from `specs/200-fullstacks/231-hermes-agent/`
|
||||
**Prerequisites**: plan.md ✅ | spec.md ✅ | research.md ✅ | data-model.md ✅ | contracts/ ✅ | quickstart.md ✅
|
||||
|
||||
**Organization**: Tasks grouped by user story (US1–US5) for independent implementation and testing
|
||||
**Staged Rollout**: US5 tasks map to Stage gates — do not skip stages
|
||||
|
||||
---
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
- **[P]**: Can run in parallel (different files, no dependencies on incomplete tasks)
|
||||
- **[Story]**: Which user story this task belongs to (US1–US5)
|
||||
- Paths below are relative to `hermes/` monorepo package root (standalone NestJS project)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Setup (Hermes Project Initialization)
|
||||
|
||||
**Purpose**: Bootstrap `hermes/` project structure and Docker infrastructure
|
||||
|
||||
- [ ] T001 Create `hermes/` NestJS project: `package.json`, `tsconfig.json`, `nest-cli.json`, `.env.example` with TypeScript strict mode and all dependencies from plan.md
|
||||
- [ ] T002 [P] Create `hermes/Dockerfile` — multi-stage Node.js 22 Alpine build for ASUSTOR deployment
|
||||
- [ ] T003 [P] Create `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/docker-compose.hermes.yml` — hermes-agent container with CPU 2.0 / mem 4096M limits (fallback + deploy.resources per ADR-031 note)
|
||||
- [ ] T004 [P] Create `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/docker-compose.hermes-redis.yml` — hermes-redis container with `hermes.redis.conf` (AOF persistence, maxmemory 512mb, isolated from DMS Redis)
|
||||
- [ ] T005 [P] Create `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/docker-compose.hermes-qdrant.yml` — hermes-qdrant container on port 6334 (separated from DMS Qdrant port 6333)
|
||||
- [ ] T006 Create `hermes/src/config/hermes.config.ts` — typed env vars (all secrets via env; no hardcoded values; ห้าม commit secret จริง)
|
||||
- [ ] T007 Create `hermes/src/app.module.ts` — root module wiring all feature modules
|
||||
|
||||
**Checkpoint**: `docker compose -f docker-compose.hermes.yml up -d` รัน hermes container ได้; `docker inspect` แสดง resource limits ถูกต้อง
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Core Infrastructure — Blocks All User Stories)
|
||||
|
||||
**Purpose**: Cross-cutting concerns ทุก user story ต้องอาศัย
|
||||
|
||||
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
||||
|
||||
- [ ] T008 Create `hermes/src/common/utils/uuid.util.ts` — UUIDv7 generation ตาม ADR-019 (`generateTransactionId()` returns UUIDv7 string)
|
||||
- [ ] T009 [P] Create `hermes/src/common/utils/secret-redactor.util.ts` — scan command payload สำหรับ secret/token/password/storage-path patterns แล้ว redact ก่อน log (FR-014)
|
||||
- [ ] T010 [P] Create `hermes/src/common/guards/api-key.guard.ts` — validate `X-API-Key` header ต่อทุก non-webhook endpoint; return 401 ถ้าไม่ถูกต้อง
|
||||
- [ ] T011 [P] Create `hermes/src/common/interceptors/transaction.interceptor.ts` — auto-generate UUIDv7 transactionId ต่อทุก request และ attach ลง response headers + request context
|
||||
- [ ] T012 Create `hermes/src/operations/operations-log.service.ts` — SQLite CRUD สำหรับ `hermes_operations_log` (create entry, update status, find by transactionId); ใช้ `better-sqlite3`
|
||||
- [ ] T013 [P] Create `hermes/src/operations/operations.module.ts` และ `hermes/src/operations/operations.controller.ts` — GET `/operations/logs` + GET `/operations/logs/:transactionId` (ตาม contracts/hermes-api.yaml)
|
||||
- [ ] T014 Create `hermes/src/health/health.controller.ts` — GET `/health` returns `HermesStatus` with queue counts; no auth required (security: [])
|
||||
- [ ] T015 [P] Write unit tests `hermes/test/unit/secret-redactor.spec.ts` — test cases: token patterns, password= patterns, storage paths, ไม่ redact code snippets / ADR content
|
||||
|
||||
- [ ] T054 [P] Write unit tests `hermes/test/unit/operations-log.spec.ts` — test cases: create entry, update status, findByTransactionId, redaction enforcement, retention boundary
|
||||
|
||||
**Checkpoint**: API Key guard ทำงาน; Operations log บันทึก/query ได้; Secret redactor pass tests; Health endpoint ตอบกลับ
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 — Autonomous Dev Orchestrator (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Developer ส่ง coding task → Hermes orchestrate sub-agents → self-correction loop → PR created
|
||||
|
||||
**Independent Test**: POST `/orchestration/tasks` ด้วย `{description: "scaffold NestJS health module", taskType: "DMS_FEATURE", telegramChatId: "test"}` → GET `/orchestration/tasks/:id` แสดง `status: PR_CREATED` + `prUrl` populated ภายใน expected timeout
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [ ] T016 [P] [US1] Create `hermes/src/qdrant/dev-qdrant.service.ts` — Qdrant JS client สำหรับ Dev Qdrant (ASUSTOR port 6334); collection `lcbp3_code_chunks`; search by `repoName`+`moduleName` (ไม่ใช้ `projectPublicId` filter)
|
||||
- [ ] T017 [P] [US1] Create `hermes/src/orchestrator/context-loader.service.ts` — selective context loading ตาม task type (DEVOPS/DMS_FEATURE/SCHEMA_DB/BUG_FIX); โหลด CONTEXT-ADR-031.md + AGENTS.md เสมอ; เพิ่ม CONTEXT.md สำหรับ DMS_FEATURE; ห้าม load production DB query results
|
||||
- [ ] T018 [P] [US1] Create `hermes/src/orchestrator/sub-agent.service.ts` — Cloud AI delegation: Claude Haiku/GPT-4o-mini สำหรับ code generation; Data Classification enforcement (ห้าม production data ใน prompt payload)
|
||||
- [ ] T019 [US1] Create `hermes/src/orchestrator/self-correction.service.ts` — รัน lint/tsc/test ผ่าน MCP hermes-tools; วนซ้ำสูงสุด 3 iterations; ถ้า > 3 → escalate notification ผ่าน BullMQ (depends on T018)
|
||||
- [ ] T020 [US1] Create `hermes/src/orchestrator/soul.service.ts` — read/append/rotate SOUL.md ที่ `/volume1/docker/hermes/SOUL.md`; rotate ทุก 30 วัน; ไม่ sync ลง repo
|
||||
- [ ] T021 [US1] Create `hermes/src/orchestrator/orchestrator.service.ts` — main dev loop: context load → plan → sub-agent delegate → self-correction → commit via hermes-bot → create PR → record SOUL.md + operations log (depends on T016–T020)
|
||||
- [ ] T022 [US1] Create `hermes/src/orchestrator/orchestrator.controller.ts` — POST `/orchestration/tasks`, GET `/orchestration/tasks/:id` ตาม OpenAPI contract; ใช้ hermes-orchestration-queue (BullMQ)
|
||||
- [ ] T023 [US1] Create `hermes/src/orchestrator/orchestrator.module.ts` — wire all orchestrator providers
|
||||
- [ ] T024 [P] [US1] Write unit tests `hermes/test/unit/orchestrator.spec.ts` — test context loader (correct files per task type), sub-agent delegation call, self-correction loop iteration count enforcement
|
||||
|
||||
**Checkpoint**: POST orchestration task ได้รับ taskId; GET task แสดง status transitions; SOUL.md มี session entry; Dev Qdrant query ไม่แตะ DMS Qdrant
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 — Telegram Read-only DevOps Commands (Priority: P2)
|
||||
|
||||
**Goal**: DevOps engineer ส่ง `/ci_status`, `/repo_summary`, `/status` ผ่าน Telegram และรับผลลัพธ์กลับ ≤ 10 วินาที
|
||||
|
||||
**Independent Test**: ส่ง webhook payload `/ci_status` พร้อม valid secret token + allowlisted user → ตรวจสอบ operations log entry + Telegram outbound message queued + BullMQ job created
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [ ] T025 [P] [US2] Create `hermes/src/integrations/gitea/gitea.service.ts` — read-only Gitea API methods: getLatestCI(), getRepoSummary(), getIssues(), getPRs(); ใช้ read-only token; ห้าม write operations ใน phase นี้
|
||||
- [ ] T026 [P] [US2] Create `hermes/src/integrations/telegram/telegram-rate-limiter.service.ts` — Redis-based rate limit: `hermes:telegram:{userId}` key, incr + expire 60s, threshold 10 req/min (FR-011)
|
||||
- [ ] T027 [US2] Create `hermes/src/integrations/telegram/hermes-telegram-gateway.ts` — inbound webhook handler: verify `X-Telegram-Bot-Api-Secret-Token` → check allowlist → check rate limit → record inbound to operations log → dispatch to command router (depends on T025, T026)
|
||||
- [ ] T028 [US2] Create `hermes/src/integrations/telegram/hermes-devops-command-router.ts` — route read-only commands (/status, /ci_status, /repo_summary, /audit_summary, /help); queue outbound response via BullMQ hermes-notification-queue (depends on T027)
|
||||
- [ ] T029 [US2] Create `hermes/src/integrations/telegram/hermes-telegram-dispatcher.ts` — BullMQ Worker @Processor('hermes-notification-queue'): @Process('telegram-devops-outbound') — send via Telegram Bot API; record outbound to operations log; retry 3x exponential backoff (ADR-007, FR-012)
|
||||
- [ ] T030 [US2] Create `hermes/src/integrations/telegram/telegram.module.ts` — wire all telegram providers + BullMQ queue registration
|
||||
- [ ] T031 [P] [US2] Write unit tests `hermes/test/unit/telegram-gateway.spec.ts` — webhook secret verification, allowlist rejection, rate limit enforcement, operations log inbound record (depends on T027)
|
||||
- [ ] T032 [P] [US2] Write unit tests `hermes/test/unit/command-router.spec.ts` — command routing (/ prefix parsing), forbidden command detection, outbound job queuing (depends on T028)
|
||||
|
||||
**Checkpoint**: POST `/telegram/webhook` ด้วย wrong secret → 401; non-allowlisted user → rejected; valid read-only command → operations log entry + BullMQ job created
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 — Telegram Write-with-Confirmation (Priority: P3)
|
||||
|
||||
**Goal**: DevOps engineer สั่ง write action → Hermes ขอ confirmation → ดำเนิน action → บันทึก operations log
|
||||
|
||||
**Independent Test**: ส่ง "สร้าง branch proposal สำหรับ fix/test" → รับ confirmation prompt → ยืนยัน → Gitea branch `hermes/fix-test` ถูกสร้าง + operations log มี git write entry + forbidden action blocklist ทำงาน
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [ ] T033 [P] [US3] Extend `hermes/src/integrations/gitea/gitea.service.ts` — เพิ่ม write methods: createBranch(), createIssue(), createPR(), triggerCI() ใช้ write token แยก (least privilege, ไม่ใช่ admin token); branch pattern validation (hermes/*)
|
||||
- [ ] T034 [US3] Extend `hermes/src/integrations/telegram/hermes-devops-command-router.ts` — เพิ่ม write-with-confirmation flow: (1) parse write intent → (2) show action summary → (3) wait for explicit confirmation → (4) execute → (5) record operations log; forbidden action blocklist (push main/develop, production deploy, schema migration, direct DB write, storage delete) → reject immediately
|
||||
- [ ] T035 [US3] Integrate `hermes-bot` Git identity ใน `hermes/src/orchestrator/orchestrator.service.ts` — `simple-git` config: user.name "Hermes Bot", user.email "hermes-bot@np-dms.work"; push เฉพาะ `hermes/*` branches; commit message format: `"feat(hermes): {task description}\n\nOrchestrated by Hermes ADR-031 v2.0"`
|
||||
- [ ] T036 [P] [US3] Write operations log record ใน `hermes/src/operations/operations-log.service.ts` สำหรับ Git write actions — บันทึก `gitea_token_identity`, `target_repo`, `target_branch`, status ก่อนและหลัง action (depends on T033)
|
||||
|
||||
**Checkpoint**: Write command ต้องการ confirmation; hermes-bot branch creation ใช้ pattern `hermes/fix-*`; forbidden actions ถูก blocked; operations log มี token identity record
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: User Story 4 — Developer AI Proxy (Priority: P4)
|
||||
|
||||
**Goal**: Developer ใช้ Codex CLI / agy โดยชี้ `OPENAI_BASE_URL` → `hermes proxy` port 8766 รับ request สำหรับ coding/devops assistance เท่านั้น
|
||||
|
||||
**Independent Test**: ตั้ง OPENAI_BASE_URL → hermes proxy → ส่ง coding request → รับ response พร้อม DMS context; ส่ง payload ที่มี password/token → ถูก reject + redact log
|
||||
|
||||
### Implementation for User Story 4
|
||||
|
||||
- [ ] T037 [US4] Create `hermes/src/proxy/proxy.service.ts` — OpenAI-compatible API (port 8766); forward coding/devops requests ไป Cloud AI พร้อม DMS context injection; validate payload ไม่มี production data (ใช้ secret-redactor.util.ts); ห้าม forward ถ้าตรวจพบ production data
|
||||
- [ ] T038 [US4] Create `hermes/src/proxy/proxy.module.ts` + controller — bind ที่ port 8766 แยกจาก main API port 8080; API Key auth; LAN/VPN-only note ใน config
|
||||
- [ ] T039 [P] [US4] Create `hermes/src/integrations/mcp/mcp-server.service.ts` — expose `/mcp` endpoint สำหรับ agy + Windsurf integration; implement `hermes-memory` tool (recall DMS context); implement `hermes-tools` tool (bash/git execution on ASUSTOR)
|
||||
- [ ] T040 [P] [US4] Create `hermes/src/integrations/mcp/mcp.module.ts` — wire MCP server providers
|
||||
- [ ] T041 [P] [US4] Verify port isolation: proxy port 8766 ≠ PaddleOCR sidecar port 8765 (ADR-023A) — add port validation assertion ใน `hermes/src/config/hermes.config.ts` ที่ startup
|
||||
|
||||
**Checkpoint**: `curl http://<ASUSTOR_IP>:8766/v1/models` returns models list; payload ที่มี "password:" ถูก reject; `/mcp` endpoint accessible; port 8765 ไม่ถูก bind โดย Hermes
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: User Story 5 — Staged Rollout & Health Monitoring (Priority: P5)
|
||||
|
||||
**Goal**: Admin deploy Hermes ผ่าน 6-stage gated rollout พร้อม monitoring ที่แยก Hermes health จาก DMS
|
||||
|
||||
**Independent Test**: ปิด hermes container → ตรวจสอบ DMS frontend/backend/workflow-engine response 200; Hermes down alert ≠ DMS production outage alert
|
||||
|
||||
### Implementation for User Story 5
|
||||
|
||||
- [ ] T042 [P] [US5] Create `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/stage-gates/` — checklist files per stage (stage-0.md → stage-5.md) ตาม quickstart.md acceptance gates; แต่ละ gate มี verification commands และ pass/fail criteria
|
||||
- [ ] T043 [US5] Extend `hermes/src/health/health.controller.ts` (extends T014) — เพิ่ม subsystem health: Redis status, Dev Qdrant status, Operations log status, hermes proxy status, BullMQ queue depths; return `HermesStatus` object ครบถ้วนตาม contracts/hermes-api.yaml
|
||||
- [ ] T044 [P] [US5] Create monitoring alert configuration: Hermes down / Telegram Bridge down / MCP unavailable / hermes proxy down = DevOps warning (ไม่ใช่ DMS production outage); repeated auth failure / rate limit spike = security alert; document ใน `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/monitoring-alerts.md`
|
||||
- [ ] T045 [P] [US5] Write failure isolation verification script `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/verify-isolation.sh` — `docker stop hermes_agent_lcbp3` แล้ว check DMS endpoints return 200; ใช้ใน Stage 1 acceptance gate
|
||||
- [ ] T046 [P] [US5] Create SOUL.md rotation cron job: เพิ่ม cron schedule ใน `hermes/src/orchestrator/soul.service.ts` สำหรับ rotate ทุก 30 วัน (archive + clear SOUL.md)
|
||||
|
||||
**Checkpoint**: Health endpoint แสดง subsystem status ครบถ้วน; Stage gate checklists ครบ 6 stages; Failure isolation test pass (DMS ยังทำงานเมื่อ Hermes ล่ม)
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Quality, security, và documentation finalization
|
||||
|
||||
- [ ] T047 [P] Verify all TypeScript files have `// File:` header and `// Change Log:` comments ตาม AGENTS.md; JSDoc สำหรับ public classes (Thai comments)
|
||||
- [ ] T048 [P] Replace all `console.log` ด้วย NestJS Logger (`this.logger.log/warn/error`) ทั่วทั้ง `hermes/src/`
|
||||
- [ ] T049 Secret scan validation: ตรวจสอบว่าไม่มี secret จริงใน `hermes/` source tree, compose files, `.env.example`, หรือ spec files; เพิ่ม pre-commit hook (mandatory — FR-020)
|
||||
- [ ] T050 [P] Resource limit verification: สร้าง `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/verify-resources.sh` — `docker inspect` + `docker stats` แล้วเปรียบเทียบกับ expected limits (CPU 2.0 / RAM 4096MB)
|
||||
- [ ] T051 [P] Data Classification audit: review hermes proxy + sub-agent service code ว่าไม่มี production DB query results หรือ document content ใน Cloud AI request payloads
|
||||
- [ ] T052 Run `quickstart.md` staged verification (Stage 0 → Stage 5) และ update checklist results; document final rollout status
|
||||
- [ ] T053 [P] Create `specs/04-Infrastructure-OPS/04-00-docker-compose/ASUSTOR/hermes/secret-rotation.md` — Secret rotation runbook สำหรับ `HERMES_PROXY_API_KEY`, Telegram bot token, Gitea read-only + write tokens, read-only DB credential; include rotation schedule, revocation steps, และ operator offboarding procedure (FR-020)
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Phase 1 (Setup)**: ไม่มี dependency — เริ่มทันที
|
||||
- **Phase 2 (Foundational)**: ต้องการ Phase 1 — **BLOCKS ทุก user story**
|
||||
- **Phase 3 (US1)**: ต้องการ Phase 2 เสร็จ — เป็น MVP
|
||||
- **Phase 4 (US2)**: ต้องการ Phase 2 เสร็จ — สามารถขนาน Phase 3 ได้
|
||||
- **Phase 5 (US3)**: ต้องการ Phase 4 เสร็จ (extends Telegram dispatcher) + Phase 3 บางส่วน (hermes-bot git)
|
||||
- **Phase 6 (US4)**: ต้องการ Phase 2 เสร็จ — สามารถขนาน Phase 3/4 ได้
|
||||
- **Phase 7 (US5)**: ต้องการ Phase 3+4 เสร็จเพื่อ health checks ครบถ้วน
|
||||
- **Phase 8 (Polish)**: ต้องการทุก user story phase เสร็จ
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **US1 (P1)**: Phase 2 เสร็จ; ไม่ขึ้นกับ US2/US3/US4/US5
|
||||
- **US2 (P2)**: Phase 2 เสร็จ; ไม่ขึ้นกับ US1/US3/US4/US5
|
||||
- **US3 (P3)**: US2 (Phase 4) เสร็จ + US1 hermes-bot integration บางส่วน
|
||||
- **US4 (P4)**: Phase 2 เสร็จ; ไม่ขึ้นกับ US1/US2/US3
|
||||
- **US5 (P5)**: US1+US2 เสร็จสำหรับ health checks; สามารถเริ่ม stage-gate docs ขนานได้ตั้งแต่ Phase 1
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- Utilities/Guards (T008-T015) ก่อน feature implementation
|
||||
- Service → Controller → Module ordering
|
||||
- Unit tests [P] สามารถเขียนขนานกับ implementation ที่ไม่มี circular dependency
|
||||
|
||||
---
|
||||
|
||||
## Parallel Execution Examples
|
||||
|
||||
### Phase 2 (Foundational — parallel within phase):
|
||||
|
||||
```bash
|
||||
# รันพร้อมกัน:
|
||||
T008: uuid.util.ts
|
||||
T009: secret-redactor.util.ts
|
||||
T010: api-key.guard.ts
|
||||
T011: transaction.interceptor.ts
|
||||
T014: health.controller.ts
|
||||
T015: secret-redactor.spec.ts
|
||||
```
|
||||
|
||||
### Phase 3 US1 (parallel foundations before orchestrator):
|
||||
|
||||
```bash
|
||||
# รันพร้อมกัน:
|
||||
T016: dev-qdrant.service.ts
|
||||
T017: context-loader.service.ts
|
||||
T018: sub-agent.service.ts
|
||||
# รอ T016-T018 เสร็จ → T019, T020
|
||||
# รอ T019-T020 เสร็จ → T021, T022
|
||||
```
|
||||
|
||||
### Phase 4+6 (US2 และ US4 ขนานกับ US1):
|
||||
|
||||
```bash
|
||||
# ขณะที่ทีม A ทำ US1 (Phase 3):
|
||||
# ทีม B ทำ US2 (Phase 4): T025, T026 ก่อน → T027 → T028, T029
|
||||
# ทีม C ทำ US4 (Phase 6): T037, T038, T039 ขนานกัน
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (US1 Only — Autonomous Dev Orchestrator)
|
||||
|
||||
1. Complete Phase 1: Setup
|
||||
2. Complete Phase 2: Foundational (CRITICAL)
|
||||
3. Complete Phase 3: US1 — Autonomous Dev Orchestrator
|
||||
4. **STOP + VALIDATE**: ส่ง coding task → ตรวจสอบ PR created in Gitea
|
||||
5. Demo to developer team
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. Setup + Foundational → Foundation ready (Stage 1 acceptance gate ✅)
|
||||
2. Add US1 → Autonomous coding loop (MVP) → demo
|
||||
3. Add US2 → Telegram read-only DevOps (Stage 3 acceptance gate ✅)
|
||||
4. Add US3 → Write-with-confirmation (Stage 4 acceptance gate ✅)
|
||||
5. Add US4 → Developer AI Proxy (Stage 5 acceptance gate ✅)
|
||||
6. Add US5 → Full monitoring + staged rollout docs complete
|
||||
|
||||
### Staged Rollout Alignment
|
||||
|
||||
| Deployment Stage | Prerequisite Tasks |
|
||||
|------------------|--------------------|
|
||||
| Stage 0 (Docs) | T001–T007 (Setup) |
|
||||
| Stage 1 (LAN container) | T008–T015 (Foundational) + T042, T045 |
|
||||
| Stage 2 (Read-only DB/Gitea) | T025 (Gitea read-only) |
|
||||
| Stage 3 (Telegram read-only) | T026–T032 (US2 complete) |
|
||||
| Stage 4 (Write-with-confirmation) | T033–T036 (US3 complete) |
|
||||
| Stage 5 (Proxy) | T037–T041 (US4 complete) |
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- [P] tasks = different files, no dependency conflicts — safe to parallelize
|
||||
- hermes-bot Gitea token ต้องสร้างก่อน T033/T035
|
||||
- Telegram bot token ต้องสร้างก่อน T027
|
||||
- ห้าม commit secret จริงใน `.env.example` หรือ compose files — placeholder only
|
||||
- ทุก TypeScript file ต้องขึ้นต้นด้วย `// File: hermes/src/...` ตาม AGENTS.md
|
||||
- ห้ามใช้ DMS production Redis, DMS Qdrant, DMS `audit_logs` ทุกกรณี
|
||||
- ADR-031 Stage gate ต้องผ่านก่อน deploy stage ถัดไป — ห้าม skip
|
||||
Reference in New Issue
Block a user