docs(hermes): PR-Hermes-Sandbox-Env-Propagation-1 closure 보고서
PR-Hermes-Docsrv-Search-1 / PR-Hermes-WebSearch-1 의 user-facing E2E 마지막 조각.
Adapter A 후 잔존한 401: execute_code/terminal 샌드박스가 HERMES_DOCSRV_TOKEN
strip. 해결 = ~/.hermes/config.yaml terminal.env_passthrough 1줄 추가.
검증:
- Direct: is_env_passthrough("HERMES_DOCSRV_TOKEN")=True, CLAUDE_API_KEY=False
(GHSA-rhgp-j443-p4rf provider blocklist 유지)
- E2E: Hermes chat → DS API 200 → conf=medium completeness=full + real corpus
citations ("test-voice-memo", "The Good List: 6 Things to Add Joy to Your Day")
PR-1/2 user-facing E2E unlock 완료 — Discord smoke 검증 진입 가능
(가족 onboarding 전 hyungi 채널 한정).
This commit is contained in:
@@ -0,0 +1,148 @@
|
|||||||
|
# PR-Hermes-Sandbox-Env-Propagation-1 Closure Report
|
||||||
|
|
||||||
|
**Date**: 2026-05-17
|
||||||
|
**선행 PR**: PR-Hermes-Docsrv-Search-1, PR-Hermes-WebSearch-1, PR-Hermes-ToolCall-Adapter-1
|
||||||
|
**범위**: 1-line config 변경 (`terminal.env_passthrough` allowlist)
|
||||||
|
**파일**: `~/.hermes/config.yaml`
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
PR-Hermes-Docsrv-Search-1 / PR-Hermes-WebSearch-1 의 user-facing E2E 마지막 조각. PR-Hermes-ToolCall-Adapter-1 closure 시 Layer 2 Hermes chat 의 `execute_code` 샌드박스가 HERMES_DOCSRV_TOKEN env 를 inherit 못 함 → DS API 401 발견. Hermes 의 `terminal.env_passthrough` 메커니즘 (skill 의 `required_environment_variables` 또는 user-config allowlist 가 sandbox 의 env 스트립을 우회) 에 1줄 추가로 해결.
|
||||||
|
|
||||||
|
## Root cause
|
||||||
|
|
||||||
|
`tools/env_passthrough.py` docstring 정리:
|
||||||
|
- `execute_code` / `terminal` 샌드박스는 기본적으로 모든 env 변수를 strip (보안)
|
||||||
|
- 두 가지 path 로 allowlist 등록 가능:
|
||||||
|
1. **Skill `skill_view` tool_call** 시 → `register_env_passthrough(required_environment_variables)` 자동 발화
|
||||||
|
2. **User config `terminal.env_passthrough`** → 영구 allowlist
|
||||||
|
|
||||||
|
**기존 docsrv_ask SKILL.md 의 frontmatter**:
|
||||||
|
```yaml
|
||||||
|
prerequisites:
|
||||||
|
commands: [curl, jq]
|
||||||
|
env: [HERMES_DOCSRV_TOKEN]
|
||||||
|
```
|
||||||
|
|
||||||
|
→ legacy `env_vars` 형식. `skill_view` 가 호출되어야 변환 + register. 그러나 `hermes chat -s docsrv_ask` preload 는 **system prompt inject 만**, `skill_view` 호출 발화 안 됨 → allowlist 등록 0 → sandbox 가 HERMES_DOCSRV_TOKEN strip → 401.
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
|
||||||
|
`~/.hermes/config.yaml` 의 terminal section 1줄 변경:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
terminal:
|
||||||
|
...
|
||||||
|
env_passthrough:
|
||||||
|
- HERMES_DOCSRV_TOKEN # PR-Hermes-Sandbox-Env-Propagation-1
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
**보안 검증** (GHSA-rhgp-j443-p4rf 정합):
|
||||||
|
- `_HERMES_PROVIDER_ENV_BLOCKLIST` 가 ANTHROPIC_*, OPENAI_*, CLAUDE_API_KEY 등 Hermes-managed provider 토큰 차단
|
||||||
|
- HERMES_DOCSRV_TOKEN 은 user-managed 토큰 (voice-memo-bot account JWT) → blocklist 외 → 안전
|
||||||
|
|
||||||
|
## 검증
|
||||||
|
|
||||||
|
### 1. Direct config verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ HERMES_DOCSRV_TOKEN=... ~/.hermes/hermes-agent/venv/bin/python -c '
|
||||||
|
from tools.env_passthrough import is_env_passthrough, _load_config_passthrough
|
||||||
|
print(_load_config_passthrough())
|
||||||
|
print(is_env_passthrough("HERMES_DOCSRV_TOKEN"))
|
||||||
|
print(is_env_passthrough("CLAUDE_API_KEY"))
|
||||||
|
'
|
||||||
|
|
||||||
|
parent process has HERMES_DOCSRV_TOKEN: True (len=157)
|
||||||
|
config terminal.env_passthrough loaded: ['HERMES_DOCSRV_TOKEN']
|
||||||
|
HERMES_DOCSRV_TOKEN in allowlist: True ✅
|
||||||
|
CLAUDE_API_KEY in allowlist (should be False): False ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Hermes chat E2E (이전 401 시나리오 재현)
|
||||||
|
|
||||||
|
```
|
||||||
|
hermes chat -s docsrv_ask -q 'docsrv_ask 으로 내 자료에서 voice memo 관련 자료 찾아줘'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Proxy 로그 trace** (이전 vs 현재):
|
||||||
|
|
||||||
|
| 단계 | 이전 (Adapter A only) | 현재 (Adapter A + env_passthrough) |
|
||||||
|
|---|---|---|
|
||||||
|
| Hermes Turn 1 | Gemma → execute_code(curl) | Gemma → execute_code(curl) |
|
||||||
|
| Sandbox env | HERMES_DOCSRV_TOKEN STRIPPED | HERMES_DOCSRV_TOKEN PROPAGATED ✅ |
|
||||||
|
| DS API call | HTTP 401 "유효하지 않은 토큰" | **HTTP 200** ✅ |
|
||||||
|
| DS RAG pipeline | (skip) | query_analyze + classifier + evidence + synthesis ALL RUN ✅ |
|
||||||
|
| Result | Hermes 401 loop (4 turn) | **Real corpus answer with 2 citations** |
|
||||||
|
|
||||||
|
**DS log 발췌** (보고서 작성 시점, voice memo query):
|
||||||
|
```
|
||||||
|
[INFO] query_analyze ok query='voice memo' conf=0.90 intent=semantic_search elapsed_ms=6692
|
||||||
|
[INFO] evidence ok query='voice memo' candidates=2 kept=2 elapsed_ms=10665
|
||||||
|
[INFO] classifier ok query='voice memo' verdict=sufficient (raw=partial) covered=1 missing=2 elapsed_ms=13076
|
||||||
|
[INFO] synthesis ok query='voice memo' evidence_n=2 answer_len=186 citations=2 conf=medium elapsed_ms=3948
|
||||||
|
[INFO] ask query='voice memo' results=10 evidence=2 cite=2 synth=completed conf=medium completeness=full refused=False total=17363
|
||||||
|
```
|
||||||
|
|
||||||
|
**DS synthesis 결과** (실제 corpus, hallucinated 아님):
|
||||||
|
> "The evidence mentions voice memos as one of the things to add joy to your day [2]. Additionally, there is a test voice memo related to the first review item for gas engineer studies [1]."
|
||||||
|
|
||||||
|
Citations:
|
||||||
|
- [1] "테스트 음성 메모입니다. 가스기사 학습 검토 항목 첫 번째" — 실제 DS memo (test-voice-memo)
|
||||||
|
- [2] "Voice memos, snail mail and your own private screening room." — "The Good List: 6 Things to Add Joy to Your Day" 문서
|
||||||
|
|
||||||
|
### 3. Layer 2 user-facing 응답
|
||||||
|
|
||||||
|
Hermes 가 DS 응답 받은 후 multi-turn agent loop 에서 추가 docsrv_ask 호출 (refinement) — 응답 합성에 ~5-10분 소요 (Mac mini 26B + 23000 input tokens). Background 중단했으나 모든 핵심 검증 (env propagation + DS 실 호출 + 실 citations) 통과.
|
||||||
|
|
||||||
|
## File changes
|
||||||
|
|
||||||
|
### Mac mini
|
||||||
|
- `~/.hermes/config.yaml`:
|
||||||
|
- `terminal.env_passthrough: [] → [HERMES_DOCSRV_TOKEN]`
|
||||||
|
- `~/.hermes/config.yaml.pre-env-passthrough.20260517` (7일 안전망)
|
||||||
|
|
||||||
|
### 변경 없음
|
||||||
|
- SKILL.md (정상 동작 — sandbox env가 propagate 되므로 skill 본문 변경 불필요)
|
||||||
|
- mlx-proxy.py
|
||||||
|
- DS code
|
||||||
|
- Hermes gateway / launchagent
|
||||||
|
|
||||||
|
## 결정 사항
|
||||||
|
|
||||||
|
1. **PR-Hermes-Sandbox-Env-Propagation-1 = SHIPPED**:
|
||||||
|
- Direct config verification PASS
|
||||||
|
- Hermes chat E2E DS API 200 + real corpus citations 확보
|
||||||
|
- **PR-1 / PR-2 user-facing E2E 마지막 조각 풀림**
|
||||||
|
2. **남은 운영 관심사** (별 트랙):
|
||||||
|
- **PR-Hermes-Skill-Curl-Refine-1** (선택): docsrv_ask SKILL.md frontmatter 를 legacy `prerequisites.env` → 표준 `required_environment_variables` 로 마이그레이션. 효과 = `skill_view` 도 자동 registration. 본 config-level fix 와 중복 안전망. P3.
|
||||||
|
- **PR-Hermes-Multi-Turn-Refinement-1** (선택): Gemma 가 첫 docsrv_ask 결과로 만족 못 하면 같은 query 를 refinement 와 함께 재호출 → multi-turn 길어짐. skill 본문에 "1회 호출 후 결과 그대로 사용" 강조. P3.
|
||||||
|
- **PR-Hermes-MaxTokens-Followup**: 23320 input tokens (31 tools + 90 skills + persona) → 30s+ first-token. tools/skills 선택적 로딩. P3.
|
||||||
|
|
||||||
|
## 후속 트랙 (PR-1/2 user-facing E2E 진입 가능)
|
||||||
|
|
||||||
|
| 우선순위 | 트랙 | 이전 진입 조건 충족? |
|
||||||
|
|---|---|---|
|
||||||
|
| **이제 가능** | PR-1 Layer 2/3 user-facing E2E 검증 (Discord smoke) | ✅ (Adapter A + env_passthrough) |
|
||||||
|
| **이제 가능** | PR-2 Layer 2/3 user-facing E2E 검증 (Discord smoke, web_search 자율 호출) | ✅ |
|
||||||
|
| 별 트랙 | PR-Hermes-Answer-Policy-1 (출처 라벨 plugin-level 강제) | PR-1/2 user-facing 안정화 후 |
|
||||||
|
| 별 트랙 | PR-Hermes-FamilyACL-N | 진입 조건 미정 |
|
||||||
|
|
||||||
|
## 7일 안전망 (2026-05-24)
|
||||||
|
|
||||||
|
- Mac mini: `~/.hermes/config.yaml.pre-env-passthrough.20260517`
|
||||||
|
- 복귀 시: `terminal.env_passthrough` 리스트 비우기 (또는 백업 복원)
|
||||||
|
|
||||||
|
## 검증 commands (재실행)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Direct config verify
|
||||||
|
ssh macmini "~/.hermes/hermes-agent/venv/bin/python -c 'from tools.env_passthrough import is_env_passthrough; print(is_env_passthrough(\"HERMES_DOCSRV_TOKEN\"))'"
|
||||||
|
|
||||||
|
# Hermes chat E2E (Discord 채널 입력으로 등가)
|
||||||
|
ssh macmini "HERMES_DOCSRV_TOKEN=... && ~/.hermes/hermes-agent/venv/bin/python -m hermes_cli.main chat -s docsrv_ask -q '<query>'"
|
||||||
|
|
||||||
|
# DS API 호출 확인
|
||||||
|
ssh gpu "cd ~/Documents/code/hyungi_Document_Server && docker compose logs --since=5m fastapi | grep 'ask query'"
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user