ADR: 심덩 Architecture Decision Records#
문서 목적#
이 문서는 심덩 Discord Codex assistant의 핵심 아키텍처 결정을 기록한다. PRD가 요구사항을 설명하고 SSOT가 기준 출처를 정한다면, ADR은 중요한 설계 결정을 왜 그렇게 했는지 남긴다.
적용 범위#
- Discord bot과 agent-runtime의 책임 분리
- approval metadata 저장 방식
- 자연어 intent classifier 회피
- write-agent 산출물 경계
관련 문서#
ADR-001: Discord bot은 UI adapter로 제한하고 agent-runtime이 workflow를 소유한다#
상태#
Accepted
맥락#
심덩은 Discord에서 요청을 받고 결과를 보여준다. 하지만 workflow state, Codex thread control, approval, write-agent orchestration, runtime store 접근까지 Discord bot이 모두 맡으면 UI 코드가 실행 정책과 상태 관리까지 소유하게 된다.
이는 다음 문제를 만든다.
- Discord UI 변경이 workflow 안정성에 영향을 준다.
- 승인 범위 판단이 여러 위치에 흩어진다.
- write-agent path validation과 artifact parsing 책임이 불분명해진다.
- 테스트가 Discord mock 중심으로 과도하게 복잡해진다.
결정#
Discord bot은 UI adapter로 제한한다.
- Discord bot: 메시지 수신, 버튼 표시, 상태 렌더링, 결과 전달
- agent-runtime: workflow state, Codex thread control, approval, write-agent orchestration, runtime stores, final approval-scope decisions
결과#
장점:
- 상태 소유권이 명확하다.
- 승인과 workflow 검증을 agent-runtime 중심으로 테스트할 수 있다.
- Discord UI가 바뀌어도 핵심 실행 정책은 유지된다.
단점:
- agent-runtime API와 DTO 설계가 필요하다.
- Discord bot은 단순해지지만 agent-runtime의 책임은 커진다.
연결 문서#
- PRD: “안전한 실행 경계”, “상태 추적” 목표
- SSOT: workflow 상태의 기준은 agent-runtime store
- BDD: Discord bot이 workflow state를 직접 수정하지 않는 시나리오
ADR-002: 승인 버튼에는 approval id만 넣고 scope는 server-side에서 조회한다#
상태#
Accepted
맥락#
Discord 버튼의 custom_id에 action, repo, cwd, command, scope를 모두 넣으면 payload가 길어지고 조작 위험이 커진다. 또한 승인 범위가 UI payload와 server store 사이에서 불일치할 수 있다.
결정#
승인 버튼 custom_id에는 approval id만 포함한다. 실제 action, scope, repo, cwd, request metadata는 agent-runtime approval store에 저장한다.
결과#
장점:
- Discord payload에 민감하거나 복잡한 승인 정보를 넣지 않는다.
- 승인 처리 시 server-side 기준만 사용한다.
- audit trail을 approval store 중심으로 남길 수 있다.
단점:
- approval store 조회 실패 시 버튼 클릭을 처리할 수 없다.
- 승인 record lifecycle 관리가 필요하다.
연결 문서#
- PRD: 승인 필요한 작업 흐름
- SSOT: approval metadata의 최종 기준
- BDD: 승인 버튼 클릭 시 approval id로 scope를 조회하는 시나리오
ADR-003: 자연어 intent를 하드코딩된 classifier로 만들지 않는다#
상태#
Accepted
맥락#
Discord 사용자는 자연어로 요청한다. 하지만 특정 단어, regex, 키워드 테이블로 intent나 권한을 판정하면 쉽게 우회되거나 오분류된다.
예를 들어 “삭제해줘”라는 단어만 보고 destructive command로 확정하거나, “관리자 승인”이라는 문구만 보고 권한이 있다고 판단하면 안 된다.
결정#
자연어는 current-turn reasoning의 입력으로만 사용한다. 최종 판단에는 structured input, Discord metadata, server-side role, repo allow-list, approval record, handoff operation 같은 authoritative metadata를 사용한다.
결과#
장점:
- prompt injection과 phrasing 우회 위험이 줄어든다.
- 정책 판단과 권한 판단이 코드의 키워드 테이블에 묶이지 않는다.
- 애매한 요청은 clarification이나 승인 요청으로 처리할 수 있다.
단점:
- 단순 keyword router보다 구현이 느릴 수 있다.
- structured metadata 설계가 중요해진다.
연결 문서#
- PRD: 안전한 실행 경계
- SSOT: 자연어보다 metadata를 우선하는 기준
- BDD: 자연어만으로 권한을 부여하지 않는 시나리오
ADR-004: write-agent는 선언된 artifact path 안에서만 산출물을 생성한다#
상태#
Accepted
맥락#
write-agent는 Markdown, HTML, JSON, SVG 같은 산출물을 만들 수 있다. 그러나 요청 본문이나 소스 문서 안에 “다른 경로에 저장하라”는 지시가 들어 있을 수 있다. 이 지시를 따르면 path traversal이나 원치 않는 파일 변경이 발생할 수 있다.
결정#
write-agent는 structured handoff의 declared paths를 최종 출력 경계로 사용한다. data/runtime/write-agents/<topic>/ 아래 선언된 path만 반환하고, 허용 확장자만 사용한다.
결과#
장점:
- 산출물 저장 위치가 예측 가능하다.
- Discord delivery와 artifact 관리가 단순해진다.
- prompt injection이 출력 경로를 바꾸기 어렵다.
단점:
- 추가 산출물이 필요하면 handoff에 path를 다시 선언해야 한다.
연결 문서#
- PRD: 산출물 관리 목표
- SSOT: write-agent artifact path의 최종 기준
- BDD: 선언되지 않은 path를 만들지 않는 시나리오
WTF 후보 감지: ADR을 보강해야 하는 신호#
다음 의문이 나오면 ADR을 보강한다.
- “왜 Discord bot이 상태를 가지면 안 되지?”
- “왜 버튼에 전체 scope를 넣지 않고 approval id만 넣지?”
- “왜 regex intent router를 쓰면 안 되지?”
- “왜 write-agent가 원하는 파일을 자유롭게 만들면 안 되지?”
ADR은 이미 선택한 구조적 결정을 설명한다. 요구사항 자체가 불분명하면 PRD, 기준 출처가 불분명하면 SSOT, 동작 검증이 부족하면 BDD를 보강한다.