GEODE는 확장 표면을 권한별로 나눕니다. 외부 통합이 의존할 수 있는 HookName, 실행을 감싸는 신뢰 표면 MiddlewareRegistry, 운영 관측을 위한 RuntimeEvent로 역할과 권한을 분리합니다.
세 표면
| 표면 | 용도 | 권한 |
|---|---|---|
| 공개 훅 | 사용자 입력, 도구, 압축, 세션, 서브에이전트, 검증 경계 | 이름별로 허용된 typed decision만 반환 |
| 신뢰 미들웨어 | 도구·LLM 요청 변환과 실제 실행 래핑 | 요청 단계는 변환, 실행 단계는 감싸기·단축 반환 |
| 런타임 이벤트 | 메트릭, 감사, 저장, 운영 진단 | 내부 관측 전용. 실행 제어 계약이 아님 |
공개 훅 13종
공개 목록은 의도적으로 작고 버전이 고정됩니다. 와일드카드 구독은 없으며, 입력은 크기 제한·JSON 안전화·비밀값 제거를 거칩니다.
| 훅 | 필수 payload | 허용 action |
|---|---|---|
UserPromptSubmit | user_input | continue · rewrite · block |
PreToolUse | tool_name, arguments | continue · rewrite · block · request_permission |
PermissionRequest | tool_name, safety_level, detail | allow · deny · ask |
PostToolUse | tool_name, arguments, result, has_error, executed | continue · add_context · block |
PreCompact | model, provider, message_count, keep_recent, trigger, hard | continue · rewrite · defer |
PostCompact | model, provider, original_message_count, new_message_count, keep_recent, trigger, persisted | continue |
SessionStart | model, provider, resumed, status | continue |
SessionEnd | reason, status | continue |
SubagentStart | task_id, task_type, description, child_session_key, parent_session_key | continue |
SubagentStop | task_id, task_type, success, status, duration_ms, error, child_session_key | continue |
PreVerify | termination_reason, rounds, tool_call_count, candidate_summary | continue · strengthen |
PostVerify | passed, mode, score, rubric_misses, termination_reason, rounds, tool_call_count, candidate_summary | accept · revise · escalate |
Stop | PostVerify fields + policy_action, evidence_refs | finalize · continue |
이 allowlist 밖의 action과 payload 필드는 거부됩니다. 실패한 내장 검증을 외부 훅이 pass로 뒤집을 수도 없습니다. rewrite는 비어 있지 않은 updates, PostVerify.revise와Stop.continue는 비어 있지 않은 instruction이 필요합니다.
공통 envelope와 제한
| 항목 | 계약 |
|---|---|
| 버전 | geode.public-hook.v2 (v1 schema 조회 가능) |
| 상관관계 | session_id, turn_id, step_id, run_id, session generation, verify attempt, tool/LLM call ID |
| payload 상한 | 문자열 4,096자, JSON 32 KiB, collection 64개, depth 8 |
| decision 상한 | reason 1,024자, instruction 4,096자, evidence reference 32개 |
| 기본 timeout | handler별 10초. sync handler는 event loop 밖에서 실행 |
| 오류 | 현재 handler 오류를 기록하고 다음 handler를 계속 실행 |
각 hook의 Draft 2020-12 JSON Schema는 런타임에서 직접 조회합니다. 문서 표와 직렬화 계약이 다르면 런타임 schema가 정본입니다.
from core.hooks import HookName, public_hook_schema schema = public_hook_schema(HookName.POST_VERIFY) print(schema["properties"]["payload"]) print(schema["properties"]["decision"])
PostVerify와 외부 루프
PostVerify는 이미 실행된 부수 효과를 재생하지 않고, 완성된 후보와 내장 검증 결과를 외부 평가기·CI 정책·오케스트레이터가 판정하게 합니다. revise는 구체적인 후속 지시가 있어야 하며 최대 2회 연속 시도로 제한됩니다. 최종 결과에는 모든 시도의 rounds, tool calls, usage가 합산된 뒤 증거와 체크포인트가 저장됩니다. escalate는 delivery gate로 동작합니다. 세션을 pause하고 후보를 외부 소유자에게만 pending_text로 반환하며 terminal session.ended를 만들지 않습니다.
외부 handler 결정이 없으면 pass는 accept, 재시도 가능한 실패는 revise, 그 밖의 실패는 escalate하는 기본 정책이 동작합니다. revision 지시는 human transcript를 보존한 채 dynamic system context에 한 번 주입됩니다. verification.decided는 후보 본문을 생략하고 SHA-256 digest와 handler별 결정을 session timeline에 남깁니다.
신뢰 미들웨어 4개 결합점
| 결합점 | 계약 |
|---|---|
tool_request | 승인 전 도구명·인자를 순차 변환하고 다시 스키마 검증 |
tool_execution | 승인된 요청을 변경하지 않고 실제 executor를 async onion으로 감쌈 |
llm_request | 조립된 adapter request를 순차 변환. 캐시 prefix 변경은 명시 권한과 사유가 필요 |
llm_execution | 요청을 변경하지 않고 provider 실행을 감싸거나 단축 반환 |
실행 미들웨어의 next_call은 한 번만 호출할 수 있습니다. 변환이 필요하면 반드시 request 결합점을 사용합니다.
내부 이벤트와 저장
현재 RuntimeEvent는 57개의 내부 관측 이벤트를 가집니다. HookEvent/HookSystem은 기존 통합을 위한 타입 별칭이며, 새 코드는 RuntimeEvent/RuntimeEventBus를 사용합니다.
| 저장소 | 동작 |
|---|---|
| SQLite activity store | 운영 이벤트의 정본. 공개 훅과 미들웨어 호출도 extension.invoked 행으로 저장 |
RunTimeline events.jsonl | 활성 run projection이 있을 때만 같은 typed activity row를 미러링 |
확장 호출 행은 표면, 이름, 확장자, 상태, 지연, 상관 ID만 보존합니다. 원문 사용자 입력, 전체 요청·응답, 개인 데이터, 비밀값은 저장하지 않습니다.
도구 경계 순서
tool_request → schema validation → PreToolUse → revalidation → hard deny / policy → PermissionRequest → pending-call checkpoint → effect admission → terminal executor 1회 호출 → TOOL_EXEC_ENDED or TOOL_EXEC_FAILED → PostToolUse → receipt commit
여기서 1회는 승인된 한 요청의 프로세스 내부 호출 횟수입니다. 외부 효과의 exactly-once를 뜻하지 않습니다. 변경·통신·관리 도구는 별도의 durable admission receipt로 같은 logical operation의 중복을 억제합니다. receipt에는 PostToolUse까지 끝난 결과를 저장하며, 완료 여부가 불명확하면 자동 재실행하지 않습니다.