gitea-agent: rework PR #9

Review-ID: 41
Previous-SHA: 15d8c75308
This commit is contained in:
gitea-agent
2000-01-01 00:00:00 +00:00
parent 15d8c75308
commit 85de08b2c6
2 changed files with 44 additions and 212 deletions
+43 -211
View File
@@ -6,9 +6,7 @@
"revision": "0.1", "revision": "0.1",
"status": "approved", "status": "approved",
"depends_on": [], "depends_on": [],
"applies_to": [ "applies_to": ["chat-tui-message-rendering"],
"chat-tui-message-rendering"
],
"language": "ko" "language": "ko"
} }
--- ---
@@ -17,234 +15,76 @@
## 1. 목적 ## 1. 목적
대화형 Textual TUI에서 사용자가 입력한 메시지와 에이전트의 응답을 작성자 라벨과 구조적 스타일로 명확하게 구분한다. 각 메시지의 작성자 의미를 명시적인 데이터 역할로 관리하여 화면 표시, 실행 흐름 및 자동 테스트에서 일관되게 검증할 수 있게 한다. 대화형 Textual TUI의 프로젝트 스캐폴드와 실행 기반을 보존하고, 메시지 작성자 의미를 명시적인 데이터 역할로 관리한다. 입력 정규화, 응답 선택, 메시지 누적 및 종료와 같은 대화 상호작용의 상세 규칙은 `REQ-002`에서 관리한다.
## 2. 배경 ## 2. 배경
현재 애플리케이션은 사용자 메시지와 에이전트 응답을 서로 다른 CSS 클래스를 가진 Label로 표시하지만 화면에 작성자 라벨이 없고 작성자 의미가 데이터 개념으로 표현되지 않는다. 따라서 메시지의 작성자를 화면에서 구분하기 어렵고, 테스트도 표시 순서와 내용만 검증할 뿐 작성자 역할과 구조적 구분을 검증하지 못한다. 애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI다. 기존 메시지 표시의 작성자 의미는 `ChatMessage`와 `MessageRole`로 표현되어야 하며, 화면 라벨과 구조적 스타일은 그 역할에서 파생되어야 한다. 이번 문서는 프로젝트 구조·패키징·실행 진입점과 승인된 작성자 모델을 보존하고, 대화 상호작용 규칙을 별도 요구사항으로 분리한다.
이번 요구사항은 외부 API나 LLM 연동 없이 현재 Textual 기반 대화 흐름을 유지하면서 작성자 의미를 명시적으로 모델링하고, 색상에만 의존하지 않는 라벨·테두리·정렬 기반의 구분을 제공하기 위한 것이다.
## 3. 범위 ## 3. 범위
포함 범위는 다음과 같다. 포함 범위는 Python 패키지 구조, 패키징 메타데이터, Textual 실행 기반, `chat_tui.app:main` 콘솔 실행 진입점과 승인된 메시지 작성자 모델이다. 작성자 모델은 `ChatMessage`와 `MessageRole`을 통해 사용자와 에이전트의 의미를 표현하고, 렌더러가 역할에서 라벨과 구조적 스타일을 파생할 수 있도록 한다.
- 사용자 메시지와 에이전트 응답을 각각 별도의 Label 대화 항목으로 표시한다. 제외 범위는 입력 정규화, 고정 응답 선택, 메시지 누적 순서, 빈 입력 처리, 입력창 초기화와 종료 단축키를 포함한 대화 상호작용의 세부 동작이다. 이러한 규칙과 인수 기준은 `REQ-002`에서 단일 정본으로 관리한다. 외부 API, LLM, 인증, 영속 저장소, 데이터베이스와 새 의존성도 추가하지 않는다.
- 각 메시지에 사용자 또는 에이전트라는 명시적인 작성자 역할을 부여한다.
- 화면에 사용자와 에이전트 작성자 라벨을 표시한다.
- `user-message`와 `response-message` 식별자를 유지하고, 테두리 또는 정렬 차이 같은 구조적 스타일을 적용한다.
- 유효한 입력의 정규화, 응답 선택, 메시지 표시 순서 및 공백 입력 무시 동작을 유지한다.
- 작성자 역할, 라벨, 구조적 스타일 및 기존 동작을 자동 테스트로 검증한다.
- 관련 요구사항, 데이터 모델, 인터페이스 계약 및 실행 흐름 문서와의 추적성을 유지한다.
제외 범위는 다음과 같다.
- LLM 연동 또는 외부 API 호출
- 대화 저장, 사용자 인증 또는 사용자별 기록 관리
- 고정 응답 목록과 응답 생성 방식의 변경
- 대화 영역 전체 레이아웃의 재설계
- 색상만으로 작성자를 구분하는 방식
- 별도 영속성 백엔드나 데이터베이스 도입
### 포함
대화형 Textual TUI에서 사용자 메시지와 에이전트 응답을 명시적인 작성자 역할로 관리하고, 사용자·에이전트 라벨과 구조적 스타일로 구분하여 표시한다. 유효한 입력의 정규화, 고정 응답 선택, 메시지 순서, 공백 입력 무시 및 관련 자동 검증을 포함한다.
### 제외
외부 API 또는 LLM 연동, 대화 저장과 사용자 인증, 고정 응답 목록과 생성 방식의 변경, 대화 영역 전체 레이아웃 재설계, 색상만으로 작성자를 구분하는 방식 및 별도 영속성 백엔드 도입은 포함하지 않는다.
## 4. 용어와 기준 ## 4. 용어와 기준
사용자 메시지는 입력창에 사용자가 제출한 공백 제거 후의 유효한 문자열이다. 에이전트 응답은 유효한 사용자 입력마다 고정된 응답 목록에서 표준 난수 선택으로 생성되는 문자열이다. 메시지 역할은 메시지를 작성한 주체를 나타내는 명시적인 값이며 `user` 또는 `agent` 중 하나다. 프로젝트 스캐폴드는 Python 패키지 구조, 선언된 런타임 의존성과 콘솔 실행 진입점의 조합을 뜻한다. 메시지 역할은 작성자 의미를 나타내는 `user` 또는 `agent` 값이며, `ChatMessage.role`과 `ChatMessage.content`가 작성자 의미의 정본이다. 사용자·에이전트 라벨과 CSS 클래스는 이 역할에서 파생되는 표시 정보다.
작성자 라벨은 사용자 역할을 `사용자`, 에이전트 역할을 `에이전트`로 화면에 표시하는 문자열이다. 구조적 스타일은 색상에만 의존하지 않고 CSS 클래스, 테두리 또는 정렬 차이로 작성자를 구분하는 표현이다.
정본 기준은 `ChatMessage.role`과 `ChatMessage.content`의 조합을 메시지 의미의 단일 기준으로 삼는 것이다. 작성자 라벨과 CSS 클래스는 이 역할에서 파생하며, CSS 클래스만으로 메시지 역할을 판정하지 않는다.
## 5. 요구사항 ## 5. 요구사항
`REQ-001`은 대화 메시지의 작성자 의미를 명시적으로 관리하고 화면 및 검증 절차에서 일관되게 구분하기 위한 요구사항 묶음의 식별자다. ### REQ-001.01 — 프로젝트 패키지와 실행 기반
시스템은 유효한 사용자 입력과 그에 대응하는 에이전트 응답을 각각 명시적인 작성자 역할을 가진 메시지로 관리해야 한다. 사용자 메시지의 역할은 `user`, 에이전트 응답의 역할은 `agent`여야 하며, 역할과 본문은 하나의 대화 메시지 단위로 보존되어야 한다. 이 요구사항은 `ChatMessage`, `MessageRole`, 대화 영역의 Label 렌더링, 세션 메모리의 메시지 목록 및 UI 렌더러와 자동 테스트에 영향을 준다. 유효한 입력의 정규화, 응답 선택, 입력·응답 배열 및 표시 순서는 유지하며 별도 영속성이나 마이그레이션은 필요하지 않다. 프로젝트는 Python 3.11 이상에서 현재 Textual 의존성을 사용하고, 기존 패키지 구조와 `chat_tui.app:main` 콘솔 실행 진입점을 유지해야 한다. 구현은 외부 API, LLM, 인증, 영속 저장소 또는 별도 데이터베이스를 추가하지 않아야 한다.
시스템은 각 메시지의 명시적인 역할을 작성자 라벨과 구조적 스타일로 변환하여 표시해야 한다. 사용자 메시지는 `사용자` 라벨과 `user-message` 식별자를 사용하고, 에이전트 응답은 `에이전트` 라벨과 `response-message` 식별자를 사용해야 한다. 사용자 Label에는 `chat-message user-message user-role` 클래스가 포함되고 에이전트 Label에는 `chat-message response-message agent-role` 클래스가 포함되어야 한다. 구조적 스타일은 색상만으로 작성자를 구분하지 않아야 하며 역할별 테두리 또는 정렬 차이를 포함해야 한다. 기존 식별자와 사용자·응답의 표시 순서는 유지하고, 화면 위젯과 세션 메모리만 변경하며 별도 영속성이나 마이그레이션은 필요하지 않다. ### REQ-001.02 — 승인된 메시지 작성자 모델
### REQ-001.01 — 명시적인 메시지 역할 관리 메시지 모델은 `ChatMessage`와 `MessageRole`을 통해 작성자 역할과 본문을 함께 표현해야 한다. 역할 값은 `user`와 `agent`이며, UI 렌더러는 역할에서 사용자·에이전트 라벨과 기존 `user-message`·`response-message` 식별자를 파생해야 한다. 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다.
시스템은 유효한 사용자 입력과 그에 대응하는 에이전트 응답을 각각 명시적인 작성자 역할을 가진 메시지로 관리해야 한다. 사용자 메시지의 역할은 user, 에이전트 응답의 역할은 agent여야 하며, 역할과 본문은 하나의 대화 메시지 단위로 함께 보존되어야 한다. 유효한 입력의 정규화, 응답 선택, 메시지 목록의 순서와 기존 세션 내 동작은 유지해야 한다.
**영향 범위**
인터페이스는 ChatMessage, MessageRole 및 대화 영역의 Label 렌더링에 영향을 받는다. 영속성은 없으며 메시지는 애플리케이션 세션 메모리에만 유지한다. 후속 사용 주체는 UI 렌더러와 자동 테스트다. 마이그레이션은 필요하지 않다. Python 3.11 이상과 현재 Textual 실행 환경을 유지한다.
### REQ-001.02 — 작성자 라벨과 구조적 표시
시스템은 각 메시지의 명시적인 역할을 작성자 라벨과 구조적 스타일로 변환하여 표시해야 한다. 사용자 메시지는 사용자 라벨과 user-message 식별자를 사용하고, 에이전트 응답은 에이전트 라벨과 response-message 식별자를 사용해야 한다. 구조적 스타일은 색상만으로 작성자를 구분하지 않아야 하며 역할별 테두리 또는 정렬 차이를 포함해야 한다.
**영향 범위**
인터페이스는 conversation 영역 내부 Label의 표시 문자열과 CSS 클래스에 영향을 받는다. 영속성은 없으며 화면 위젯과 세션 메모리만 변경한다. 후속 사용 주체는 사용자, UI 검수자 및 자동 회귀 테스트다. 마이그레이션은 필요하지 않다. Textual의 Label, VerticalScroll 및 CSS 스타일 기능을 사용할 수 있어야 한다.
## 6. 제약과 불변조건 ## 6. 제약과 불변조건
- Python 3.11 이상과 현재 Textual 기반 TUI 구조를 유지한다. - Python 3.11 이상과 현재 Textual 기반 TUI 구조 및 선언된 의존성을 유지한다.
- 유효한 입력은 앞뒤 공백을 제거한 뒤 사용자 메시지로 한 번만 기록한다. - `chat_tui.app:main` 콘솔 실행 진입점과 기존 패키지 위치를 유지한다.
- 공백만 있거나 빈 입력은 응답을 선택하지 않고 메시지 목록과 화면을 변경하지 않는다. - 메시지의 작성자 의미는 CSS 클래스나 화면 색상에서 추론하지 않고 명시적인 `MessageRole` 값에서 확인한다.
- 유효한 입력 하나마다 사용자 메시지가 먼저 표시되고 그 뒤에 에이전트 응답이 표시되어야 한다. - 사용자와 에이전트의 라벨 및 구조적 스타일은 역할과 일치해야 한다.
- 에이전트 응답은 기존 고정 응답 목록에서 표준 난수 선택으로 결정한다. - 입력 처리와 응답 동작의 상세 규칙은 이 문서에 복제하지 않고 `REQ-002`를 따른다.
- 모든 메시지는 명시적인 메시지 역할을 통해 작성자 의미를 가져야 하며 CSS 클래스만으로 역할을 판정하지 않는다. - 외부 API, LLM, 인증, 영속 저장소, 데이터베이스 및 새 의존성은 추가하지 않는다.
- 사용자와 에이전트는 화면의 텍스트 라벨로 구분되어야 한다.
- 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다.
- 메시지 표시와 테스트에서 사용자 및 에이전트 역할의 순서와 의미가 일치해야 한다.
- 외부 API, 인증, 영속 저장소 및 민감정보 처리는 추가하지 않는다.
## 7. 인수 기준 ## 7. 인수 기준
인수 기준은 각 소속 요구사항을 포함하는 식별 체계로 관리하며, 판정 조건과 검증 방법 및 상태 불변조건을 함께 기록한다. ### REQ-001.01-AC01 — 패키지와 실행 진입점 보존
**메시지 역할이 순서대로 보존됨** 프로젝트가 Python 3.11 이상과 선언된 Textual 의존성으로 설치되고 `chat_tui.app:main` 진입점을 계속 제공하면 통과로 판정한다. 이 기준은 프로젝트 구조와 실행 기반만 검증하며 대화 상호작용의 판정은 `REQ-002`에 위임한다.
판정 기준은 유효한 입력의 앞뒤 공백이 제거된 사용자 메시지가 사용자 역할로 기록되고, 같은 제출에서 선택된 응답이 에이전트 역할로 기록되는지 확인하는 것이다. 여러 입력을 제출할 때 메시지 목록은 각 입력에 대해 사용자 메시지 다음에 에이전트 응답이 오는 순서를 유지해야 하며, 역할과 본문은 함께 비교 가능해야 한다. 역할은 CSS 클래스에서 추론하지 않는다. ### REQ-001.02-AC01 — 역할이 작성자 표시의 정본임
검증은 Textual 테스트 앱에서 두 개의 유효한 입력을 제출하고 제출 입력, 선택 응답 및 메시지의 값과 순서를 비교하는 방식으로 수행한다. 메시지가 사용자와 에이전트 역할을 번갈아 포함하는지 확인하고, 응답 선택을 고정하여 입력 정규화와 역할 보존을 결정적으로 검증한다. 검증 수준은 통합 테스트이며 별도 백엔드는 없고 정상 사례를 대상으로 한다. `ChatMessage`가 `MessageRole`과 본문을 함께 보유하고, 사용자와 에이전트 표시의 라벨·식별자·구조적 스타일이 그 역할에서 파생되며 색상만으로 역할을 판정하지 않으면 통과로 판정한다.
성공하면 입력과 응답이 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다. 기존 입력과 응답의 순서 및 내용은 변경되지 않아야 하며, 실패 또는 공백 입력에서는 응답 선택과 메시지 추가가 발생하지 않아야 한다.
**공백 입력이 역할 없는 메시지를 만들지 않음**
판정 기준은 빈 문자열 또는 공백, 탭, 개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않고 응답 선택 함수가 호출되지 않는지 확인하는 것이다. 제출 후 입력창은 비워져야 한다.
검증은 공백만 포함한 입력과 빈 입력을 각각 Textual 테스트 앱에 제출하고 메시지 목록과 대화 영역 항목 수가 변경되지 않는지 확인하는 방식으로 수행한다. 응답 선택 함수가 호출되지 않았는지와 입력창이 비워지는지를 확인한다. 검증 수준은 통합 테스트이며 경계 사례를 대상으로 한다.
무시 처리가 성공하면 메시지 목록, 제출 입력 기록 및 응답 기록은 변경되지 않아야 한다. 대화 영역에 작성자 라벨을 포함한 새 항목이 추가되어서는 안 되며, 실패 시 부분적인 사용자 메시지 또는 응답이 남아서는 안 된다.
**작성자 라벨과 구조적 스타일이 역할과 일치함**
판정 기준은 사용자 메시지가 사용자 라벨과 사용자 식별자를 사용하고, 에이전트 응답이 에이전트 라벨과 에이전트 식별자를 사용하는지 확인하는 것이다. 사용자 표시에는 사용자 역할 클래스가, 에이전트 표시에는 에이전트 역할 클래스가 포함되어야 한다. CSS에는 양쪽 역할의 구조적 차이를 나타내는 테두리 또는 정렬 규칙이 있어야 한다.
검증은 유효한 입력 하나를 제출하고 대화 영역의 두 표시 항목을 조회하여 렌더링 문자열과 클래스가 각각의 역할과 일치하는지 확인하는 방식으로 수행한다. 애플리케이션 CSS에 역할별 테두리와 정렬 규칙이 포함되는지도 확인한다. 검증 수준은 통합 테스트이며 정상 사례를 대상으로 한다.
성공하면 각 메시지의 라벨과 구조적 클래스가 해당 역할과 일치해야 한다. 메시지 본문, 표시 순서 및 기존 식별자는 변경되지 않아야 하며, 렌더링 실패 시 다른 역할의 라벨이나 일부만 표시된 메시지가 남아서는 안 된다.
**기존 응답 선택과 종료 동작을 보존함**
판정 기준은 유효한 입력 제출 시 기존 응답 목록을 인자로 하여 표준 난수 선택이 한 번 호출되고, Escape 입력이 기존처럼 애플리케이션 종료를 요청하는지 확인하는 것이다. 작성자 구분 기능을 추가해도 기존 입력과 응답 회귀 검증이 통과해야 한다.
검증은 난수 선택을 모의 처리하여 고정 응답 목록이 전달되는지 확인하고, Textual 테스트 앱에서 Escape를 입력하여 종료 요청을 확인하는 방식으로 수행한다. 유효 입력 두 건의 정규화, 응답 내용, 표시 순서 및 입력창 초기화를 함께 검증한다. 검증 수준은 통합 테스트이며 변경 없음 사례를 대상으로 한다.
성공하면 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다. 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되어서는 안 되며, 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다.
### REQ-001.01-AC01 — 메시지 역할이 제출 순서대로 보존됨
**판정 기준**
유효한 사용자 입력을 제출하면 앞뒤 공백이 제거된 본문이 user 역할로 기록되고, 같은 제출에서 선택된 응답이 agent 역할로 기록되어야 한다. 여러 입력을 제출하면 각 입력에 대해 사용자 메시지 다음에 에이전트 응답이 배치되어야 하며, 역할은 CSS 클래스가 아니라 메시지 데이터에서 확인할 수 있어야 한다.
**검증**
Textual 테스트 앱에서 두 개 이상의 유효한 입력을 제출하고 submitted_inputs, selected_responses 및 messages의 값과 순서를 비교한다. 응답 선택을 고정하여 입력 정규화와 역할 보존을 결정적으로 검증한다.
**검증 분류**
integration
**상태 불변조건**
성공 시 입력과 응답은 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다. 기존 입력과 응답의 순서 및 내용은 변경되지 않아야 한다. 실패 또는 공백 입력에서는 응답 선택과 메시지 목록 추가가 발생하지 않아야 한다.
### REQ-001.01-AC02 — 공백 입력이 역할 없는 메시지를 만들지 않음
**판정 기준**
빈 문자열 또는 공백, 탭, 개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않아야 한다. 공백 입력에서는 응답 선택 함수가 호출되지 않아야 하며, 제출 후 입력창은 비워져야 한다.
**검증**
공백만 포함한 입력과 빈 입력을 각각 Textual 테스트 앱에 제출한다. 메시지 목록과 대화 영역의 항목 수가 변하지 않는지 확인하고, random.choice가 호출되지 않았으며 입력창 값이 비워지는지 검증한다.
**검증 분류**
integration
**상태 불변조건**
무시 처리 후 메시지 목록, 제출 입력 기록 및 응답 기록은 변경되지 않아야 한다. 작성자 라벨을 포함한 새 화면 항목이 추가되면 안 된다. 실패 시 부분적인 사용자 메시지 또는 응답이 남아서는 안 된다.
### REQ-001.02-AC01 — 작성자 라벨과 구조적 스타일이 역할과 일치함
**판정 기준**
사용자 메시지는 사용자: 본문 형식으로, 에이전트 응답은 에이전트: 본문 형식으로 표시되어야 한다. 사용자 Label에는 chat-message, user-message, user-role 클래스가 포함되고 에이전트 Label에는 chat-message, response-message, agent-role 클래스가 포함되어야 한다. CSS에는 양쪽 역할의 구조적 차이를 나타내는 테두리와 역할별 정렬 규칙이 있어야 한다.
**검증**
유효한 입력 하나를 제출하고 대화 영역의 Label 두 개를 조회한다. 렌더링 문자열과 클래스를 각각의 역할과 비교하고, 애플리케이션 CSS에서 사용자와 에이전트의 테두리 및 정렬 규칙을 확인한다.
**검증 분류**
integration
**상태 불변조건**
성공 시 각 메시지의 라벨과 구조적 클래스는 해당 역할과 일치해야 한다. 메시지 본문, 표시 순서 및 기존 식별자는 변경되지 않아야 한다. 렌더링 실패 시 서로 다른 역할의 라벨이 표시되거나 일부만 표시된 메시지가 남아서는 안 된다.
### REQ-001.02-AC02 — 기존 응답 선택과 종료 동작을 보존함
**판정 기준**
유효한 입력 제출 시 기존 응답 목록을 대상으로 표준 random.choice가 한 번 호출되어야 한다. Escape 키 입력은 애플리케이션 종료를 요청해야 하며, 작성자 구분 기능을 추가해도 기존 입력과 응답의 정규화, 내용, 표시 순서 및 입력창 초기화 동작이 유지되어야 한다.
**검증**
random.choice를 모의 처리하여 기존 응답 목록이 전달되는지 확인한다. Textual 테스트 앱에서 Escape를 입력하고 종료 요청을 확인한 뒤, 두 개의 유효 입력을 제출하여 정규화, 응답 내용, 표시 순서 및 입력창 초기화를 함께 검증한다.
**검증 분류**
integration
**상태 불변조건**
유효 입력 성공 시 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다. 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되어서는 안 된다. 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다.
## 8. 오류 및 충돌 계약 ## 8. 오류 및 충돌 계약
- 입력 오류: 빈 입력과 공백 입력은 오류를 표시하지 않고 무시하며, 응답 선택과 메시지 추가를 수행하지 않는다. - 프로젝트 설치 또는 콘솔 진입점이 제공되지 않으면 스캐폴드 요구사항을 충족한 것으로 판정하지 않는다.
- 상태 충돌: 단일 Textual 이벤트 루프에서 제출 이벤트 순서를 처리하며, 동일 입력을 자동으로 중복 제출하지 않는다. - 정의되지 않은 메시지 역할은 정상 표시하지 않으며 역할과 라벨의 매핑은 명시적인 기준을 따른다.
- 저장 실패: 영속 저장소가 없으므로 저장 실패와 롤백 대상이 없다. 렌더링 실패가 발생하더라도 별도의 부분 영속 기록을 만들지 않는다. - 프로젝트 구조·패키징·실행 기반에 관한 충돌은 이 문서를 따른다.
- 역할 오류: 사용자 또는 에이전트로 정의되지 않은 역할은 정상 메시지로 렌더링하지 않으며, 역할 값과 표시 라벨의 매핑은 한 곳의 명시적 기준을 따른다. - 입력·응답·누적·입력창·종료 동작에 관한 충돌은 `REQ-002`를 따른다.
## 9. 데이터 및 인터페이스 계약 ## 9. 데이터 및 인터페이스 계약
- 메시지 역할은 문자열 기반 열거형으로 관리하며 사용자 역할의 값은 `user`, 에이전트 역할의 값은 `agent`이다. - `MessageRole`은 문자열 기반 열거형이며 값은 `user` 또는 `agent`다.
- 각 대화 메시지는 필수 역할 값과 필수 본문 문자열을 함께 보유하여 작성자와 내용을 하나의 단위로 표현한다. - `ChatMessage.role`은 필수 역할 값이고 `ChatMessage.content`는 필수 본문 문자열이다.
- 본문은 앞뒤 공백 제거가 완료된 사용자 입력 또는 선택된 응답을 담는다. - 역할에서 사용자 라벨 `사용자` 또는 에이전트 라벨 `에이전트`를 파생할 수 있어야 한다.
- 역할은 사용자 라벨인 `사용자` 또는 에이전트 라벨인 `에이전트`로 변환할 수 있어야 한다. - 사용자 표시 항목은 `chat-message user-message user-role` 식별자를, 에이전트 표시 항목은 `chat-message response-message agent-role` 식별자를 사용한다.
- 세션 메시지 목록은 제출 순서를 보유하며 유효한 입력마다 사용자 메시지와 에이전트 응답을 차례로 추가한다. - 상세 입력·응답·세션 누적 계약은 `REQ-002`에 정의한다.
- 사용자 표시값은 `사용자: 본문` 형식이고 에이전트 표시값은 `에이전트: 본문` 형식이다.
- 사용자 표시 항목은 사용자 메시지 식별자와 사용자 역할 식별자를 포함하고, 에이전트 표시 항목은 응답 메시지 식별자와 에이전트 역할 식별자를 포함한다.
- 제출 입력 기록, 선택 응답 기록 및 기존 고정 응답 목록 계약은 유지한다.
- 식별자는 세션 내 메모리 객체와 CSS 클래스에 한정되며 시간대, 단위 및 정밀도 계약은 없다.
## 10. 하위 호환성 ## 10. 하위 호환성
- Python 3.11 이상에서 실행되는 기존 패키지와 콘솔 실행 진입점을 유지한다. - Python 3.11 이상, 현재 Textual 런타임 의존성, 패키지 위치 및 `chat_tui.app:main` 진입점을 유지한다.
- 대화 영역과 입력 위젯의 기존 식별자를 유지한다. - 기존 `#conversation`과 `#user-input` 식별자를 유지한다.
- 사용자 메시지와 에이전트 응답의 표시 항목 구조 및 표시 순서를 유지하되 표시 문자열과 역할 클래스를 통해 작성자 정보를 추가한다. - 작성자 모델과 역할별 표시를 추가해도 대화 영역 전체 레이아웃을 재설계하지 않는다.
- Enter 제출, 앞뒤 공백 제거, 공백 입력 무시, 고정 응답 목록 선택, Escape 및 Ctrl+Q 종료 동작을 유지한다. - 입력 제출, 응답 선택, 입력창 초기화와 종료 동작은 `REQ-002`의 기존 계약을 따른다.
- 기존 영속 데이터가 없으므로 데이터 마이그레이션은 필요하지 않다.
- 작성자 라벨과 구조적 스타일은 추가하지만 대화 영역 전체 레이아웃을 재설계하지 않는다.
- 외부 API, LLM 연동, 인증, 영속 저장소 및 별도 데이터베이스를 추가하지 않는다.
## 11. 검증 계획 ## 11. 검증 계획
Textual 테스트 앱에서 정상 입력, 여러 메시지의 순서, 메시지 역할 객체, 작성자 라벨과 구조적 CSS 클래스를 검증한다. 입력값의 앞뒤 공백이 제거되는지, 유효한 입력마다 사용자 메시지와 에이전트 응답이 차례로 추가되는지, 기존 메시지가 삭제되거나 재배열되지 않는지 확인한다. 패키지 메타데이터와 콘솔 진입점이 Python 3.11 이상 및 선언된 Textual 환경에서 제공되는지 확인한다. `ChatMessage`와 `MessageRole`의 역할-본문 모델, 역할별 라벨과 식별자, 테두리 또는 정렬 기반 스타일을 검증한다. 입력 정규화, 응답 선택, 메시지 순서, 빈 입력, 입력창 초기화와 종료 단축키의 실행 검증은 `REQ-002`의 테스트 추적성 계약에서 관리한다.
빈 문자열과 공백·탭·개행만 포함한 입력을 각각 제출하여 응답 선택이 호출되지 않고 메시지 목록과 대화 영역이 변경되지 않으며 입력창만 비워지는지 검증한다. 응답 선택을 고정하거나 모의 처리하여 정본 응답 목록이 전달되고 선택된 응답이 에이전트 메시지로 표시되는지 확인한다.
사용자 메시지와 에이전트 응답의 표시 문자열, 역할, 식별자 및 구조적 스타일을 비교하고, 역할별 테두리 또는 정렬 차이가 색상에만 의존하지 않는지 확인한다. Escape와 Ctrl+Q 입력이 동일한 종료 동작을 요청하며 메시지 제출이나 응답 선택을 발생시키지 않는지도 회귀 검증한다.
실행 가능한 테스트 정의는 별도 테스트 카탈로그에서 관리하고, 요구사항 문서에는 검증 의도와 판정 조건만 기록한다. 실행 결과는 별도 증거 산출물에 기록하며, 실제로 실행하지 않은 검증은 성공으로 기록하지 않는다. 외부 API, 영속성 백엔드 및 데이터베이스를 사용하지 않으므로 저장 후 재조회와 마이그레이션 검증은 해당 없음으로 판정한다. 관련 요구사항과 데이터 모델, 인터페이스 계약 및 실행 흐름 문서의 역할·라벨·스타일·순서 설명이 구현 및 테스트와 일치하는지도 문서 검토로 확인한다.
### 테스트 추적성 계약 ### 테스트 추적성 계약
@@ -254,11 +94,9 @@ Textual 테스트 앱에서 정상 입력, 여러 메시지의 순서, 메시지
Test ID: TC-001-001 Test ID: TC-001-001
Verifies: Verifies:
- REQ-001.01-AC01 - REQ-001.01-AC01
- REQ-001.01-AC02
- REQ-001.02-AC01 - REQ-001.02-AC01
- REQ-001.02-AC02 Test reference: 프로젝트 패키징 검사와 Textual 애플리케이션 테스트
Test reference: tests/test_app.py의 Textual 애플리케이션 테스트 Automated: 패키지 진입점, 메시지 역할 모델, 역할별 라벨·식별자·구조적 스타일을 자동 검증한다.
Automated: Textual 테스트 앱에서 작성자 역할, 라벨, 구조적 스타일, 입력 정규화, 응답 선택, 표시 순서와 공백 입력 무시 동작을 자동 검증한다.
``` ```
실행 증거: 실행 증거:
@@ -267,26 +105,18 @@ Automated: Textual 테스트 앱에서 작성자 역할, 라벨, 구조적 스
Test ID: TC-001-001 Test ID: TC-001-001
Requirement revision: REQ-001@0.1 Requirement revision: REQ-001@0.1
Commit: 실행 증거 미기록 Commit: 실행 증거 미기록
Environment: Python 3.11 이상, 현재 Textual 테스트 앱, 영속 백엔드 없음 Environment: Python 3.11 이상, 선언된 Textual 런타임 의존성
Result: 미실행 Result: 미실행
Executed at: 검증 실행 시각 미기록 Executed at: 검증 실행 시각 미기록
``` ```
## 12. 추적성 ## 12. 추적성
근거 이슈는 Gitea 이슈 #6인 메시지 표시창의 메시지 작성자 구분 요청이다. 구현 PR은 아직 없으며, 관련 설계 문서는 데이터 모델, 인터페이스 계약, 런타임 흐름 및 프로젝트 구조 문서다. 근거 이슈는 Gitea 이슈 #6인 메시지 표시창의 메시지 작성자 구분 요청이다. 구현 PR은 아직 없으며, 관련 설계 문서는 데이터 모델, 인터페이스 계약, 런타임 흐름 및 프로젝트 구조 문서다. 이 문서는 프로젝트 스캐폴드와 승인된 작성자 모델의 정체성을 보존하고, 대화 상호작용의 상세 규칙은 `REQ-002`의 원본 Gitea 이슈 #8 추적성으로 분리한다.
이 문서는 대화 메시지의 역할과 본문을 정본으로 삼고, 사용자와 에이전트의 라벨·식별자·구조적 스타일 및 표시 순서를 구현과 테스트에서 일관되게 추적한다. 입력 정규화, 고정 응답 선택, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 계약으로 보존하며 작성자 구분을 위해 의미를 변경하지 않는다.
역할은 CSS 클래스나 화면 색상에서 추론하지 않고 명시적인 메시지 데이터에서 확인해야 한다. 테스트는 메시지 역할과 본문, 렌더링 라벨과 클래스, 표시 순서 및 기존 동작의 보존 여부를 함께 비교하며, 실행 결과와 커밋 결합 정보는 별도 증거 산출물에서 관리한다.
## 13. 확정된 결정 ## 13. 확정된 결정
사용자 메시지와 에이전트 응답은 명시적인 작성자 역할과 본문을 함께 가진 대화 메시지로 관리한다. 사용자 역할은 user이고 에이전트 역할은 agent이며, 화면의 라벨과 구조적 스타일은 이 역할에서 파생한다. 프로젝트의 Python 패키지 구조, Textual 실행 기반과 `chat_tui.app:main` 진입점을 유지한다. 메시지 작성자 의미는 `MessageRole`과 `ChatMessage`에 명시적으로 보존하고 라벨·식별자·구조적 스타일은 역할에서 파생한다. 입력과 응답의 세부 동작은 `REQ-002`에서 관리한다.
사용자 메시지는 사용자 라벨과 사용자 식별자를 사용하고 에이전트 응답은 에이전트 라벨과 응답 식별자를 사용한다. 역할 구분은 색상에만 의존하지 않으며 역할별 테두리 또는 정렬 차이를 포함한다.
유효한 입력의 앞뒤 공백 제거, 고정 응답 목록에서의 표준 난수 선택, 사용자 메시지 뒤에 에이전트 응답을 표시하는 순서, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 의미를 유지한다. 외부 API, LLM, 인증, 영속 저장소 및 데이터베이스는 추가하지 않는다.
## 14. 미결 사항 ## 14. 미결 사항
@@ -294,6 +124,8 @@ Executed at: 검증 실행 시각 미기록
## 15. 승인 기록 ## 15. 승인 기록
이 요구사항은 approved 상태로 승인되었다. 승인 주체는 spec-agent이며, 승인 근거는 승인 댓글 923 및 디스커버리 승인 결과다. - 상태: `approved`
- 승인 주체: `spec-agent`
- 승인 근거: 승인 댓글 923 및 디스커버리 승인 결과
작성자 구분을 명시적인 메시지 역할과 역할에서 파생되는 라벨 및 구조적 스타일로 관리하는 범위는 승인된 정본의 의미로 보존한다. 문서 정리나 관련 문서와의 정합성 검토만으로 승인 상태, 승인 주체 또는 승인 근거를 변경하지 않는다. 문서 분리와 정리만으로 기존 승인 상태, 승인 주체 또는 승인 근거를 변경하지 않는다.
@@ -453,7 +453,7 @@ Executed at: 검증 실행 시각 미기록
## 12. 추적성 ## 12. 추적성
근거는 원본 Gitea 이슈 #8인 요구사항명세서 재작업 요청, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소의 사용자 동작 설명, 애플리케이션 구현 및 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 그 패키징과 실행 계약을 변경하거나 다시 정의하지 않는다. 근거는 원본 Gitea 이슈 #8인 요구사항명세서 재작업 요청([Gitea 이슈 #8](https://gitea.jsfamily.quest/genichin/gitea-agent-testbed/issues/8)), 기존 프로젝트 스캐폴드 요구사항 문서, 저장소의 사용자 동작 설명, 애플리케이션 구현 및 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 그 패키징과 실행 계약을 변경하거나 다시 정의하지 않는다.
입력 양끝 공백 제거, 유효 입력 판정, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 프로젝트 구조, 패키징 메타데이터와 실행 진입점은 선행 요구사항 문서에서 추적하므로 이 문서에서는 상세 규칙과 인수 기준을 중복 정의하지 않는다. 입력 양끝 공백 제거, 유효 입력 판정, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 프로젝트 구조, 패키징 메타데이터와 실행 진입점은 선행 요구사항 문서에서 추적하므로 이 문서에서는 상세 규칙과 인수 기준을 중복 정의하지 않는다.