From 41b44b03b49133e290feab40a0dfaf392a79a72a Mon Sep 17 00:00:00 2001 From: cafitac Date: Mon, 27 Apr 2026 22:57:28 +0900 Subject: [PATCH 1/2] docs: add agent learner integration PRD --- docs/agent-learner-integration.md | 679 ++++++++++++++++++++++++++++++ 1 file changed, 679 insertions(+) create mode 100644 docs/agent-learner-integration.md diff --git a/docs/agent-learner-integration.md b/docs/agent-learner-integration.md new file mode 100644 index 0000000..bd185eb --- /dev/null +++ b/docs/agent-learner-integration.md @@ -0,0 +1,679 @@ +# PRD: codex-channels & agent-learner v2 통합 + +**작성일**: 2026-04-26 +**최종 업데이트**: 2026-04-27 +**상태**: 구현 완료 + +--- + +## 1. 배경 및 목적 + +### codex-channels +Codex가 Hermit을 subprocess로 오케스트레이션할 때, Hermit의 interactive 프롬프트(권한 요청, 사용자 입력)를 codex-channels 런타임을 통해 외부 채널(Slack, Telegram 등)로 라우팅한다. **Hermit standalone과는 무관하다.** + +### agent-learner v2 +Hermit Learner의 직계 후계자이자 하네스 독립 학습 라이브러리. + +**설계 원칙:** +1. **완전 자동화** — LLM 추출 → verify → 프로모션 → deprecated 전 과정 무인 실행 +2. **하네스 독립** — Claude Code / Codex / Hermit 동일한 인터페이스 +3. **READ/WRITE 경로 분리** — WRITE(추출+추적)는 Stop hook, READ(주입)는 프롬프트 준비 시점 ← 3자 협의 확정 +4. **최대 통일** — Stop hook 트리거, 파일명, 주입 경로 모두 동일 패턴 +5. **모델 인지** — 성능 추적 기반 자동 include/exclude +6. **계층적 스코프** — project local → user global 자동 프로모션 +7. **autoresearch 확장점** — 학습된 md 데이터를 autoresearch seed로 활용 + +> **3자 협의 핵심 결정 (2026-04-26)**: "단일 Stop hook = 모든 경로 통일"이 아니라 "단일 WRITE 트리거(Stop hook) + READ는 세션 시작 시 유지"로 확정. +> - WRITE 경로(추출 `loop.py:707` + 추적 `agent_session.py:149`) → Stop hook으로 통일 +> - READ 경로(주입 `agent_session.py:128`) → 프롬프트 준비 시점 유지, `agent-learned.md` 파일 읽기 +> - 이유: READ를 Stop hook으로 옮기면 "첫 세션 또는 직전 세션 크래시 시 규칙 미주입" 시간적 결합 발생 + +--- + +## 2. 전체 아키텍처 + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ 하네스 (Claude Code / Codex / Hermit) │ +│ │ +│ 세션 시작 세션 종료 │ +│ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ .hermit/rules/ │ │ Stop hook │ │ +│ │ agent-learned.md │ │ (settings.json) │ │ +│ │ 읽어서 prompt 주입│ └────────┬─────────┘ │ +│ └──────────────────┘ │ │ +└─────────────────────────────────────────────────────────────────-┘ + ↑ inject │ trigger + │ ▼ +┌──────────────────────────────────────────────────────────────────┐ +│ agent-learner v2 │ +│ │ +│ events/{adapter}/session_end-{id}.json │ +│ ↓ │ +│ AutoLearningPipeline │ +│ 1. LLM 추출 (configured LLM) │ +│ 2. 유사도 비교 (신규/갱신/fork/중복) │ +│ 3. verify_cmd 실행 │ +│ 4. 모델 성능 카운터 업데이트 │ +│ 5. auto-promote or auto-deprecate │ +│ 6. agent-learned.md 재생성 │ +│ 7. inject_dirs 전체에 fan-out │ +│ ↓ │ +│ .agent-learner/agent-learned.md ← source of truth │ +│ .claude/rules/agent-learned.md │ +│ .codex/rules/agent-learned.md │ +│ .hermit/rules/agent-learned.md │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 3. 인터페이스 통일 명세 + +### 3-1. Hook 트리거 (모든 하네스 동일) + +| 하네스 | Hook 방식 | 설정 위치 | +|---|---|---| +| Claude Code | `Stop` hook | `.claude/settings.json` | +| Hermit | `Stop` hook (신규 추가) | `.hermit/settings.json` | +| Codex | `Stop` hook 또는 skill | `.codex/settings.json` or skill | + +모든 hook이 실행하는 명령어: +```bash +agent-learner process \ + --adapter {hermit|claude|codex} \ + --session-id {SESSION_ID} \ + --cwd {CWD} \ + --model-id {MODEL_ID} \ + --auto +``` + +`--auto` 플래그: 사람 리뷰 없이 전 파이프라인 자동 실행. + +### 3-2. 이벤트 파일 포맷 (모든 어댑터 동일) + +```jsonc +// .agent-learner/events/{adapter}/session_end-{id}.json +{ + "adapter": "hermit", + "event_name": "session_end", + "session_id": "abc123", + "cwd": "/path/to/project", + "model_id": "glm-4-9b", + "ts": "2026-04-26T10:00:00Z", + "payload": { + "outcome": "success", // success | failure | cancelled + "tool_call_count": 23, + "message_count": 41, + "pytest_output": "...", // 있으면 + "transcript_path": "..." // 있으면 + } +} +``` + +### 3-3. 주입 파일 (모든 하네스 동일 파일명) + +**파일명**: `agent-learned.md` (경로만 다름) + +``` +.agent-learner/agent-learned.md ← source of truth +.claude/rules/agent-learned.md ← Claude Code 자동 로드 +.codex/rules/agent-learned.md ← Codex 자동 로드 +.hermit/rules/agent-learned.md ← Hermit context_injector 로드 +``` + +설정: +```jsonc +// .agent-learner/config.json +{ + "inject_dirs": [ + ".agent-learner", + ".claude/rules", + ".codex/rules", + ".hermit/rules" + ] +} +``` + +agent-learner가 규칙 변경 시 `inject_dirs`의 모든 경로에 `agent-learned.md` 동일 내용으로 씀. + +### 3-4. 주입 파일 포맷 + +```markdown + + +# Learned Rules + +## always-verify-with-pytest +pytest 실행 후 결과로 검증한다. +**Why**: 자기보고만으론 실제 오류 놓침 +*scope: changes | validated: claude-sonnet-4-6, glm-4-9b* + +## prefer-select-related-for-fk +FK 필드 조회 시 select_related() 사용한다. +**Why**: N+1 쿼리 방지 +*scope: django | validated: claude-sonnet-4-6* +``` + +--- + +## 4. agent-learner v2 설계 + +### 4-1. 핵심 추가 컴포넌트 + +#### A. LearnerLLM 프로토콜 + +```python +# agent_learner/core/llm.py + +from typing import Protocol + +class LearnerLLM(Protocol): + def extract( + self, + prompt: str, + system: str | None = None, # 미래 multi-turn/시스템 프롬프트 확장 대비 + timeout: float = 30.0, # [P1] shutdown 경로 LLM 콜 timeout 필수 + ) -> dict | None: + """규칙 후보 추출. 실패 또는 timeout 시 None 반환 (예외 불가).""" + ... + +class ConfiguredLearnerLLM: + """config.json 기반 LLM 클라이언트.""" + # provider: anthropic | openai | ollama | hermit-mcp + # model: claude-sonnet-4-6 등 + # endpoint: optional override + ... + +class HermitMcpLearnerLLM: + """Hermit MCP 경유 LLM (Claude Code에서 Hermit LLM 쓰고 싶을 때).""" + ... +``` + +> **[P1] Shutdown 경로 LLM Timeout**: `extract()`는 shutdown/atexit 경로에서 호출될 수 있으므로 반드시 `timeout` 파라미터를 강제하고, 초과 시 `None` 반환 (예외 전파 금지). ThreadPoolExecutor + timeout 또는 threading.Timer watchdog으로 구현. + +LLM 우선순위: +1. `AutoLearningPipeline(llm=...)` 주입값 +2. `.agent-learner/config.json`의 `llm` 설정 +3. `~/.agent-learner/config.json`의 `llm` 설정 +4. 환경변수 (`AGENT_LEARNER_LLM_*`) + +#### B. AutoLearningPipeline + +```python +# agent_learner/core/pipeline_auto.py + +class AutoLearningPipeline: + """session_end 이벤트 → approved rule 완전 자동 처리.""" + + def process_session( + self, + *, + session_id: str, + adapter: str, + outcome: Literal["success", "failure", "cancelled"], + tool_call_count: int, + cwd: str, + model_id: str, + pytest_output: str | None = None, + transcript_path: str | None = None, + ) -> ProcessedSessionResult: + """ + 1. 이벤트 파일 기록 + 2. LLM으로 규칙 후보 추출 + 3. 기존 규칙 유사도 비교 (신규/갱신/fork/중복 판단) + 4. verify_cmd 실행 + 5. 모델 성능 카운터 업데이트 + 6. auto_promote=True → 즉시 approved + 7. agent-learned.md 재생성 → inject_dirs fan-out + """ + ... + + def record_rule_used( + self, + rule_name: str, + *, + outcome: bool | None, + model_id: str, + ) -> None: + """규칙 사용 후 모델별 성능 카운터 업데이트 + auto-deprecated 체크.""" + ... +``` + +#### C. 모델별 성능 추적 (LearningRule 확장) + +```python +# agent_learner/core/models.py + +@dataclass +class ModelPerf: + use_count: int = 0 + success_count: int = 0 + fail_count: int = 0 + + @property + def success_rate(self) -> float: + total = self.success_count + self.fail_count + return self.success_count / total if total > 0 else 0.0 + +@dataclass +class LearningRule: + # 기존 필드 유지 ... + + # 모델별 성능 (동적 include/exclude 기반) + model_performance: dict[str, ModelPerf] = field(default_factory=dict) + + # 자동 관리 — 사람이 직접 편집 비권장 + validated_on_models: list[str] = field(default_factory=list) + excluded_models: list[str] = field(default_factory=list) + + # Hermit Learner에서 이식 + use_count: int = 0 # 전체 (모델 무관) + last_used: str = "" + needs_review: bool = False + verify_cmd: str = "" + + # 어댑터/하네스 태깅 + source_adapter: str = "" # hermit | claude | codex + harness: str = "universal" # hermit | claude | codex | universal +``` + +#### D. 모델 동적 include/exclude 자동화 + +| 상황 | 동작 | +|---|---| +| 모델이 `validated_on_models`에 있음 | 규칙 적용 | +| 모델이 `excluded_models`에 있음 | 규칙 제외 | +| 처음 보는 모델 (neutral) | 일단 적용 + 해당 모델 성능 추적 시작 | +| neutral 모델 `success_rate ≥ 0.7`, `use_count ≥ N` | → `validated_on_models` 자동 추가 | +| neutral/validated 모델 `success_rate < 0.4`, `use_count ≥ N` | → `excluded_models` 자동 이동 | +| excluded였다가 성능 회복 (`success_rate ≥ 0.7`) | → excluded 제거, validated 복귀 | + +모델 성능 추적 예시: + +```yaml +model_performance: + claude-sonnet-4-6: + use_count: 8 + success_count: 7 + fail_count: 1 # success_rate: 0.875 → validated + glm-4-9b: + use_count: 6 + success_count: 2 + fail_count: 4 # success_rate: 0.33 → excluded + qwen2.5-coder:32b: + use_count: 0 # neutral → 일단 적용, 추적 시작 + +validated_on_models: [claude-sonnet-4-6] # 자동 관리 +excluded_models: [glm-4-9b] # 자동 관리 +``` + +### 4-2. 스코프 계층 자동 프로모션 + +``` +project rule + use_count ≥ 10, success_rate ≥ 0.7 + ↓ 자동 global 프로모션 후보 +~/.agent-learner/global/learning/approved/ + 여러 adapter에서 사용 → harness: universal 태깅 + ↓ +다음 세션 retrieval 시 project + global 머지 (project 우선) +``` + +### 4-3. 어댑터 재설계 + +어댑터는 이벤트 에밋 + hook 설치만 담당. 파이프라인은 `AutoLearningPipeline` 한 벌. + +```python +# agent_learner/adapters/hermit.py + +def install_hermit_hooks(project_root: Path) -> None: + """ + .hermit/settings.json에 Stop hook 추가: + { + "hooks": { + "Stop": [{ + "command": "agent-learner process --adapter hermit ..." + }] + } + } + """ + ... + +# agent_learner/adapters/claude.py (기존 리팩토링) +def install_claude_hooks(project_root: Path) -> None: + """ + .claude/settings.json에 Stop hook 추가 (기존 방식 유지). + """ + ... + +# agent_learner/adapters/codex.py (기존 리팩토링) +def install_codex_hooks(project_root: Path) -> None: + """ + Stop hook 또는 AUTO_SESSION_LEARNING skill 설치. + Codex의 hook API 지원 여부에 따라 분기. + """ + ... +``` + +설치 통합 CLI: +```bash +agent-learner bootstrap --target /path/to/project +# → .agent-learner/ 초기화 +# → 감지된 하네스(hermit/claude/codex)에 hook 자동 설치 +# → inject_dirs 설정 +``` + +### 4-4. 아키텍처 결정: 부분 재작성 + +**유지 (현재 agent-learner)** +- `LearningRule` 기본 모델 구조 +- 2단계 인덱싱 (`rules.json` → 파일 로드) +- `RetrievalRequest` / scoring 시스템 +- project + global 저장소 레이아웃 +- CLI 커맨드 이름 체계 + +**재작성** +- 수동 리뷰 → `AutoLearningPipeline`이 primary +- `LearnerLLM` 프로토콜 신규 +- `LearningRule`에 모델별 성능 추적 필드 추가 +- `verify_cmd` + auto-deprecated 로직 (Hermit Learner에서 이식) +- 어댑터: hook 설치 + 이벤트 에밋만으로 단순화 +- retrieval: 모델/어댑터 필터 추가 + +--- + +## 5. 설정 파일 + +```jsonc +// ~/.agent-learner/config.json (user global) +{ + "auto_pipeline": { + "enabled": true, + "auto_promote": true, + "verify_timeout": 30, + "project_to_global_threshold": 10, + "global_promotion_min_adapters": 2 + }, + "llm": { + "provider": "anthropic", // anthropic | openai | ollama | hermit-mcp + "model": "claude-sonnet-4-6", + "endpoint": null + }, + "deprecation": { + "min_uses_before_eval": 5, + "success_rate_threshold": 0.4, + "unused_days_threshold": 30 + }, + "model_validation": { + "min_uses_before_classify": 5, + "validated_threshold": 0.7, + "excluded_threshold": 0.4 + } +} + +// .agent-learner/config.json (project override) +{ + "llm": { + "provider": "ollama", + "model": "qwen2.5-coder:32b" + }, + "inject_dirs": [ + ".agent-learner", + ".claude/rules", + ".codex/rules", + ".hermit/rules" + ] +} +``` + +--- + +## 6. 저장소 레이아웃 + +``` +~/.agent-learner/ ← user global + global/ + learning/ + approved/rule-name.md + deprecated/ + history/promotions.jsonl + config.json + +/.agent-learner/ ← project local + events/ + hermit/session_end-{id}.json + claude/session_end-{id}.json + codex/session_end-{id}.json + learning/ + approved/rule-name.md + needs_review/ + deprecated/ + drafts/ + index/ + rules.json ← 빠른 검색 인덱스 + history/promotions.jsonl + config.json + agent-learned.md ← source of truth (자동 생성) + +/.claude/rules/agent-learned.md ← Claude Code 주입 (자동 생성) +/.codex/rules/agent-learned.md ← Codex 주입 (자동 생성) +/.hermit/rules/agent-learned.md ← Hermit 주입 (자동 생성) +``` + +--- + +## 7. Hermit 통합 (hermit-agent 변경 사항) + +> **3자 협의 확정**: WRITE 경로(추출+추적)만 Stop hook으로 이관. READ 경로(주입)는 프롬프트 준비 시점 유지. + +### 7-0. 선행: HookEvent.ON_STOP 추가 (Phase 3 착수 전 필수) + +`ON_EXIT`(프로세스 종료)와 `ON_STOP`(세션 완료)은 MCP 모드에서 구분이 필수 — 단일 프로세스가 다수 세션을 처리한다. + +```python +# hermit_agent/hooks.py (또는 hooks/types.py) +class HookEvent(str, Enum): + PRE_TOOL_USE = "PreToolUse" + POST_TOOL_USE = "PostToolUse" + ON_START = "OnStart" + ON_EXIT = "OnExit" + ON_STOP = "OnStop" # ← 신규: 세션/태스크 완료 시 +``` + +`loop.py::shutdown()`에 호출 추가 (기존 `ON_EXIT` 다음): +```python +self.hook_runner.run_hooks(HookEvent.ON_STOP, "", { + "session_id": self.session_id, + "model_id": self.llm.model_id, + "tool_call_count": self.tool_call_count, +}) +``` + +### 7-1. Stop hook 배선 (WRITE 경로만) + +```jsonc +// .hermit/settings.json (agent-learner bootstrap이 자동 설치) +{ + "hooks": { + "OnStop": [{ + "command": "agent-learner process --adapter hermit --session-id $HERMIT_SESSION_ID --cwd $CWD --model-id $HERMIT_MODEL_ID --auto" + }] + } +} +``` + +**제거 대상 (WRITE 경로)**: +- `loop.py:707-731` `_maybe_trigger_learner()` → 추출 WRITE, Stop hook으로 이관 +- `agent_session.py:149-158` `_schedule_teardown()` learner 부분 → 추적 WRITE, Stop hook으로 이관 + +**유지 대상 (READ 경로)**: +- `agent_session.py:128-136` `_prepare_prompt()` learner 주입 → 세션 시작 시 READ, 그대로 둠 + +Phase 3 작업 순서: +1. `HookEvent.ON_STOP` 추가 및 `shutdown()` 호출 추가 +2. WRITE 경로 2개 제거 (`_maybe_trigger_learner`, `_schedule_teardown` learner 부분) +3. Stop hook 단일 경로로만 WRITE 실행 검증 (mock adapter 호출 횟수 == 1) +4. READ 경로(`_prepare_prompt`) 동작 유지 검증 + +### 7-2. context_injector 변경 (READ 경로 — 프롬프트 준비 시점) + +```python +# agent_session.py::_prepare_prompt() 또는 context_injector.py + +def _build_learned_rules_block(self, context_keywords: list[str] | None = None) -> str: + rules_file = Path(self.cwd) / ".hermit" / "rules" / "agent-learned.md" + if rules_file.exists(): + content = rules_file.read_text(encoding="utf-8").strip() + return content if content else "" + # 폴백: 기존 Hermit Learner (context_keywords 필터링 유지) + return self._build_hermit_learner_block(context_keywords) +``` + +> **[P2] context_keywords 필터링 보존**: `agent-learned.md`는 현재 flat 파일이지만, agent-learner v2 retrieval이 `context_keywords` 기반 필터링을 지원하면 태스크 키워드로 필터된 내용을 생성하도록 확장한다. 소규모 LLM(glm-4-9b)에서 토큰 예산 낭비 방지 목적. + +### 7-3. 동시 세션 파일 락 + +여러 세션이 동시에 `agent-learned.md` fan-out을 트리거할 수 있다. + +```python +# agent_learner/core/fanout.py +import fcntl + +def write_agent_learned(path: Path, content: str) -> None: + lock_path = path.with_suffix(".lock") + with open(lock_path, "w") as lf: + fcntl.flock(lf, fcntl.LOCK_EX) + try: + if path.exists() and path.read_text(encoding="utf-8") == content: + return # idempotent skip + path.write_text(content, encoding="utf-8") + finally: + fcntl.flock(lf, fcntl.LOCK_UN) +``` + +### 7-4. Hermit Learner 처리 + +- `.hermit/rules/agent-learned.md` 파일 존재 → Hermit Learner 폴백 비활성화 (자동 감지) +- 기존 `.hermit/skills/learned-feedback/` 데이터 마이그레이션 불필요 (클린 슬레이트) +- `hermit_agent/learner.py`는 Phase 3 완료 후 `DeprecationWarning` 추가, 삭제는 별도 PR + +--- + +## 8. codex-channels 통합 (범위 재정의) + +**유스케이스**: Codex ↔ Hermit 파이프라인에서 Hermit의 interactive 프롬프트 라우팅. + +남은 작업: + +| Story | 규모 | 우선순위 | +|---|---|---| +| Health Check + Graceful Degradation | S | P1 | +| MCPAgentSession 배선 | M | P1 | +| CLI (`hermit codex-channels install/start/stop/status`) | M | P2 | + +--- + +## 9. 구현 순서 (완료) + +``` +✅ Phase 1 — agent-learner v2 코어 (agent-learner PR#3) + 1a. LearningRule 모델 확장 (모델별 성능 추적 필드) + 1b. LearnerLLM 프로토콜 + ConfiguredLearnerLLM + 1c. AutoLearningPipeline (추출 → verify → 프로모션 → deprecated) + 1d. retrieval 모델/어댑터 필터 추가 + 1e. agent-learned.md 생성 + inject_dirs fan-out + +✅ Phase 2 — 어댑터 재작성 (agent-learner PR#4, PR#5) + 2a. Hermit 어댑터 (Stop hook 설치 + 이벤트 포맷) + 2b. Claude 어댑터 — install_claude_hooks() 추가, hook_format="claude" 지원 + 2c. Codex 어댑터 — install_codex_hooks() 추가, hook_format="codex" 지원 + ※ bootstrap CLI는 hermit install 내 자동 통합으로 대체 + +✅ Phase 3 — Hermit 통합 (hermit-agent PR#4) + 3a. HookEvent.ON_STOP 추가 (hooks/types.py + loop.py) + 3b. loop.py::_run_agent_learner_on_stop() — ON_STOP fire-and-forget + 3c. context_injector: agent-learned.md 파일 읽기 (READ 경로 유지) + 3d. ON_STOP: gateway/mcp 세션 스킵, start_new_session=True + +✅ Phase 4 — codex-channels 완성 (hermit-agent PR#5, PR#6) + 4a. Health check + 캐시 + graceful degradation (CodexChannelsInteractiveSink) + 4b. MCPAgentSession 배선 + +✅ Phase 5 — CLI/UX (hermit-agent PR#7, PR#9) + 5a. hermit learner {init,status,dashboard,process,inject} + 5b. hermit codex-channels {install,start,stop,status} + +✅ 추가 — 자동 설치/등록 + - hermit install: agent-learner pip install 자동 실행 (PR#9) + - hermit install: ~/.claude/settings.json + ~/.codex/hooks.json Stop hook 자동 등록 + - hermit doctor: agent-learner 설치 여부 + hook 등록 상태 진단 (2026-04-27) + - hermit doctor --fix: agent-learner 자동 복구 (run_install 경유) +``` + +--- + +## 10. 테스트 전략 + +### agent-learner v2 +``` +test_auto_pipeline_success_flow.py — 성공 세션 → approved rule 생성 +test_auto_pipeline_failure_flow.py — 실패 세션 → 개선 rule 추출 +test_auto_pipeline_verify_cmd.py — verify_cmd 실패 → not promoted +test_auto_pipeline_deprecation.py — success_rate < 0.4 → deprecated +test_model_perf_auto_validated.py — success_rate ≥ 0.7 → validated_on_models 추가 +test_model_perf_auto_excluded.py — success_rate < 0.4 → excluded_models 이동 +test_model_perf_recovery.py — excluded → 성능 회복 → validated 복귀 +test_retrieval_model_filter.py — excluded 모델 규칙 제외 확인 +test_retrieval_scope_merge.py — project + global 머지, project 우선 +test_inject_dirs_fanout.py — agent-learned.md 모든 inject_dirs에 동일 내용 +test_hook_install_hermit.py — .hermit/settings.json Stop hook 추가 +test_hook_install_claude.py — .claude/settings.json Stop hook 추가 +test_learner_llm_priority.py — LLM 설정 우선순위 (inject > project > global > env) +``` + +### Hermit 통합 +``` +test_on_stop_hook_event_added.py — HookEvent.ON_STOP 존재, shutdown()에서 호출 +test_write_path_adapter_called_once.py — 세션 종료 시 mock adapter 호출 횟수 == 1 (중복 없음) +test_write_path_removed_from_session.py — _schedule_teardown에 learner 코드 없음 (grep 검증) +test_read_path_prepare_prompt.py — _prepare_prompt에서 agent-learned.md 읽어 주입 +test_context_injector_fallback.py — agent-learned.md 없으면 Hermit Learner 폴백 +test_fanout_concurrent_lock.py — 동시 쓰기 시 파일 락 충돌 없음 +test_learner_llm_timeout.py — extract() 30s 초과 시 None 반환, 예외 없음 +test_codex_channels_degradation.py — 서버 없을 때 예외 없이 skip +``` + +--- + +## 11. 리스크 + +| 리스크 | 영향도 | 대응 | 검증 | +|---|---|---|---| +| R1: agent-learner 재작성 범위 크리프 | H | retrieval/index/storage 모듈 frozen list. LearnerLLM 프로토콜이 유일한 경계 | `git diff --name-only` vs frozen list CI 체크 | +| R2: WRITE 경로 중복 트리거 | H | 3개 경로 중 WRITE 2개만 제거, READ 유지. `ON_STOP` 단일 트리거 | mock adapter 호출 횟수 == 1 테스트 | +| R3: Codex Stop hook 미지원 | M | `atexit.register()` + CLI fallback (`agent-learner process --auto`) | 프로세스 종료 시뮬레이션 → atexit 실행 확인 | +| R4: 모델 성능 임계값 초기 부정확 | L | 초기 6개월 `auto_classify: false`. config로 조정 가능 | 50+ 규칙 평가 후 수동 임계값 튜닝 | +| R5: fan-out 부분 실패 | L | best-effort + fcntl 락 + 에러 로그. source of truth는 항상 성공 | 2개 존재 + 1개 없는 dir 테스트 → 2 성공 + 1 경고 | +| R6: shutdown 경로 LLM 콜 타임아웃 없음 [P1] | H | `extract()` 30s timeout 강제. 초과 시 None 반환, 예외 불가 | `test_learner_llm_timeout.py` | +| R7: READ/WRITE 경로 혼동으로 주입 경로 잘못 제거 | H | Phase 3 작업 순서에 "유지 대상" 명시. grep으로 READ 경로 존재 검증 | `test_read_path_prepare_prompt.py` | + +--- + +## 12. 장기 로드맵 + +``` +agent-learner v2 (행동 규칙 학습) ← 이 PRD +agent-brain / mempalace (도메인 지식 KB) ← 별도 프로젝트, learner와 분리 +autoresearch ← agent-learner approved/ md를 seed로 활용 +``` + +--- + +## 참고 + +- `hermit_agent/learner.py` — Phase 3 완료 후 deprecated 예정 +- `hermit_agent/codex/channels_adapter.py` — codex-channels 어댑터 (완성) +- `hermit_agent/interactive_sinks/codex_channels.py` — Sink 구현 (완성) +- `~/Project/agent-learner/` — 재작성 대상 (Phase 1-2) +- `~/Project/codex-channels/` — 참고용 (수정 대상 아님) From 1343bc156c51f593651ac71d949300aa26e5e089 Mon Sep 17 00:00:00 2001 From: cafitac Date: Mon, 27 Apr 2026 22:58:38 +0900 Subject: [PATCH 2/2] chore: ignore local worktree directories --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b878bd5..baef3e5 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,6 @@ hermes-agent/ # Local knowledge scratchpad kb/ + +# Local git worktrees used for isolated agent tasks +.worktrees/