code-agent: implement issue 8
Approval-Correlation: a1502ebfff533b69c158f3c6c1316c01
Plan-SHA256: aae2d7573d66fb5573378443712149a4f7ba23f7f9de19e25b00f9b760d05c3e
Bundle-SHA256: 29ce1ef1917864f79938459725201e6e74d67e21b1f817ac53d7b294eca8f1a2
Base-SHA: d0ac7fc7bc
This commit is contained in:
@@ -2,296 +2,262 @@
|
||||
{
|
||||
"schema": "proofline.requirement/v1",
|
||||
"id": "REQ-001",
|
||||
"title": "프로젝트 스캐폴드의 메시지 작성자 구분",
|
||||
"title": "프로젝트 스캐폴드와 실행 진입점",
|
||||
"revision": "0.1",
|
||||
"status": "approved",
|
||||
"status": "draft",
|
||||
"depends_on": [],
|
||||
"applies_to": ["chat-tui-message-rendering"],
|
||||
"applies_to": [
|
||||
"프로젝트 스캐폴드",
|
||||
"Python 패키징",
|
||||
"콘솔 실행 진입점"
|
||||
],
|
||||
"language": "ko"
|
||||
}
|
||||
---
|
||||
|
||||
# REQ-001 — 프로젝트 스캐폴드의 메시지 작성자 구분
|
||||
# REQ-001 — 프로젝트 스캐폴드와 실행 진입점
|
||||
|
||||
## 1. 목적
|
||||
|
||||
대화형 Textual TUI에서 사용자가 입력한 메시지와 에이전트의 응답을 작성자 라벨과 구조적 스타일로 명확하게 구분한다. 각 메시지의 작성자 의미를 명시적인 데이터 역할로 관리하여 화면 표시, 실행 흐름 및 자동 테스트에서 일관되게 검증할 수 있게 한다.
|
||||
이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 지정된 콘솔 명령 또는 모듈 실행 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 이 범위에 포함하지 않는다.
|
||||
|
||||
## 2. 배경
|
||||
|
||||
현재 애플리케이션은 사용자 메시지와 에이전트 응답을 서로 다른 CSS 클래스를 가진 Label로 표시하지만 화면에 작성자 라벨이 없고 작성자 의미가 데이터 개념으로 표현되지 않는다. 따라서 메시지의 작성자를 화면에서 구분하기 어렵고, 테스트도 표시 순서와 내용만 검증할 뿐 작성자 역할과 구조적 구분을 검증하지 못한다.
|
||||
|
||||
이번 요구사항은 외부 API나 LLM 연동 없이 현재 Textual 기반 대화 흐름을 유지하면서 작성자 의미를 명시적으로 모델링하고, 색상에만 의존하지 않는 라벨·테두리·정렬 기반의 구분을 제공하기 위한 것이다.
|
||||
프로젝트는 소스 코드를 `src` 레이아웃 아래에 두고 `chat_tui` 패키지로 제공한다. 패키징은 setuptools 빌드 백엔드를 사용하며 Python 3.11 이상을 실행 환경으로 요구한다. 런타임에는 Textual 0.47 이상 1.0 미만을 사용하고, 테스트용 선택 의존성으로 pytest 8.0 이상을 제공한다. 패키지 버전은 현재 0.1.0으로 관리한다.
|
||||
|
||||
## 3. 범위
|
||||
|
||||
포함 범위는 다음과 같다.
|
||||
|
||||
- `src/chat_tui` Python 패키지의 기본 구조와 패키지 버전 공개
|
||||
- `pyproject.toml`의 빌드 시스템, 프로젝트 메타데이터, Python 버전, 런타임 및 테스트 의존성 정의
|
||||
- `chat-tui` 콘솔 스크립트가 애플리케이션의 실행 함수를 호출하는 진입점 제공
|
||||
- `python -m chat_tui` 방식으로 패키지를 실행할 수 있는 모듈 진입점 제공
|
||||
- 소스 디렉터리를 패키지 탐색 대상으로 사용하는 설치 구조
|
||||
|
||||
제외 범위는 대화 입력 정규화, 메시지 누적, 응답 선택 및 표시, 빈 입력 처리, 종료 단축키와 같은 애플리케이션 동작 계약이다. 외부 API 연동, 영속성, 배포 환경 변경과 새 의존성 추가도 포함하지 않는다.
|
||||
|
||||
### 포함
|
||||
|
||||
- 사용자 메시지와 에이전트 응답을 각각 별도의 Label 대화 항목으로 표시한다.
|
||||
- 각 메시지에 사용자 또는 에이전트라는 명시적인 작성자 역할을 부여한다.
|
||||
- 화면에 사용자와 에이전트 작성자 라벨을 표시한다.
|
||||
- `user-message`와 `response-message` 식별자를 유지하고, 테두리 또는 정렬 차이 같은 구조적 스타일을 적용한다.
|
||||
- 유효한 입력의 정규화, 응답 선택, 메시지 표시 순서 및 공백 입력 무시 동작을 유지한다.
|
||||
- 작성자 역할, 라벨, 구조적 스타일 및 기존 동작을 자동 테스트로 검증한다.
|
||||
- 관련 요구사항, 데이터 모델, 인터페이스 계약 및 실행 흐름 문서와의 추적성을 유지한다.
|
||||
Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구조, setuptools 패키징 설정, 런타임 의존성, 테스트 선택 의존성, 콘솔 스크립트 진입점과 python -m 실행 진입점을 다룬다.
|
||||
|
||||
### 제외
|
||||
|
||||
- LLM 연동 또는 외부 API 호출
|
||||
- 대화 저장, 사용자 인증 또는 사용자별 기록 관리
|
||||
- 고정 응답 목록과 응답 생성 방식의 변경
|
||||
- 대화 영역 전체 레이아웃의 재설계
|
||||
- 색상만으로 작성자를 구분하는 방식
|
||||
- 별도 영속성 백엔드나 데이터베이스 도입
|
||||
사용자 입력 정규화, 대화 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용 동작은 다루지 않는다.
|
||||
|
||||
## 4. 용어와 기준
|
||||
|
||||
- **사용자 메시지**: 입력창에 사용자가 제출한 공백 제거 후의 유효한 문자열이다.
|
||||
- **에이전트 응답**: 유효한 사용자 입력마다 고정된 응답 목록에서 표준 난수 선택으로 생성되는 문자열이다.
|
||||
- **메시지 역할**: 메시지를 작성한 주체를 나타내는 명시적인 값이며 `user` 또는 `agent` 중 하나다.
|
||||
- **작성자 라벨**: 사용자 역할을 `사용자`, 에이전트 역할을 `에이전트`로 화면에 표시하는 문자열이다.
|
||||
- **구조적 스타일**: 색상에만 의존하지 않고 CSS 클래스, 테두리 또는 정렬 차이로 작성자를 구분하는 표현이다.
|
||||
- **정본 기준**: `ChatMessage.role`과 `ChatMessage.content`의 조합을 메시지 의미의 단일 기준으로 삼고, 라벨과 CSS 클래스는 이 역할에서 파생한다.
|
||||
스캐폴드는 다음 기준을 따른다.
|
||||
|
||||
- 프로젝트 이름은 `gitea-agent-testbed`이고 Python 패키지 이름은 `chat_tui`이다.
|
||||
- 소스 루트는 `src`이며 패키지 탐색 설정은 해당 루트를 기준으로 한다.
|
||||
- 패키지 초기화 모듈은 패키지 버전 `0.1.0`을 공개한다.
|
||||
- 모듈 실행 진입점은 애플리케이션 모듈의 실행 함수를 호출한다.
|
||||
- 콘솔 스크립트 진입점은 `chat_tui.app:main`으로 연결한다.
|
||||
- 빌드 백엔드는 setuptools를 사용하고 빌드 요구 버전은 68 이상이다.
|
||||
- 테스트 설정은 `src`를 Python 경로에 포함하고 `tests` 디렉터리를 검색 대상으로 한다.
|
||||
- 문서와 소스의 스캐폴드 설명은 실제 패키지 구조와 패키징 설정에 부합해야 한다.
|
||||
|
||||
## 5. 요구사항
|
||||
|
||||
`REQ-001`은 대화 메시지의 작성자 의미를 명시적으로 관리하고 화면 및 검증 절차에서 일관되게 구분하기 위한 요구사항 묶음의 식별자다.
|
||||
시스템은 다음 프로젝트 기반 요구를 충족해야 한다.
|
||||
|
||||
### REQ-001.01 — 명시적인 메시지 역할 관리
|
||||
- 프로젝트는 Python 3.11 이상에서 설치 및 실행 가능한 표준 Python 패키지 구조를 제공해야 한다.
|
||||
- 빌드 설정은 setuptools를 사용하고 `src` 아래의 `chat_tui` 패키지를 배포 대상에 포함해야 한다.
|
||||
- 프로젝트 메타데이터에는 프로젝트 이름, 현재 버전, 설명, README 참조, Python 최소 버전과 Textual 런타임 의존성이 포함되어야 한다.
|
||||
- 테스트 선택 의존성을 별도로 설치할 수 있어야 하며 pytest 8.0 이상을 지정해야 한다.
|
||||
- `chat-tui` 명령을 실행하면 `chat_tui.app` 모듈의 `main` 함수가 호출되어 애플리케이션 시작 절차로 진입해야 한다.
|
||||
- `python -m chat_tui`를 실행하면 패키지의 모듈 진입점이 동일한 애플리케이션 시작 함수를 호출해야 한다.
|
||||
- 패키지 버전은 초기 스캐폴드 기준으로 `0.1.0`을 일관되게 노출해야 한다.
|
||||
- 패키징 및 실행 진입점 검증은 대화 기능의 세부 동작과 독립적으로 수행할 수 있어야 한다.
|
||||
|
||||
시스템은 유효한 사용자 입력과 그에 대응하는 에이전트 응답을 각각 명시적인 작성자 역할을 가진 메시지로 관리해야 한다. 사용자 메시지의 역할은 `user`, 에이전트 응답의 역할은 `agent`여야 하며, 역할과 본문은 하나의 대화 메시지 단위로 보존되어야 한다.
|
||||
### REQ-001.01 — Python 패키지 구조와 메타데이터를 제공한다
|
||||
|
||||
프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전, 설명, Python 3.11 이상 실행 조건, Textual 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있어야 한다.
|
||||
|
||||
**영향 범위**
|
||||
|
||||
- 인터페이스: `ChatMessage`, `MessageRole`, 대화 영역의 Label 렌더링
|
||||
- 영속성: 없음. 메시지는 애플리케이션 세션 메모리에만 유지한다.
|
||||
- 후속 사용 주체: UI 렌더러와 자동 테스트
|
||||
- 마이그레이션: 필요 없음. 기존 저장 데이터가 없다.
|
||||
- 호환성: 유효한 입력의 정규화, 응답 선택, 입력·응답 배열 및 표시 순서를 유지한다.
|
||||
- 배포 전제 조건: Python 3.11 이상과 현재 Textual 의존성을 유지한다.
|
||||
인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구, 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상과 기존 패키지 이름을 유지한다. 배포 전제 조건: setuptools 기반 editable 설치가 가능해야 한다.
|
||||
|
||||
### REQ-001.02 — 작성자 라벨과 구조적 표시
|
||||
### REQ-001.02 — 모듈 실행 진입점을 제공한다
|
||||
|
||||
시스템은 각 메시지의 명시적인 역할을 작성자 라벨과 구조적 스타일로 변환하여 표시해야 한다. 사용자 메시지는 `사용자` 라벨과 `user-message` 식별자를 사용하고, 에이전트 응답은 `에이전트` 라벨과 `response-message` 식별자를 사용해야 한다. 구조적 스타일은 색상만으로 작성자를 구분하지 않아야 하며, 역할별 테두리 또는 정렬 차이를 포함해야 한다.
|
||||
프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수를 호출하고, 실행 가능한 모듈로 직접 호출되었을 때만 애플리케이션을 시작해야 한다.
|
||||
|
||||
**영향 범위**
|
||||
|
||||
- 인터페이스: `#conversation` 내부 Label의 표시 문자열과 CSS 클래스
|
||||
- 영속성: 없음. 화면 위젯과 세션 메모리만 변경한다.
|
||||
- 후속 사용 주체: 사용자, UI 검수자 및 자동 회귀 테스트
|
||||
- 마이그레이션: 필요 없음
|
||||
- 호환성: 기존 `user-message` 및 `response-message` 식별자와 사용자·응답의 표시 순서를 유지한다.
|
||||
- 배포 전제 조건: Textual의 Label, VerticalScroll 및 CSS 스타일 기능을 사용할 수 있어야 한다.
|
||||
인터페이스: `python -m chat_tui` 실행 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자와 운영자가 사용하는 Python 모듈 실행 환경. 마이그레이션: 필요 없음. 호환성: 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다.
|
||||
|
||||
### REQ-001.03 — 콘솔 스크립트 실행 진입점을 제공한다
|
||||
|
||||
패키징 설정은 `chat-tui` 콘솔 명령을 애플리케이션 모듈의 공개 실행 함수에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 한다.
|
||||
|
||||
**영향 범위**
|
||||
|
||||
인터페이스: 설치 후 제공되는 `chat-tui` 콘솔 명령에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 최종 사용자와 운영 스크립트. 마이그레이션: 필요 없음. 호환성: 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지 설치 시 console script가 생성되어야 한다.
|
||||
|
||||
## 6. 제약과 불변조건
|
||||
|
||||
- Python 3.11 이상과 현재 Textual 기반 TUI 구조를 유지한다.
|
||||
- 유효한 입력은 앞뒤 공백을 제거한 뒤 사용자 메시지로 한 번만 기록한다.
|
||||
- 공백만 있거나 빈 입력은 응답을 선택하지 않고 메시지 목록과 화면을 변경하지 않는다.
|
||||
- 유효한 입력 하나마다 사용자 메시지가 먼저, 그 뒤에 에이전트 응답이 표시되어야 한다.
|
||||
- 에이전트 응답은 기존 `RESPONSE_MESSAGES`에서 `random.choice(RESPONSE_MESSAGES)`로 선택한다.
|
||||
- 모든 메시지는 `MessageRole`을 통해 작성자 의미를 가져야 하며 CSS 클래스만으로 역할을 판정하지 않는다.
|
||||
- 사용자와 에이전트는 화면의 텍스트 라벨로 구분되어야 한다.
|
||||
- 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다.
|
||||
- 메시지 표시와 테스트에서 사용자 및 에이전트 역할의 순서와 의미가 일치해야 한다.
|
||||
- 외부 API, 인증, 영속 저장소 및 민감정보 처리는 추가하지 않는다.
|
||||
- 프로젝트는 Python 3.11 이상에서 실행되어야 한다.
|
||||
- 패키지 구성은 `src` 기반 레이아웃을 유지하며, 애플리케이션 패키지와 테스트 패키지의 책임을 분리해야 한다.
|
||||
- 런타임 의존성은 Textual 계열의 호환 범위 안에서 관리하고, 테스트 의존성은 선택적 설치 항목으로 제공해야 한다.
|
||||
- 패키징 메타데이터, 버전, 설명, 지원 Python 버전은 서로 일관되어야 한다.
|
||||
- 콘솔 실행 진입점과 모듈 실행 진입점은 동일한 애플리케이션 시작 동작을 호출해야 한다.
|
||||
- 이 범위에서는 대화 입력 정규화, 메시지 누적, 응답 선택과 표시, 빈 입력 처리 및 종료 동작의 의미를 변경하지 않는다.
|
||||
- 외부 API, LLM, 데이터베이스, 영속 저장소 또는 추가 배포 환경을 도입하지 않는다.
|
||||
- 기존 프로젝트 구조와 실행 계약을 사용하는 호출자는 별도 변환 없이 계속 사용할 수 있어야 한다.
|
||||
|
||||
## 7. 인수 기준
|
||||
|
||||
인수 기준은 소속 요구사항을 포함한 `REQ-001.01-AC01` 형식으로 식별한다.
|
||||
- 프로젝트를 개발 환경에 설치하면 패키지와 런타임 의존성이 선언된 구성에 따라 설치되어야 한다.
|
||||
- 설치된 콘솔 명령을 실행하면 애플리케이션의 주 실행 진입점이 호출되어야 한다.
|
||||
- `python -m chat_tui`로 실행해도 콘솔 명령과 동일한 애플리케이션이 시작되어야 한다.
|
||||
- 소스 패키지는 `src` 아래에서 검색되어 설치되어야 하며, 패키지 버전과 프로젝트 버전 선언은 일치해야 한다.
|
||||
- 테스트 의존성을 선택적으로 설치할 수 있어야 하며, 테스트 실행 명령으로 저장소의 테스트를 검색하고 실행할 수 있어야 한다.
|
||||
- 스캐폴드 변경 후에도 대화 기능과 종료 기능에 대한 기존 회귀 검증이 통과해야 한다.
|
||||
- 패키징 설정에 명시되지 않은 외부 연동이나 추가 실행 전제 조건이 없어야 한다.
|
||||
- 검증은 Python 3.11 이상 환경에서 패키지 설치, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행한다.
|
||||
|
||||
### REQ-001.01-AC01 — 메시지 역할이 순서대로 보존됨
|
||||
### REQ-001.01-AC01 — 패키징 메타데이터가 프로젝트 계약과 일치한다
|
||||
|
||||
**판정 기준**
|
||||
|
||||
- 유효한 사용자 입력이 제출되면 입력 문자열의 앞뒤 공백이 제거된 사용자 메시지가 `user` 역할로 기록된다.
|
||||
- 같은 제출에서 선택된 응답이 `agent` 역할로 기록된다.
|
||||
- 여러 입력을 제출할 때 메시지 목록은 각 입력에 대해 사용자 메시지 다음 에이전트 응답 순서를 유지한다.
|
||||
- 메시지 역할과 본문이 함께 비교 가능해야 하며, 역할을 CSS 클래스에서 추론하지 않아야 한다.
|
||||
패키징 설정에 프로젝트 이름, 버전, 설명, Python 3.11 이상 조건, Textual 의존성, 소스 디렉터리 패키지 검색 설정이 모두 선언되어 있으면 PASS로 판정한다.
|
||||
|
||||
**검증**
|
||||
|
||||
- Textual 테스트 앱에서 두 개의 유효한 입력을 제출한다.
|
||||
- `submitted_inputs`, `selected_responses`, `messages`의 값과 순서를 비교한다.
|
||||
- `messages`가 사용자와 에이전트 역할을 번갈아 포함하는지 확인한다.
|
||||
- 응답 선택을 고정해 입력 정규화와 메시지 역할 보존을 결정적으로 검증한다.
|
||||
`pyproject.toml`을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 editable 설치를 수행하여 패키지가 정상적으로 구성되는지 검증한다.
|
||||
|
||||
**검증 분류**
|
||||
|
||||
- 수준: `integration`
|
||||
- 백엔드: 없음
|
||||
- 케이스: `positive`
|
||||
수준: integration; 백엔드: Python 패키징 도구와 setuptools; 케이스: positive
|
||||
|
||||
**상태 불변조건**
|
||||
|
||||
- 성공 시 입력과 응답이 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다.
|
||||
- 성공하더라도 기존 입력·응답의 순서와 내용은 변경되면 안 된다.
|
||||
- 실패 또는 공백 입력 시 응답 선택과 메시지 목록 추가가 발생하지 않아야 한다.
|
||||
성공 시 선언된 패키지와 의존성이 설치되어야 한다. 패키징 설정에 명시되지 않은 외부 연동이나 배포 설정은 추가되지 않아야 한다. 설치 실패 시 부분적으로 유효하지 않은 패키지 계약을 성공으로 간주하지 않아야 한다.
|
||||
|
||||
### REQ-001.01-AC02 — 공백 입력이 역할 없는 메시지를 만들지 않음
|
||||
### REQ-001.01-AC02 — 패키지 버전을 import할 수 있다
|
||||
|
||||
**판정 기준**
|
||||
|
||||
- 빈 문자열 또는 공백·탭·개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않아야 한다.
|
||||
- 공백 입력에서는 응답 선택 함수가 호출되지 않아야 한다.
|
||||
- 입력창은 기존 동작과 같이 제출 후 비워져야 한다.
|
||||
`chat_tui` 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되면 PASS로 판정한다.
|
||||
|
||||
**검증**
|
||||
|
||||
- 공백만 포함한 입력과 빈 입력을 각각 Textual 테스트 앱에 제출한다.
|
||||
- 메시지 목록과 대화 영역 Label 개수가 0인지 확인한다.
|
||||
- `random.choice`가 호출되지 않았는지 확인한다.
|
||||
- 입력창 값이 비워지는지 확인한다.
|
||||
Python에서 `chat_tui.__version__`을 조회하고 패키징 설정의 프로젝트 버전과 일치하는지 확인한다.
|
||||
|
||||
**검증 분류**
|
||||
|
||||
- 수준: `integration`
|
||||
- 백엔드: 없음
|
||||
- 케이스: `boundary`
|
||||
수준: unit; 백엔드: Python import 시스템; 케이스: positive
|
||||
|
||||
**상태 불변조건**
|
||||
|
||||
- 성공적인 무시 처리에서 메시지 목록, 제출 입력 기록 및 응답 기록은 변경되지 않아야 한다.
|
||||
- 대화 영역에 작성자 라벨을 포함한 새 Label이 추가되면 안 된다.
|
||||
- 실패 시 부분적인 사용자 메시지 또는 응답이 남아서는 안 된다.
|
||||
성공 시 패키지 import가 가능해야 한다. 버전 조회가 패키지 초기화 중 외부 상태를 변경해서는 안 된다. 조회 실패 시 애플리케이션 실행 진입점의 정상 동작을 성공으로 판정하지 않는다.
|
||||
|
||||
### REQ-001.02-AC01 — 작성자 라벨과 구조적 스타일이 역할과 일치함
|
||||
### REQ-001.02-AC01 — 모듈 명령이 애플리케이션을 시작한다
|
||||
|
||||
**판정 기준**
|
||||
|
||||
- 사용자 메시지는 `사용자: 본문` 형식으로 표시되어야 한다.
|
||||
- 에이전트 응답은 `에이전트: 본문` 형식으로 표시되어야 한다.
|
||||
- 사용자 Label에는 `chat-message user-message user-role` 클래스가 포함되어야 한다.
|
||||
- 에이전트 Label에는 `chat-message response-message agent-role` 클래스가 포함되어야 한다.
|
||||
- CSS에는 사용자와 에이전트의 구조적 차이를 나타내는 `border-left`, `border-right`, `align: left middle`, `align: right middle` 규칙이 있어야 한다.
|
||||
설치된 패키지 환경에서 `python -m chat_tui`를 실행하면 패키지의 실행 함수가 호출되어 TUI가 시작되면 PASS로 판정한다.
|
||||
|
||||
**검증**
|
||||
|
||||
- 유효한 입력 하나를 제출하고 대화 영역의 Label 두 개를 조회한다.
|
||||
- Label의 렌더링 문자열과 클래스가 각각 사용자 및 에이전트 역할과 일치하는지 확인한다.
|
||||
- 애플리케이션 CSS에 양쪽 테두리와 역할별 정렬 규칙이 포함되는지 확인한다.
|
||||
모듈 진입점 파일이 애플리케이션의 실행 함수를 import하고 직접 실행 조건에서 호출하는지 확인한 뒤, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다.
|
||||
|
||||
**검증 분류**
|
||||
|
||||
- 수준: `integration`
|
||||
- 백엔드: 없음
|
||||
- 케이스: `positive`
|
||||
수준: end-to-end; 백엔드: Python 모듈 실행기와 Textual 런타임; 케이스: positive
|
||||
|
||||
**상태 불변조건**
|
||||
|
||||
- 성공 시 각 메시지의 라벨과 구조적 클래스가 해당 역할과 일치해야 한다.
|
||||
- 성공하더라도 메시지 본문, 표시 순서 및 기존 식별자는 변경되면 안 된다.
|
||||
- 렌더링 실패 시 역할이 다른 라벨이나 일부만 표시된 메시지가 남아서는 안 된다.
|
||||
성공 시 모듈 실행은 공개 실행 함수를 통해 애플리케이션을 시작해야 한다. 모듈을 단순 import하는 것만으로 TUI가 시작되어서는 안 된다. 초기화 실패 시 실행되지 않은 상태를 정상 시작으로 기록하지 않는다.
|
||||
|
||||
### REQ-001.02-AC02 — 기존 응답 선택과 종료 동작을 보존함
|
||||
### REQ-001.03-AC01 — 설치 후 콘솔 명령이 생성된다
|
||||
|
||||
**판정 기준**
|
||||
|
||||
- 유효한 입력 제출 시 기존 응답 목록을 인자로 하여 표준 `random.choice`가 한 번 호출되어야 한다.
|
||||
- `Escape` 키 입력은 기존처럼 애플리케이션 종료를 요청해야 한다.
|
||||
- 작성자 구분 기능을 추가해도 기존 입력·응답 회귀 테스트가 통과해야 한다.
|
||||
editable 설치가 완료된 환경에서 `chat-tui` 명령이 PATH에 생성되고 애플리케이션을 시작하면 PASS로 판정한다.
|
||||
|
||||
**검증**
|
||||
|
||||
- `random.choice`를 모의 처리하여 `RESPONSE_MESSAGES`가 전달되는지 확인한다.
|
||||
- Textual 테스트 앱에서 `Escape`를 입력하고 `exit()` 호출을 확인한다.
|
||||
- 유효 입력 두 건의 정규화, 응답 내용, 표시 순서 및 입력창 초기화를 함께 확인한다.
|
||||
패키지를 editable 방식으로 설치한 뒤 `chat-tui` 명령의 존재를 확인하고 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다.
|
||||
|
||||
**검증 분류**
|
||||
|
||||
- 수준: `integration`
|
||||
- 백엔드: 없음
|
||||
- 케이스: `unchanged-state`
|
||||
수준: end-to-end; 백엔드: setuptools console script와 Textual 런타임; 케이스: positive
|
||||
|
||||
**상태 불변조건**
|
||||
|
||||
- 유효 입력 성공 시 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다.
|
||||
- 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되면 안 된다.
|
||||
- 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다.
|
||||
성공 시 콘솔 명령은 지정된 공개 실행 함수를 호출해야 한다. 명령 생성 과정에서 대화 상태나 사용자 입력이 변경되어서는 안 된다. 설치가 완료되지 않은 환경에서는 명령이 존재한다고 판정하지 않는다.
|
||||
|
||||
## 8. 오류 및 충돌 계약
|
||||
|
||||
- 입력 오류: 빈 입력과 공백 입력은 오류를 표시하지 않고 무시하며, 응답 선택과 메시지 추가를 수행하지 않는다.
|
||||
- 상태 충돌: 단일 Textual 이벤트 루프에서 제출 이벤트 순서를 처리하며, 동일 입력을 자동으로 중복 제출하지 않는다.
|
||||
- 저장 실패: 영속 저장소가 없으므로 저장 실패와 롤백 대상이 없다. 렌더링 실패가 발생하더라도 별도의 부분 영속 기록을 만들지 않는다.
|
||||
- 역할 오류: 사용자 또는 에이전트로 정의되지 않은 역할은 정상 메시지로 렌더링하지 않으며, 역할 값과 표시 라벨의 매핑은 한 곳의 명시적 기준을 따른다.
|
||||
- 패키지 설치에 필요한 메타데이터가 누락되거나 유효하지 않으면 설치는 성공한 것으로 판정하지 않으며, 설치 과정은 원인 확인 가능한 오류를 반환해야 한다.
|
||||
- 지원하지 않는 Python 버전에서는 실행을 정상 동작으로 간주하지 않는다.
|
||||
- 콘솔 진입점 또는 모듈 진입점이 애플리케이션 시작 함수를 찾지 못하면 실행은 실패해야 하며, 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않는다.
|
||||
- 의존성 버전 제약을 만족하지 못하는 환경에서는 호환되는 런타임으로 자동 대체하거나 외부 서비스를 호출하지 않는다.
|
||||
- 테스트 의존성 설치 실패는 제품 런타임 의존성의 정상 설치와 별개의 실패로 식별되어야 한다.
|
||||
- 스캐폴드 변경으로 기존 대화 동작이나 종료 동작이 달라지면 인수에 실패한 것으로 판정한다.
|
||||
- 설치 또는 실행 실패 시 프로젝트 파일에 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다.
|
||||
|
||||
## 9. 데이터 및 인터페이스 계약
|
||||
|
||||
- `MessageRole`: 문자열 기반 열거형이며 `USER`의 값은 `user`, `AGENT`의 값은 `agent`다.
|
||||
- `ChatMessage.role`: 필수 `MessageRole` 값으로 메시지 작성자를 나타낸다.
|
||||
- `ChatMessage.content`: 필수 문자열로 공백 제거가 완료된 사용자 입력 또는 선택된 응답 본문을 담는다.
|
||||
- `MessageRole.label`: `user`를 `사용자`, `agent`를 `에이전트`로 변환한다.
|
||||
- `ChatApp.messages`: 제출 순서대로 `ChatMessage`를 보유하며 유효 입력마다 사용자 메시지와 에이전트 응답을 차례로 추가한다.
|
||||
- 사용자 Label 표시값은 `사용자: 본문` 형식이고 에이전트 Label 표시값은 `에이전트: 본문` 형식이다.
|
||||
- 사용자 Label은 `user-message`와 `user-role`을 포함하고 에이전트 Label은 `response-message`와 `agent-role`을 포함한다.
|
||||
- `submitted_inputs`, `selected_responses` 및 기존 `RESPONSE_MESSAGES` 계약은 유지한다.
|
||||
- 식별자는 세션 내 메모리 객체와 CSS 클래스에 한정되며 시간대·단위·정밀도 계약은 없다.
|
||||
- 프로젝트 패키지의 정본 위치는 `src/chat_tui`이며, 패키지 검색 기준은 `src`이다.
|
||||
- 프로젝트 메타데이터는 패키지 이름, 버전, 설명, README 위치, 지원 Python 버전 및 런타임 의존성을 제공해야 한다.
|
||||
- 테스트 의존성은 별도 선택적 의존성 그룹으로 선언되어야 한다.
|
||||
- 콘솔 인터페이스는 `chat-tui` 명령에서 애플리케이션의 `main` 실행 함수를 호출해야 한다.
|
||||
- 모듈 인터페이스는 `python -m chat_tui` 실행 시 패키지의 모듈 진입점에서 동일한 `main` 함수를 호출해야 한다.
|
||||
- 패키지 공개 버전은 프로젝트 메타데이터의 버전과 일치해야 한다.
|
||||
- 실행 진입점은 외부 입력을 별도 프로토콜이나 네트워크 인터페이스로 변환하지 않고 로컬 Textual 애플리케이션을 시작한다.
|
||||
- 테스트 인터페이스는 표준 unittest 검색 방식으로 저장소 테스트를 실행할 수 있어야 하며, 별도의 서비스나 데이터 저장소를 요구하지 않는다.
|
||||
|
||||
## 10. 하위 호환성
|
||||
|
||||
- Python 3.11 이상에서 실행되는 기존 패키지와 콘솔 진입점 `chat_tui.app:main`을 유지한다.
|
||||
- `#conversation`, `#user-input`, `user-message`, `response-message` 식별자를 유지한다.
|
||||
- Enter 제출, 앞뒤 공백 제거, 공백 입력 무시, 고정 응답 목록 선택, `Escape` 및 `Ctrl+Q` 종료 동작을 유지한다.
|
||||
- 기존의 사용자·응답 Label 두 항목 표시 구조를 유지하되 표시 문자열에 작성자 라벨과 역할 클래스를 추가한다.
|
||||
- 기존 영속 데이터가 없으므로 데이터 마이그레이션은 필요하지 않다.
|
||||
- 작성자 라벨과 구조적 스타일은 추가되지만 대화 영역 전체 레이아웃을 재설계하지 않는다.
|
||||
- 기존의 `chat-tui` 콘솔 실행 방식은 유지되어야 한다.
|
||||
- 기존의 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다.
|
||||
- Python 3.11 이상 지원 조건과 현재 패키지 이름 및 버전 계약은 유지되어야 한다.
|
||||
- `src` 기반 패키지 검색과 애플리케이션 패키지의 공개 버전 노출 방식은 유지되어야 한다.
|
||||
- 기존 README에 설명된 설치 및 실행 명령은 스캐폴드 정리 이후에도 유효해야 한다.
|
||||
- 대화 동작을 별도 요구사항으로 분리하더라도 현재 구현과 테스트가 보장하는 입력 처리, 응답 표시, 빈 입력 무시 및 종료 동작은 변경하지 않는다.
|
||||
- 새 외부 의존성, 외부 연동, 배포 방식 또는 실행 환경을 추가하지 않는다.
|
||||
- 변경된 요구사항 문서는 프로젝트 스캐폴드와 패키징 및 실행 진입점만 정본 범위로 보유하고, 대화 동작의 세부 계약을 중복해서 정의하지 않는다.
|
||||
|
||||
## 11. 검증 계획
|
||||
|
||||
- `tests/test_app.py`의 Textual 비동기 테스트로 정상 입력, 다중 메시지 순서, 역할 객체, 라벨 및 CSS 클래스를 검증한다.
|
||||
- 공백 입력과 빈 입력 테스트로 응답 선택 미호출, 메시지 미추가 및 화면 미변경을 검증한다.
|
||||
- `random.choice` 모의 테스트로 기존 응답 선택 계약을 검증한다.
|
||||
- `Escape` 종료 테스트로 기존 종료 바인딩을 회귀 검증한다.
|
||||
- 별도 영속성 백엔드와 마이그레이션이 없으므로 저장 후 재조회 검증은 해당 없음으로 판정한다.
|
||||
- 요구사항, `docs/data-model.md`, `docs/interface-contract.md`, `docs/runtime-flow.md`의 역할·라벨·스타일·순서 설명이 구현 및 테스트와 일치하는지 문서 검토로 확인한다.
|
||||
프로젝트 스캐폴드와 패키징 계약은 Python 3.11 이상 환경에서 패키지 설치가 가능한지 검증한다. 패키지 메타데이터, 런타임 의존성, 테스트 선택 의존성, 소스 패키지 검색 설정이 선언된 값과 일치하는지 확인한다. 콘솔 실행 명령과 모듈 실행 명령이 동일한 애플리케이션 진입점으로 연결되는지 확인한다. 기존 대화 동작은 이 문서의 검증 대상에서 제외하고 분리된 대화 요구사항에서 검증한다. 자동화된 저장소 테스트와 패키지 설치 검증을 모두 통과해야 하며, 실행 환경은 지원되는 Python 버전과 선언된 의존성을 기준으로 한다.
|
||||
|
||||
### 테스트 추적성 계약
|
||||
|
||||
- 요구사항 문서에는 검증 의도와 판정 조건만 기록한다.
|
||||
- 실행 가능한 테스트 정의는 별도 테스트 카탈로그 산출물에서 관리한다.
|
||||
- 각 테스트 케이스는 안정적인 식별자를 사용하고 `verifies`로 인수 기준을 참조한다.
|
||||
- 하나의 테스트가 여러 인수 기준을 검증할 수 있으며, 각 연결을 빠짐없이 기록한다.
|
||||
- 실행 결과는 요구사항 또는 테스트 정의에 덮어쓰지 않고 별도 증거 산출물에 기록한다.
|
||||
- 증거는 요구사항 개정 번호, 검증한 커밋, 환경과 실행 시각에 결합한다.
|
||||
- 테스트 정의의 존재, 자동화 여부, 특정 커밋에서의 실행 여부와 PASS 결과를 서로 다른 상태로 취급한다.
|
||||
|
||||
테스트 정의 예시:
|
||||
테스트 정의:
|
||||
|
||||
```text
|
||||
Test ID: TC-001-001
|
||||
Verifies:
|
||||
- REQ-001.01-AC01
|
||||
- REQ-001.01-AC02
|
||||
- REQ-001.02-AC01
|
||||
Test reference: tests/test_app.py::ChatAppTest::test_submitted_input_and_response_are_displayed_in_order
|
||||
Automated: true
|
||||
- REQ-001.03-AC01
|
||||
Test reference: pyproject.toml 설정 검토 및 python -m unittest discover -s tests -v
|
||||
Automated: 기존 패키징 및 실행 진입점 검증 테스트를 사용한다.
|
||||
```
|
||||
|
||||
실행 증거 예시:
|
||||
실행 증거:
|
||||
|
||||
```text
|
||||
Test ID: TC-001-001
|
||||
Requirement revision: REQ-001@0.1
|
||||
Commit: 검증 실행 시점의 커밋 SHA
|
||||
Environment: Python 3.11 이상, Textual 테스트 앱, 영속 백엔드 없음
|
||||
Result: PASS | FAIL | BLOCKED
|
||||
Executed at: 실행 시각
|
||||
Commit: d0ac7fc7bcfaf402bbda24776f051fa9992993e1
|
||||
Environment: Python 3.11 이상, setuptools 기반 설치 환경
|
||||
Result: 미실행
|
||||
Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음
|
||||
```
|
||||
|
||||
## 12. 추적성
|
||||
|
||||
- 근거 이슈: Gitea 이슈 #6, 제목 `메세지 표시창에서 메세지 작성자 구분`
|
||||
- 구현 PR: 없음
|
||||
- 관련 설계 문서: `docs/data-model.md`, `docs/interface-contract.md`, `docs/runtime-flow.md`, `docs/project-structure.md`
|
||||
- 관련 요구사항: 없음
|
||||
근거는 원본 이슈의 요구사항 재작업 요청과 저장소에 존재하는 프로젝트 메타데이터 및 패키지 진입점 선언이다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 및 콘솔 실행 진입점에 관한 내용만 추적한다. 입력 정규화, 메시지 누적, 응답 선택, 입력창 초기화, 종료 동작과 같은 대화 기능은 별도의 대화 요구사항 문서에서 추적한다. 두 문서 사이에는 프로젝트 실행 기반을 선행 조건으로 하는 의존 관계가 있으며, 각 기능과 수용 기준은 두 문서에 중복 기록하지 않는다.
|
||||
|
||||
## 13. 확정된 결정
|
||||
|
||||
- 사용자 메시지와 에이전트 응답은 작성자 라벨과 구조적 스타일로 구분한다.
|
||||
- 작성자 구분은 색상에만 의존하지 않고 테두리 또는 정렬 차이를 포함한다.
|
||||
- 작성자 의미는 CSS 클래스에만 두지 않고 명시적인 메시지 역할로 관리한다.
|
||||
- 기존 사용자·응답 표시 순서, 입력 정규화, 고정 응답 선택 및 종료 동작은 유지한다.
|
||||
- 외부 API, LLM, 인증 및 영속 저장은 이번 범위에 포함하지 않는다.
|
||||
디스커버리에서 확정된 추가 제품 정책이나 구현 변경 결정은 없다. 기존 프로젝트 스캐폴드의 의미와 이력은 유지하고, 대화 동작 요구사항만 별도 문서로 분리한다. 애플리케이션 코드, 테스트 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다.
|
||||
|
||||
## 14. 미결 사항
|
||||
|
||||
@@ -299,6 +265,4 @@ Executed at: 실행 시각
|
||||
|
||||
## 15. 승인 기록
|
||||
|
||||
- 상태: `approved`
|
||||
- 승인 주체: `spec-agent`
|
||||
- 승인 근거: 승인 댓글 923 및 디스커버리 승인 결과
|
||||
상태는 초안이다. 요구사항 문서 자체의 승인 주체와 승인 근거는 아직 기록되지 않았다. 원본 이슈의 디스커버리는 승인되었으나, 이 문서의 최종 요구사항 승인은 별도 절차에서 수행해야 한다.
|
||||
|
||||
Reference in New Issue
Block a user