From 1f73b4bd414d9d579cdaeef391377d4959910c48 Mon Sep 17 00:00:00 2001 From: code-agent Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH 1/5] code-agent: implement issue 8 Approval-Correlation: a1502ebfff533b69c158f3c6c1316c01 Plan-SHA256: aae2d7573d66fb5573378443712149a4f7ba23f7f9de19e25b00f9b760d05c3e Bundle-SHA256: 29ce1ef1917864f79938459725201e6e74d67e21b1f817ac53d7b294eca8f1a2 Base-SHA: d0ac7fc7bcfaf402bbda24776f051fa9992993e1 --- docs/requirements/req-001_project-scaffold.md | 294 ++++++------ .../req-002_conversation-interaction.md | 438 ++++++++++++++++++ 2 files changed, 567 insertions(+), 165 deletions(-) create mode 100644 docs/requirements/req-002_conversation-interaction.md diff --git a/docs/requirements/req-001_project-scaffold.md b/docs/requirements/req-001_project-scaffold.md index fb2c69c..248eada 100644 --- a/docs/requirements/req-001_project-scaffold.md +++ b/docs/requirements/req-001_project-scaffold.md @@ -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 및 디스커버리 승인 결과 +상태는 초안이다. 요구사항 문서 자체의 승인 주체와 승인 근거는 아직 기록되지 않았다. 원본 이슈의 디스커버리는 승인되었으나, 이 문서의 최종 요구사항 승인은 별도 절차에서 수행해야 한다. diff --git a/docs/requirements/req-002_conversation-interaction.md b/docs/requirements/req-002_conversation-interaction.md new file mode 100644 index 0000000..fd88a20 --- /dev/null +++ b/docs/requirements/req-002_conversation-interaction.md @@ -0,0 +1,438 @@ +--- +{ + "schema": "proofline.requirement/v1", + "id": "REQ-002", + "title": "대화 입력과 고정 응답 상호작용", + "revision": "0.1", + "status": "draft", + "depends_on": [ + "REQ-001" + ], + "applies_to": [ + "Textual 대화형 TUI", + "입력 정규화와 메시지 누적", + "고정 응답 선택과 표시", + "빈 입력 처리와 종료 동작" + ], + "language": "ko" +} +--- + +# REQ-002 — 대화 입력과 고정 응답 상호작용 + +## 1. 목적 + +이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 입력한 메시지를 정규화하고 세션 내 대화 영역에 누적 표시하는 동작을 정의한다. 유효한 입력에는 고정된 응답 목록에서 하나를 선택하여 사용자 메시지 바로 뒤에 표시하고, 공백만 포함하거나 비어 있는 입력은 대화 상태를 변경하지 않고 무시한다. 입력을 처리한 뒤 입력창을 비우며, 기존 프로젝트 스캐폴드와 실행 진입점에 의존하여 동일한 애플리케이션 흐름 안에서 동작하도록 보장한다. + +## 2. 배경 + +현재 애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 메시지를 작성하고 Enter를 눌러 제출하며, 애플리케이션은 입력 양끝의 공백을 제거한 결과를 세션의 사용자 메시지로 기록한다. 정규화 결과가 유효하면 고정된 다섯 개 응답 중 하나를 표준 난수 선택 방식으로 결정하고, 사용자 메시지와 에이전트 응답을 정해진 순서로 대화 영역에 표시한다. + +대화 기능은 외부 API, LLM, 데이터베이스 또는 영속 저장소를 사용하지 않는다. 메시지와 선택 결과는 실행 중인 세션의 메모리 상태로 관리하며, 프로젝트의 설치 및 실행 기반은 선행 요구사항에 정의된 계약을 따른다. + +## 3. 범위 + +포함 범위는 다음과 같다. + +- 입력값의 양끝 공백 제거와 정규화 결과 판정 +- 유효한 사용자 입력과 선택된 에이전트 응답의 세션 내 누적 +- 고정된 응답 목록에서 표준 난수 선택 방식으로 응답 결정 +- 사용자 메시지를 먼저 표시하고 그 바로 뒤에 에이전트 응답을 표시하는 순서 보장 +- 작성자 역할에 따른 사용자 및 에이전트 라벨과 구조적 표시 스타일 제공 +- 공백만 포함하거나 비어 있는 입력의 무시 +- 입력 제출 후 입력창 초기화 +- Escape 및 Ctrl+Q를 통한 애플리케이션 종료 요청 +- 선행 프로젝트 스캐폴드 요구사항과의 의존 관계 및 원본 이슈 추적 + +제외 범위는 다음과 같다. + +- 프로젝트 패키징, 설치 설정 및 실행 진입점 자체의 변경 +- 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작의 변경 +- 외부 API, LLM, 네트워크 서비스, 데이터베이스 및 영속 저장소 연동 +- 사용자 인증, 권한 관리, 다중 세션 관리 및 메시지 복원 +- 새로운 런타임 의존성, 배포 방식 또는 실행 환경 추가 + +### 포함 + +사용자 입력의 trim 정규화, 유효한 메시지의 세션 내 누적, 고정된 응답 목록에서의 응답 선택과 표시, 사용자 메시지와 에이전트 응답의 순서 보장, 빈 입력 무시, 입력창 초기화, Escape 및 Ctrl+Q 종료 동작을 다룬다. REQ-001이 제공하는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용한다. + +### 제외 + +프로젝트 스캐폴드, 패키징 메타데이터와 실행 진입점의 변경은 다루지 않는다. 고정 응답 문구, 입력 처리 순서와 사용자 인터페이스 의미를 변경하지 않으며, LLM, 외부 API, 네트워크 연동, 영속 저장소, 새 의존성, 배포 환경 변경도 포함하지 않는다. + +## 4. 용어와 기준 + +입력은 사용자가 입력창에서 제출한 문자열이며, 정규화는 문자열 양끝의 공백을 제거하는 것을 의미한다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. + +유효한 메시지는 정규화된 사용자 입력과 고정 응답 목록에서 선택된 응답으로 구성된 한 쌍의 대화 항목이다. 사용자 메시지는 사용자 역할을 가지며, 선택된 응답은 에이전트 역할을 가진다. 화면 라벨은 각각 사용자와 에이전트로 표시하고 역할에 대응하는 구조적 스타일을 적용한다. + +고정 응답 목록은 다음 다섯 문구를 정본으로 사용한다. + +- 안녕하세요! 무엇을 도와드릴까요? +- 그것은 제가 처리하기 불가능합니다. +- 맡겨만 주세요. +- 지금 처리 중입니다. +- 작업을 완료하였습니다. + +응답 선택은 표준 난수 선택 기능에 이 목록 전체를 전달하여 수행한다. 선택 결과는 입력마다 하나만 생성하며, 사용자 메시지 다음에 즉시 배치한다. 세션의 메시지 순서와 입력별 선택 결과는 실행 중 메모리 상태를 정본으로 삼는다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며, 종료 과정에서 외부 상태나 영속 데이터는 생성하지 않는다. + +## 5. 요구사항 + +시스템은 다음 대화 상호작용 요구를 충족해야 한다. + +- 사용자가 입력을 제출하면 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. +- 정규화한 값이 비어 있지 않은 경우에만 유효한 사용자 메시지로 기록하고 화면에 표시해야 한다. +- 유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 선택 방식으로 응답 하나를 선택해야 한다. +- 사용자 메시지는 사용자 역할과 사용자 라벨로 표시하고, 선택된 응답은 에이전트 역할과 에이전트 라벨로 표시해야 한다. +- 각 입력의 사용자 메시지와 응답은 사용자 메시지가 먼저 오고 응답이 바로 뒤따르는 순서로 대화 영역에 누적해야 한다. +- 여러 입력을 제출한 경우 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서를 유지해야 한다. +- 유효한 입력을 처리한 뒤 입력창의 값은 빈 문자열로 초기화해야 한다. +- 비어 있거나 공백만 포함한 입력은 응답을 선택하지 않고 메시지 상태와 화면을 변경하지 않아야 한다. +- 공백 입력을 무시하더라도 입력창은 초기화해야 한다. +- Escape와 Ctrl+Q 입력은 애플리케이션 종료 동작을 요청해야 한다. +- 대화 동작은 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. +- 기존 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 선행 요구사항이 제공하는 실행 환경에서 동작해야 한다. + +### REQ-002.01 — 입력 정규화와 유효 입력 판정 + +사용자가 입력을 제출하면 시스템은 앞뒤 공백을 제거한 값을 정규화한다. 정규화한 값이 빈 문자열이면 해당 제출을 유효한 메시지로 처리하지 않고, 응답을 선택하거나 대화 영역에 항목을 추가하지 않는다. 하나 이상의 문자가 남은 입력만 유효한 사용자 메시지로 처리한다. + +**영향 범위** + +인터페이스: 입력 위젯의 제출 처리와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 확인하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 앞뒤 공백 제거와 공백 입력 무시 동작을 유지한다. 배포 전제 조건: 선언된 Textual 런타임에서 입력 이벤트를 처리할 수 있어야 한다. + +### REQ-002.02 — 유효 메시지와 고정 응답을 순서대로 누적 표시한다 + +유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 먼저 대화 상태와 대화 영역에 추가하고, 고정된 응답 목록에서 표준 난수 선택으로 하나의 응답을 선택한 뒤 바로 이어서 에이전트 메시지로 추가한다. 제출이 반복될 때마다 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적한다. + +**영향 범위** + +인터페이스: 대화 영역의 메시지 순서와 작성자 표시 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, TUI 렌더링 계층 및 회귀 테스트. 마이그레이션: 필요 없음. 호환성: 기존 고정 응답 목록과 표준 난수 선택 방식을 유지한다. 배포 전제 조건: Textual 대화 영역과 표준 Python 난수 모듈을 사용할 수 있어야 한다. + +### REQ-002.03 — 제출 후 입력창을 초기화한다 + +입력 제출 이벤트가 발생하면 시스템은 제출된 값이 유효한지와 관계없이 입력 위젯의 값을 즉시 빈 문자열로 초기화한다. 초기화는 유효 메시지 처리와 독립적으로 수행되어야 하며, 사용자가 다음 메시지를 입력할 수 있는 상태를 제공한다. + +**영향 범위** + +인터페이스: 입력 위젯의 값과 연속 입력 경험에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 제출 후 입력창이 비워지는 기존 동작을 유지한다. 배포 전제 조건: Textual Input 위젯이 제출 이벤트에서 갱신 가능해야 한다. + +### REQ-002.04 — 역할 기반 메시지 표시를 유지한다 + +시스템은 대화 메시지의 작성자 역할을 사용자와 에이전트로 명시적으로 보유하고, 역할에 맞는 라벨과 구조적 스타일을 적용해 표시한다. 사용자 메시지는 사용자 라벨과 사용자 스타일을 사용하고, 응답 메시지는 에이전트 라벨과 응답 스타일을 사용한다. + +**영향 범위** + +인터페이스: 대화 영역의 라벨, 스타일 클래스 및 시각적 구분에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 접근 가능한 화면 검증 및 렌더링 테스트. 마이그레이션: 필요 없음. 호환성: 기존 사용자와 에이전트 역할 구분을 유지한다. 배포 전제 조건: Textual Label 및 CSS 스타일 처리를 사용할 수 있어야 한다. + +### REQ-002.05 — 종료 단축키로 애플리케이션을 종료한다 + +사용자가 Escape 또는 Ctrl+Q를 누르면 시스템은 현재 TUI 애플리케이션의 종료 동작을 요청한다. 종료 요청은 해당 단축키 입력에 대해 수행되며, 종료 과정에서 대화 기능을 위해 기록된 상태를 임의로 변경하거나 외부 서비스를 호출하지 않는다. + +**영향 범위** + +인터페이스: TUI 키 바인딩과 애플리케이션 종료 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: Textual 애플리케이션의 종료 명령을 사용할 수 있어야 한다. + +## 6. 제약과 불변조건 + +- 모든 입력은 제출 시점에 앞뒤 공백을 제거한 값으로 정규화한다. +- 정규화 결과가 빈 문자열이면 응답 선택, 메시지 목록 변경, 화면 항목 추가를 수행하지 않는다. +- 유효한 입력은 세션 내 대화 상태에 사용자 메시지와 에이전트 응답을 순서대로 추가한다. +- 에이전트 응답은 사전에 정의된 다섯 개의 고정 응답 중 표준 난수 선택으로 하나를 결정한다. +- 화면에 표시되는 사용자 메시지와 에이전트 응답의 작성자 역할, 라벨, 스타일은 메시지 역할에서 일관되게 파생되어야 한다. +- 유효한 입력을 처리한 뒤 입력창은 항상 빈 값으로 초기화한다. +- 빈 입력 또는 공백만 포함한 입력을 처리해도 기존 대화 상태와 응답 선택 상태는 변경되지 않아야 한다. +- 대화 메시지는 현재 실행 세션에만 누적하며 외부 API, 데이터베이스 또는 영속 저장소를 사용하지 않는다. +- 입력 제출 순서와 메시지 표시 순서를 보존해야 하며, 각 사용자 메시지 바로 뒤에 해당 응답을 배치한다. +- 종료 동작은 Escape와 Ctrl+Q 입력에 대해 애플리케이션 종료를 요청해야 하며, 종료 시 새로운 대화 메시지를 추가하지 않는다. +- 프로젝트 실행 기반과 패키징 계약은 선행 요구사항의 범위를 유지하며, 이 문서에서는 이를 변경하지 않는다. +- 구현은 승인된 분리 범위를 벗어나 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 도입하지 않는다. + +## 7. 인수 기준 + +- 앞뒤에 공백이 포함된 유효한 입력을 제출하면 공백이 제거된 사용자 메시지가 대화 영역과 세션 상태에 기록되어야 한다. +- 유효한 입력마다 사용자 메시지 하나와 고정 응답 하나가 생성되고, 대화 영역에는 사용자 메시지 다음에 해당 응답이 표시되어야 한다. +- 선택된 응답은 정의된 다섯 개의 고정 응답 중 하나여야 하며, 표준 난수 선택 절차가 호출되어야 한다. +- 여러 입력을 연속해서 제출하면 각 입력과 응답 쌍이 제출 순서대로 누적되어야 한다. +- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로 표시되고, 에이전트 응답은 에이전트 라벨과 응답용 구조적 스타일로 표시되어야 한다. +- 유효한 입력을 제출한 뒤 입력창 값은 빈 문자열이어야 한다. +- 빈 문자열을 제출하면 대화 목록, 제출 입력 목록, 선택 응답 목록 및 화면 항목이 변경되지 않아야 한다. +- 공백과 탭 또는 줄바꿈만 포함한 입력을 제출해도 빈 입력과 동일하게 처리되어야 하며 응답 선택이 호출되지 않아야 한다. +- Escape를 누르면 애플리케이션 종료 요청이 발생해야 한다. +- Ctrl+Q를 누르면 Escape와 동일한 종료 동작이 발생해야 한다. +- 종료 단축키를 처리해도 대화 메시지나 입력 처리 상태가 새로 기록되어서는 안 된다. +- 패키지 실행 진입점에서 대화 화면을 시작할 수 있어야 하며, 대화 기능 검증은 선행 프로젝트 스캐폴드 계약과 함께 수행할 수 있어야 한다. + +### REQ-002.01-AC01 — 앞뒤 공백을 제거한 입력을 처리한다 + +**판정 기준** + +앞뒤 공백이 포함된 입력을 제출했을 때 대화 상태와 화면에는 공백이 제거된 본문만 사용자 메시지로 남으면 통과로 판정한다. + +**검증** + +TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입력 목록, 메시지 본문 및 표시 라벨을 확인한다. + +**검증 분류** + +수준: integration; 백엔드: Textual 입력 이벤트와 대화 상태; 케이스: positive + +**상태 불변조건** + +성공 시 정규화된 본문만 사용자 메시지로 기록되어야 한다. 원본의 앞뒤 공백은 표시되거나 후속 응답 선택의 입력으로 사용되지 않아야 한다. + +### REQ-002.01-AC02 — 빈 입력과 공백 입력을 무시한다 + +**판정 기준** + +빈 문자열 또는 공백과 탭 및 줄바꿈만 포함한 값을 제출해도 응답 선택, 메시지 추가, 화면 항목 생성이 모두 발생하지 않으면 통과로 판정한다. + +**검증** + +빈 입력과 공백만 포함한 입력을 각각 제출하고 메시지 목록, 제출 입력 목록, 선택 응답 목록 및 대화 영역의 표시 항목 수를 확인한다. + +**검증 분류** + +수준: integration; 백엔드: Textual 입력 이벤트와 응답 선택 경계; 케이스: boundary + +**상태 불변조건** + +무효 입력 처리 후 대화 상태와 표시 영역은 변경되지 않아야 한다. 응답 선택 함수는 호출되지 않아야 하며 부분 메시지도 남지 않아야 한다. + +### REQ-002.02-AC01 — 사용자 메시지 뒤에 선택 응답을 표시한다 + +**판정 기준** + +유효 입력 하나를 제출했을 때 사용자 메시지와 선택된 응답이 같은 제출 순서로 연속 표시되고 작성자 라벨이 각각 사용자와 에이전트로 구분되면 통과로 판정한다. + +**검증** + +응답 선택을 고정한 상태에서 입력을 제출하고 내부 메시지 목록과 대화 영역의 표시 순서를 비교한다. + +**검증 분류** + +수준: integration; 백엔드: Textual 렌더링과 대화 모델; 케이스: positive + +**상태 불변조건** + +성공 시 사용자 메시지가 응답보다 먼저 존재해야 한다. 두 메시지는 동일 제출에 속하지만 역할과 본문을 서로 바꾸거나 합쳐서는 안 된다. + +### REQ-002.02-AC02 — 응답을 고정 목록에서 표준 방식으로 선택한다 + +**판정 기준** + +유효 입력마다 고정된 응답 목록을 대상으로 표준 난수 선택이 한 번 수행되고 선택 결과가 상태와 화면에 동일하게 반영되면 통과로 판정한다. + +**검증** + +난수 선택 함수를 감시하거나 고정된 결과를 반환하도록 설정한 뒤 유효 입력을 제출하고 호출 인자와 표시 결과를 확인한다. + +**검증 분류** + +수준: unit; 백엔드: Python 표준 난수 선택과 응답 상수; 케이스: positive + +**상태 불변조건** + +응답은 선언된 고정 목록 밖의 값이 될 수 없다. 무효 입력에서는 선택이 발생하지 않아야 하며 선택 결과와 표시 결과가 달라서는 안 된다. + +### REQ-002.02-AC03 — 여러 제출을 기존 순서 뒤에 누적한다 + +**판정 기준** + +두 번 이상의 유효 입력을 순서대로 제출했을 때 각 입력과 응답 쌍이 제출 순서와 동일하게 대화 상태 및 화면에 누적되면 통과로 판정한다. + +**검증** + +서로 다른 두 입력을 제출하고 제출 입력 목록, 선택 응답 목록, 메시지 목록 및 렌더링된 라벨의 전체 순서를 확인한다. + +**검증 분류** + +수준: integration; 백엔드: 세션 대화 상태와 Textual 위젯 트리; 케이스: positive + +**상태 불변조건** + +새 제출은 기존 메시지를 삭제하거나 재정렬하지 않아야 한다. 각 유효 입력은 사용자 메시지 하나와 응답 하나를 추가해야 하며 이전 상태는 보존되어야 한다. + +### REQ-002.03-AC01 — 유효 입력 제출 후 입력창을 비운다 + +**판정 기준** + +유효한 입력을 제출한 직후 입력 위젯의 값이 빈 문자열이면 통과로 판정한다. + +**검증** + +입력 위젯에 정규화 전 공백을 포함한 값을 설정하고 Enter를 누른 뒤 위젯 값을 확인한다. + +**검증 분류** + +수준: integration; 백엔드: Textual Input 위젯; 케이스: positive + +**상태 불변조건** + +입력창 초기화는 사용자 메시지와 응답의 기록을 삭제하거나 변경해서는 안 된다. 초기화 후 다음 제출을 위한 위젯이 재사용 가능해야 한다. + +### REQ-002.03-AC02 — 무효 입력 제출 후에도 입력창을 비운다 + +**판정 기준** + +빈 값 또는 공백만 있는 값을 제출한 뒤에도 입력 위젯의 값이 빈 문자열이면 통과로 판정한다. + +**검증** + +빈 입력과 공백 입력을 제출하고 각각 제출 후 입력 위젯 값을 확인한다. + +**검증 분류** + +수준: integration; 백엔드: Textual Input 위젯과 입력 검증; 케이스: unchanged-state + +**상태 불변조건** + +입력창은 비워져야 하지만 대화 상태, 선택 응답 및 표시 영역은 그대로 유지되어야 한다. + +### REQ-002.04-AC01 — 역할에 따라 라벨과 스타일을 구분한다 + +**판정 기준** + +사용자 메시지가 사용자 라벨과 사용자 메시지 스타일을 갖고 응답 메시지가 에이전트 라벨과 응답 메시지 스타일을 가지면 통과로 판정한다. + +**검증** + +각 역할의 메시지를 대화 영역에 표시한 뒤 렌더링 텍스트와 스타일 클래스를 확인한다. + +**검증 분류** + +수준: unit; 백엔드: 메시지 모델과 Textual 렌더링; 케이스: positive + +**상태 불변조건** + +메시지 역할과 표시 라벨이 서로 불일치해서는 안 된다. 역할에 따른 정렬과 경계 스타일은 반대 역할에 적용되지 않아야 한다. + +### REQ-002.05-AC01 — Escape 입력으로 종료를 요청한다 + +**판정 기준** + +실행 중인 애플리케이션에서 Escape를 누르면 애플리케이션 종료 함수가 인자 없이 호출되면 통과로 판정한다. + +**검증** + +테스트 실행 중 종료 함수를 감시하고 Escape 키를 입력한 뒤 정확히 한 번 호출되었는지 확인한다. + +**검증 분류** + +수준: end-to-end; 백엔드: Textual 키 바인딩과 애플리케이션 생명 주기; 케이스: positive + +**상태 불변조건** + +종료 요청은 입력 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 함수 호출 전후에 외부 연동이나 영속 상태 변경이 발생하지 않아야 한다. + +### REQ-002.05-AC02 — Ctrl+Q 입력으로 종료를 요청한다 + +**판정 기준** + +실행 중인 애플리케이션에서 Ctrl+Q를 누르면 Escape와 동일한 종료 동작이 수행되면 통과로 판정한다. + +**검증** + +종료 함수를 감시한 상태에서 Ctrl+Q를 입력하고 종료 요청이 정확히 한 번 발생하는지 확인한다. + +**검증 분류** + +수준: end-to-end; 백엔드: Textual 키 바인딩과 애플리케이션 생명 주기; 케이스: positive + +**상태 불변조건** + +두 종료 단축키는 동일한 종료 경로를 사용해야 한다. 종료 입력은 새 메시지나 응답을 생성하거나 기존 대화 순서를 변경해서는 안 된다. + +## 8. 오류 및 충돌 계약 + +- 입력 제출 이벤트를 사용할 수 없는 초기화 실패나 위젯 조회 실패가 발생하면 정상적인 메시지 추가로 판정하지 않으며 부분적으로 생성된 대화 상태를 성공 상태로 남기지 않는다. +- 입력값이 빈 문자열 또는 공백만 포함한 값이면 오류가 아니라 무시 가능한 입력으로 처리하고, 응답 선택과 메시지 추가를 수행하지 않는다. +- 응답 선택에 실패하면 해당 입력에 대한 사용자 메시지와 에이전트 응답을 부분적으로 기록하지 않아야 한다. +- 고정 응답 목록이 비어 있거나 정의된 계약과 다르면 응답을 생성하지 않고 처리 실패로 식별해야 한다. +- 메시지 렌더링에 실패하면 화면에 일부 항목만 남은 상태를 완전한 처리 성공으로 간주하지 않으며, 세션 상태와 화면 상태의 불일치를 정상 결과로 기록하지 않는다. +- 입력창 초기화에 실패하면 처리 결과를 완전한 성공으로 판정하지 않아야 하며, 이후 입력 처리에서 이전 값이 재사용되지 않도록 실패 원인을 확인할 수 있어야 한다. +- 종료 요청은 이미 종료된 애플리케이션에서 중복 메시지나 대화 상태를 추가하지 않아야 한다. +- 외부 API, 네트워크, 파일 저장소 또는 데이터베이스 오류를 대화 처리의 대체 경로로 사용하지 않는다. +- 지원되지 않는 실행 환경이나 선행 패키지 실행 조건을 충족하지 못한 상태에서는 대화 동작이 정상적으로 제공된 것으로 판정하지 않는다. +- 오류가 발생한 입력은 응답 선택 목록과 메시지 목록에 부분 기록을 남기지 않아야 하며, 앞서 성공한 세션 메시지는 변경하지 않는다. + +## 9. 데이터 및 인터페이스 계약 + +- 입력 인터페이스는 대화 입력 위젯에서 Enter로 제출되는 문자열 값을 사용한다. +- 입력값은 문자열로 취급하고 제출 시 앞뒤 공백을 제거한다. 문자열 내부의 공백은 정규화하지 않는다. +- 정규화된 입력이 비어 있지 않으면 사용자 메시지의 본문으로 저장하고 화면에 표시한다. +- 고정 응답 목록은 다음 다섯 문장을 정본으로 사용한다: "안녕하세요! 무엇을 도와드릴까요?", "그것은 제가 처리하기 불가능합니다.", "맡겨만 주세요.", "지금 처리 중입니다.", "작업을 완료하였습니다.". +- 응답 선택은 정본 고정 응답 목록을 표준 난수 선택 함수에 전달하여 수행한다. +- 세션 대화 상태의 각 메시지는 작성자 역할과 본문을 함께 보유한다. 작성자 역할은 사용자 또는 에이전트 중 하나이며, 본문은 비어 있지 않은 문자열이다. +- 화면 표시 문자열은 사용자 메시지의 경우 "사용자: 본문" 형식으로, 에이전트 응답의 경우 "에이전트: 본문" 형식으로 구성한다. +- 사용자 메시지와 에이전트 응답은 서로 다른 구조적 스타일을 사용하며, 스타일은 임의의 본문 문자열이 아니라 작성자 역할에서 파생한다. +- 유효한 제출 하나는 사용자 메시지와 그에 대응하는 에이전트 응답의 두 항목으로 구성되며, 두 항목은 인접한 순서를 유지한다. +- 빈 입력 제출은 입력창을 빈 값으로 만들 수 있지만 대화 메시지, 선택 응답 및 화면 항목을 생성하지 않는다. +- 입력창은 초기 화면에서 사용자 입력을 받을 수 있어야 하며, 유효한 제출 처리 후에도 다시 입력 가능한 상태를 유지한다. +- Escape와 Ctrl+Q는 별도 데이터 값을 생성하지 않고 애플리케이션 종료 동작을 요청하는 키 입력 인터페이스이다. +- 메시지와 선택 응답은 현재 프로세스의 세션 메모리에만 보관하며, 애플리케이션 종료 후 재조회하거나 복구하는 인터페이스는 제공하지 않는다. + +## 10. 하위 호환성 + +- `chat-tui`와 `python -m chat_tui` 실행 방식은 선행 프로젝트 스캐폴드 요구사항에 정의된 계약을 유지해야 한다. +- 기존 Textual 기반 화면 진입과 입력 위젯의 역할을 유지하며, 대화 기능 분리로 설치 방법이나 실행 명령을 변경하지 않는다. +- 기존의 입력 정규화, 메시지 누적, 고정 응답 선택, 응답 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 의미를 변경하지 않는다. +- 기존에 공백이 포함된 유효한 입력을 제출하면 정규화된 값만 대화에 기록해야 하며, 공백만 입력한 경우에는 아무 대화 항목도 추가하지 않아야 한다. +- 고정 응답 문구와 사용자 및 에이전트 표시 라벨은 기존 동작과 호환되도록 유지한다. +- Escape와 Ctrl+Q를 통한 종료 방식은 기존 호출자와 사용자의 추가 변환 없이 계속 사용할 수 있어야 한다. +- 세션 내 메시지 누적은 유지하되, 영속성이나 외부 서비스 연동을 새로 도입하지 않는다. +- 테스트와 문서는 기능을 신규 요구사항으로 분리하더라도 실제 애플리케이션 코드가 제공하는 동작과 일치해야 한다. +- 프로젝트 스캐폴드, Python 지원 버전, Textual 의존성, 패키지 이름과 실행 진입점은 이 요구사항의 변경 대상이 아니다. +- 대화 기능을 사용하는 기존 호출자는 별도 마이그레이션 없이 동일한 입력과 키 조작으로 동일한 관찰 결과를 얻을 수 있어야 한다. + +## 11. 검증 계획 + +Python 3.11 이상 환경에서 애플리케이션을 실행하고 대화 입력과 종료 동작을 검증한다. 정상 입력에서는 앞뒤 공백이 제거된 사용자 메시지와 고정 응답이 입력 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 세션 내 메시지와 내부 누적 상태가 사용자 메시지와 응답의 쌍으로 유지되는지 확인한다. 공백 또는 빈 입력에서는 응답 선택, 메시지 누적, 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택은 사전에 정의된 다섯 개 문구에서 표준 난수 선택으로 수행되는지 확인하며, 선택된 응답이 에이전트 역할과 구분되어 표시되는지 검증한다. 입력창 초기화는 유효 입력과 무효 입력 모두에서 제출 직후 수행되는지 확인한다. Escape와 Ctrl+Q 입력은 애플리케이션 종료를 요청하고 종료 전에 추가 메시지나 응답을 생성하지 않는지 확인한다. 기존 패키지 설치와 두 실행 진입점의 검증을 통과한 뒤 대화 기능 회귀 검증을 수행하며, 외부 API나 영속 저장소 없이 저장소의 자동화 테스트로 결과를 판정한다. + +### 테스트 추적성 계약 + +테스트 정의: + +```text +Test ID: TC-002-001 +Verifies: +- REQ-002.01-AC01 +- REQ-002.01-AC02 +- REQ-002.02-AC01 +- REQ-002.02-AC02 +- REQ-002.02-AC03 +- REQ-002.03-AC01 +- REQ-002.03-AC02 +- REQ-002.04-AC01 +- REQ-002.05-AC01 +- REQ-002.05-AC02 +Test reference: tests/test_app.py 및 python -m unittest discover -s tests -v +Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스트를 사용하여 입력, 응답, 빈 입력, 스타일과 종료 동작을 자동 검증한다. +``` + +실행 증거: + +```text +Test ID: TC-002-001 +Requirement revision: REQ-002@0.1 +Commit: d0ac7fc7bcfaf402bbda24776f051fa9992993e1 +Environment: Python 3.11 이상, 선언된 Textual 런타임 의존성이 설치된 환경 +Result: 미실행 +Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 +``` + +## 12. 추적성 + +근거는 원본 이슈의 요구사항 재작업 요청, 기존 프로젝트 스캐폴드 요구사항 문서, README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하며, 그 선행 요구사항의 의미나 실행 계약을 변경하지 않는다. 사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 패키징 메타데이터와 실행 진입점은 선행 문서에서 추적하고 이 문서에서는 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 응답 목록, 역할별 표시 구조와 종료 바인딩 및 관련 테스트가 각 동작의 근거와 검증 지점이다. + +## 13. 확정된 결정 + +기존 구현과 테스트가 정의한 대화 동작을 별도 요구사항으로 분리하여 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 아무 대화 항목도 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 사전 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. 사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 애플리케이션 종료 동작을 요청한다. 외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. + +## 14. 미결 사항 + +없음 + +## 15. 승인 기록 + +상태는 초안이다. 승인 주체는 아직 지정되지 않았으며, 승인 근거도 기록되지 않았다. 디스커버리 승인에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행해야 한다. -- 2.54.0 From 925c107f9acc4c73a03f2f0daac837716d420b8d Mon Sep 17 00:00:00 2001 From: code-agent Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH 2/5] code-agent: rework issue 8 Review-ID: 38 Previous-SHA: 1f73b4bd414d9d579cdaeef391377d4959910c48 Plan-SHA256: cbefda14ef548909f419e943825b3d11d9dff9809b9bb443b06d43db183063c0 Bundle-SHA256: 29ce1ef1917864f79938459725201e6e74d67e21b1f817ac53d7b294eca8f1a2 --- docs/requirements/req-001_project-scaffold.md | 147 ++++++++------ .../req-002_conversation-interaction.md | 186 +++++++++--------- 2 files changed, 174 insertions(+), 159 deletions(-) diff --git a/docs/requirements/req-001_project-scaffold.md b/docs/requirements/req-001_project-scaffold.md index 248eada..df48721 100644 --- a/docs/requirements/req-001_project-scaffold.md +++ b/docs/requirements/req-001_project-scaffold.md @@ -4,7 +4,7 @@ "id": "REQ-001", "title": "프로젝트 스캐폴드와 실행 진입점", "revision": "0.1", - "status": "draft", + "status": "approved", "depends_on": [], "applies_to": [ "프로젝트 스캐폴드", @@ -19,23 +19,21 @@ ## 1. 목적 -이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 지정된 콘솔 명령 또는 모듈 실행 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 이 범위에 포함하지 않는다. +이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 지정된 콘솔 명령 또는 모듈 실행 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 별도 요구사항에서 관리하며 이 문서에서는 정본으로 정의하지 않는다. + +기존 프로젝트 스캐폴드 요구사항의 정체성과 승인 이력은 유지한다. 기존 승인 상태와 승인 근거를 임의로 초안 상태로 되돌리거나 삭제하지 않으며, 이번 문서 정리는 프로젝트 스캐폴드와 실행 기반의 범위만 명확히 하는 변경으로 한정한다. ## 2. 배경 프로젝트는 소스 코드를 `src` 레이아웃 아래에 두고 `chat_tui` 패키지로 제공한다. 패키징은 setuptools 빌드 백엔드를 사용하며 Python 3.11 이상을 실행 환경으로 요구한다. 런타임에는 Textual 0.47 이상 1.0 미만을 사용하고, 테스트용 선택 의존성으로 pytest 8.0 이상을 제공한다. 패키지 버전은 현재 0.1.0으로 관리한다. +패키지 설치와 실행 진입점은 대화 기능과 독립적으로 검증할 수 있는 프로젝트 기반 계약이다. 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 원본 이슈인 Gitea 이슈 #8의 재작업 범위에 따라 별도 대화 요구사항 문서에서 추적한다. + ## 3. 범위 -포함 범위는 다음과 같다. +이 문서는 `src/chat_tui` Python 패키지의 기본 구조, 패키지 버전 공개, `pyproject.toml`의 빌드 시스템과 프로젝트 메타데이터, Python 및 런타임 의존성, 테스트 선택 의존성, `chat-tui` 콘솔 스크립트와 `python -m chat_tui` 모듈 실행 진입점을 포함한다. 소스 디렉터리를 패키지 탐색 대상으로 사용하는 설치 구조도 포함한다. -- `src/chat_tui` Python 패키지의 기본 구조와 패키지 버전 공개 -- `pyproject.toml`의 빌드 시스템, 프로젝트 메타데이터, Python 버전, 런타임 및 테스트 의존성 정의 -- `chat-tui` 콘솔 스크립트가 애플리케이션의 실행 함수를 호출하는 진입점 제공 -- `python -m chat_tui` 방식으로 패키지를 실행할 수 있는 모듈 진입점 제공 -- 소스 디렉터리를 패키지 탐색 대상으로 사용하는 설치 구조 - -제외 범위는 대화 입력 정규화, 메시지 누적, 응답 선택 및 표시, 빈 입력 처리, 종료 단축키와 같은 애플리케이션 동작 계약이다. 외부 API 연동, 영속성, 배포 환경 변경과 새 의존성 추가도 포함하지 않는다. +대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 역할별 대화 표시, 빈 입력 처리, 입력창 초기화와 종료 단축키의 상세 동작 및 수용 기준은 포함하지 않는다. 해당 내용은 별도 대화 상호작용 요구사항에서 단일 정본으로 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경 변경도 포함하지 않는다. ### 포함 @@ -43,7 +41,7 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 ### 제외 -사용자 입력 정규화, 대화 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용 동작은 다루지 않는다. +사용자 입력 정규화, 대화 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용 동작은 다루지 않는다. 외부 API 연동, 영속성, 배포 환경 변경과 새 의존성 추가도 포함하지 않는다. ## 4. 용어와 기준 @@ -52,11 +50,12 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 - 프로젝트 이름은 `gitea-agent-testbed`이고 Python 패키지 이름은 `chat_tui`이다. - 소스 루트는 `src`이며 패키지 탐색 설정은 해당 루트를 기준으로 한다. - 패키지 초기화 모듈은 패키지 버전 `0.1.0`을 공개한다. -- 모듈 실행 진입점은 애플리케이션 모듈의 실행 함수를 호출한다. +- 모듈 실행 진입점은 애플리케이션 모듈의 공개 실행 함수를 호출한다. - 콘솔 스크립트 진입점은 `chat_tui.app:main`으로 연결한다. - 빌드 백엔드는 setuptools를 사용하고 빌드 요구 버전은 68 이상이다. - 테스트 설정은 `src`를 Python 경로에 포함하고 `tests` 디렉터리를 검색 대상으로 한다. -- 문서와 소스의 스캐폴드 설명은 실제 패키지 구조와 패키징 설정에 부합해야 한다. +- 프로젝트 스캐폴드 설명은 실제 패키지 구조와 패키징 설정에 부합해야 한다. +- 대화 상호작용의 의미와 세부 검증 기준은 이 문서가 아니라 분리된 대화 요구사항을 기준으로 한다. ## 5. 요구사항 @@ -67,21 +66,41 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 - 프로젝트 메타데이터에는 프로젝트 이름, 현재 버전, 설명, README 참조, Python 최소 버전과 Textual 런타임 의존성이 포함되어야 한다. - 테스트 선택 의존성을 별도로 설치할 수 있어야 하며 pytest 8.0 이상을 지정해야 한다. - `chat-tui` 명령을 실행하면 `chat_tui.app` 모듈의 `main` 함수가 호출되어 애플리케이션 시작 절차로 진입해야 한다. -- `python -m chat_tui`를 실행하면 패키지의 모듈 진입점이 동일한 애플리케이션 시작 함수를 호출해야 한다. -- 패키지 버전은 초기 스캐폴드 기준으로 `0.1.0`을 일관되게 노출해야 한다. -- 패키징 및 실행 진입점 검증은 대화 기능의 세부 동작과 독립적으로 수행할 수 있어야 한다. +- `python -m chat_tui`를 실행하면 콘솔 명령과 동일한 애플리케이션 시작 함수를 호출해야 한다. +- 패키지 버전은 초기 스캐폴드 기준인 `0.1.0`을 일관되게 노출해야 한다. +- 패키징 및 실행 진입점 검증은 대화 기능의 상세 동작과 독립적으로 수행할 수 있어야 한다. + +**Python 패키지 구조와 메타데이터** + +프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전, 설명, Python 3.11 이상 실행 조건과 Textual 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있어야 한다. + +영향 범위는 Python 패키지 설치와 import 경계, 개발자와 패키지 설치 도구 및 실행 진입점에 한정된다. 영속성 변경과 마이그레이션은 없으며, Python 3.11 이상과 기존 패키지 이름을 유지한다. setuptools 기반 editable 설치가 가능해야 한다. + +**모듈 실행 진입점** + +프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수를 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. + +영향 범위는 모듈 실행 계약과 Python 모듈 실행 환경에 한정된다. 영속성 변경과 마이그레이션은 없으며, 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다. + +**콘솔 스크립트 실행 진입점** + +패키징 설정은 `chat-tui` 콘솔 명령을 애플리케이션 모듈의 공개 실행 함수에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 한다. + +영향 범위는 설치 후 제공되는 콘솔 명령과 최종 사용자 및 운영 스크립트에 한정된다. 영속성 변경과 마이그레이션은 없으며, 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 패키지 설치 시 console script가 생성되어야 한다. + +대화 입력, 응답, 메시지 표시와 종료 동작의 상세 요구사항 및 수용 기준은 이 문서에 중복해서 정의하지 않고 분리된 대화 요구사항에서 관리한다. ### REQ-001.01 — Python 패키지 구조와 메타데이터를 제공한다 -프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전, 설명, Python 3.11 이상 실행 조건, Textual 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있어야 한다. +프로젝트는 Python 3.11 이상에서 설치 및 실행 가능한 표준 Python 패키지 구조를 제공해야 한다. 소스 루트는 `src`이며 `src/chat_tui` 패키지를 배포 대상으로 포함해야 한다. setuptools 빌드 백엔드와 소스 디렉터리 패키지 검색 설정을 사용하고, 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 최소 버전 및 Textual 0.47 이상 1.0 미만의 런타임 의존성을 패키징 메타데이터에 선언해야 한다. 테스트용 pytest 8.0 이상 의존성은 선택적으로 설치할 수 있어야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. **영향 범위** -인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구, 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상과 기존 패키지 이름을 유지한다. 배포 전제 조건: setuptools 기반 editable 설치가 가능해야 한다. +인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구와 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상, 프로젝트 이름, 패키지 이름과 버전 계약을 유지한다. 배포 전제 조건: setuptools 기반 설치와 `src` 패키지 탐색이 가능해야 한다. ### REQ-001.02 — 모듈 실행 진입점을 제공한다 -프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수를 호출하고, 실행 가능한 모듈로 직접 호출되었을 때만 애플리케이션을 시작해야 한다. +프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 진입점은 애플리케이션의 공개 실행 함수인 `main`을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. 실행 진입점은 설치된 패키지와 선언된 런타임 환경에서 동일한 애플리케이션 시작 흐름으로 연결되어야 한다. **영향 범위** @@ -89,7 +108,7 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 ### REQ-001.03 — 콘솔 스크립트 실행 진입점을 제공한다 -패키징 설정은 `chat-tui` 콘솔 명령을 애플리케이션 모듈의 공개 실행 함수에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 한다. +패키징 설정은 `chat-tui` 콘솔 명령을 `chat_tui.app:main`에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 하며, 콘솔 명령과 모듈 실행 명령은 동일한 애플리케이션 시작 동작을 호출해야 한다. **영향 범위** @@ -98,34 +117,36 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 ## 6. 제약과 불변조건 - 프로젝트는 Python 3.11 이상에서 실행되어야 한다. -- 패키지 구성은 `src` 기반 레이아웃을 유지하며, 애플리케이션 패키지와 테스트 패키지의 책임을 분리해야 한다. -- 런타임 의존성은 Textual 계열의 호환 범위 안에서 관리하고, 테스트 의존성은 선택적 설치 항목으로 제공해야 한다. -- 패키징 메타데이터, 버전, 설명, 지원 Python 버전은 서로 일관되어야 한다. -- 콘솔 실행 진입점과 모듈 실행 진입점은 동일한 애플리케이션 시작 동작을 호출해야 한다. -- 이 범위에서는 대화 입력 정규화, 메시지 누적, 응답 선택과 표시, 빈 입력 처리 및 종료 동작의 의미를 변경하지 않는다. +- 패키지 구성은 `src` 기반 레이아웃을 유지하고 애플리케이션 패키지와 테스트 패키지의 책임을 분리해야 한다. +- 런타임 의존성은 호환되는 Textual 범위에서 관리하고 테스트 의존성은 선택적 설치 항목으로 제공해야 한다. +- 패키징 메타데이터, 공개 버전, 설명 및 지원 Python 버전은 서로 일관되어야 한다. +- 콘솔 실행 진입점과 모듈 실행 진입점은 동일한 애플리케이션 시작 함수를 호출해야 한다. +- 이 문서는 프로젝트 구조, 패키징 및 실행 진입점만 정본으로 관리하며 대화 상호작용의 상세 규칙과 인수 기준은 별도 요구사항 문서에서 관리한다. - 외부 API, LLM, 데이터베이스, 영속 저장소 또는 추가 배포 환경을 도입하지 않는다. - 기존 프로젝트 구조와 실행 계약을 사용하는 호출자는 별도 변환 없이 계속 사용할 수 있어야 한다. ## 7. 인수 기준 -- 프로젝트를 개발 환경에 설치하면 패키지와 런타임 의존성이 선언된 구성에 따라 설치되어야 한다. -- 설치된 콘솔 명령을 실행하면 애플리케이션의 주 실행 진입점이 호출되어야 한다. -- `python -m chat_tui`로 실행해도 콘솔 명령과 동일한 애플리케이션이 시작되어야 한다. -- 소스 패키지는 `src` 아래에서 검색되어 설치되어야 하며, 패키지 버전과 프로젝트 버전 선언은 일치해야 한다. -- 테스트 의존성을 선택적으로 설치할 수 있어야 하며, 테스트 실행 명령으로 저장소의 테스트를 검색하고 실행할 수 있어야 한다. -- 스캐폴드 변경 후에도 대화 기능과 종료 기능에 대한 기존 회귀 검증이 통과해야 한다. +- Python 3.11 이상 환경에서 프로젝트를 설치하면 `src` 아래의 패키지와 선언된 런타임 의존성이 정상적으로 구성되어야 한다. +- 패키징 설정에 프로젝트 이름, 버전, 설명, README 참조, Python 최소 버전, Textual 의존성 및 소스 디렉터리 검색 설정이 포함되어야 한다. +- 테스트 선택 의존성을 별도로 설치할 수 있고 저장소의 테스트를 검색하여 실행할 수 있어야 한다. +- 설치된 `chat-tui` 명령은 애플리케이션의 공개 시작 함수를 호출해야 한다. +- `python -m chat_tui` 실행도 동일한 공개 시작 함수를 통해 애플리케이션을 시작해야 한다. +- 패키지에서 조회되는 공개 버전과 패키징 메타데이터의 버전은 일치해야 한다. +- 모듈을 단순히 import하는 것만으로 애플리케이션이 시작되어서는 안 된다. - 패키징 설정에 명시되지 않은 외부 연동이나 추가 실행 전제 조건이 없어야 한다. -- 검증은 Python 3.11 이상 환경에서 패키지 설치, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행한다. +- 대화 입력과 응답 동작의 기존 회귀 검증은 별도 요구사항 문서의 범위에서 계속 확인되어야 하며, 이 문서에서는 해당 기준을 반복하지 않는다. +- 검증은 지원되는 Python 환경에서 패키지 설치, 공개 버전 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행한다. ### REQ-001.01-AC01 — 패키징 메타데이터가 프로젝트 계약과 일치한다 **판정 기준** -패키징 설정에 프로젝트 이름, 버전, 설명, Python 3.11 이상 조건, Textual 의존성, 소스 디렉터리 패키지 검색 설정이 모두 선언되어 있으면 PASS로 판정한다. +프로젝트 이름, 버전, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성, pytest 선택 의존성 및 `src` 기반 패키지 검색 설정이 모두 선언되어 있으면 통과로 판정한다. **검증** -`pyproject.toml`을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 editable 설치를 수행하여 패키지가 정상적으로 구성되는지 검증한다. +`pyproject.toml`을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 설치를 수행하여 패키지와 선언된 의존성이 정상적으로 구성되는지 검증한다. **검증 분류** @@ -133,17 +154,17 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 **상태 불변조건** -성공 시 선언된 패키지와 의존성이 설치되어야 한다. 패키징 설정에 명시되지 않은 외부 연동이나 배포 설정은 추가되지 않아야 한다. 설치 실패 시 부분적으로 유효하지 않은 패키지 계약을 성공으로 간주하지 않아야 한다. +성공 시 선언된 패키지와 의존성이 설치되어야 한다. 패키징 설정에 명시되지 않은 외부 연동이나 배포 설정은 추가되지 않아야 한다. 설치 실패 시 유효하지 않은 패키지 계약을 성공으로 간주하지 않아야 한다. -### REQ-001.01-AC02 — 패키지 버전을 import할 수 있다 +### REQ-001.01-AC02 — 패키지 버전을 조회할 수 있다 **판정 기준** -`chat_tui` 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되면 PASS로 판정한다. +`chat_tui` 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되고 패키징 메타데이터의 `0.1.0`과 일치하면 통과로 판정한다. **검증** -Python에서 `chat_tui.__version__`을 조회하고 패키징 설정의 프로젝트 버전과 일치하는지 확인한다. +Python에서 `chat_tui.__version__`을 조회하고 프로젝트 메타데이터의 버전 선언과 비교한다. **검증 분류** @@ -151,17 +172,17 @@ Python에서 `chat_tui.__version__`을 조회하고 패키징 설정의 프로 **상태 불변조건** -성공 시 패키지 import가 가능해야 한다. 버전 조회가 패키지 초기화 중 외부 상태를 변경해서는 안 된다. 조회 실패 시 애플리케이션 실행 진입점의 정상 동작을 성공으로 판정하지 않는다. +성공 시 패키지 import와 버전 조회가 가능해야 한다. 버전 조회가 패키지 초기화 중 외부 상태를 변경해서는 안 된다. 조회 실패 시 패키지 계약을 충족한 것으로 판정하지 않는다. ### REQ-001.02-AC01 — 모듈 명령이 애플리케이션을 시작한다 **판정 기준** -설치된 패키지 환경에서 `python -m chat_tui`를 실행하면 패키지의 실행 함수가 호출되어 TUI가 시작되면 PASS로 판정한다. +설치된 패키지 환경에서 `python -m chat_tui`를 실행했을 때 공개 실행 함수를 통해 TUI가 시작되면 통과로 판정한다. **검증** -모듈 진입점 파일이 애플리케이션의 실행 함수를 import하고 직접 실행 조건에서 호출하는지 확인한 뒤, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다. +모듈 진입점이 애플리케이션의 공개 실행 함수를 직접 실행 조건에서 호출하는지 확인하고, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다. **검증 분류** @@ -169,17 +190,17 @@ Python에서 `chat_tui.__version__`을 조회하고 패키징 설정의 프로 **상태 불변조건** -성공 시 모듈 실행은 공개 실행 함수를 통해 애플리케이션을 시작해야 한다. 모듈을 단순 import하는 것만으로 TUI가 시작되어서는 안 된다. 초기화 실패 시 실행되지 않은 상태를 정상 시작으로 기록하지 않는다. +성공 시 모듈 실행은 공개 실행 함수를 통해 애플리케이션을 시작해야 한다. 모듈을 import하는 것만으로 TUI가 시작되어서는 안 된다. 초기화 실패를 정상 시작으로 기록하지 않는다. -### REQ-001.03-AC01 — 설치 후 콘솔 명령이 생성된다 +### REQ-001.03-AC01 — 설치 후 콘솔 명령이 생성되고 실행된다 **판정 기준** -editable 설치가 완료된 환경에서 `chat-tui` 명령이 PATH에 생성되고 애플리케이션을 시작하면 PASS로 판정한다. +설치가 완료된 환경에서 `chat-tui` 명령이 실행 경로에 생성되고 애플리케이션을 시작하면 통과로 판정한다. **검증** -패키지를 editable 방식으로 설치한 뒤 `chat-tui` 명령의 존재를 확인하고 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다. +패키지를 설치한 뒤 `chat-tui` 명령의 생성 여부와 연결된 실행 대상을 확인하고 명령을 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다. **검증 분류** @@ -191,39 +212,41 @@ editable 설치가 완료된 환경에서 `chat-tui` 명령이 PATH에 생성되 ## 8. 오류 및 충돌 계약 -- 패키지 설치에 필요한 메타데이터가 누락되거나 유효하지 않으면 설치는 성공한 것으로 판정하지 않으며, 설치 과정은 원인 확인 가능한 오류를 반환해야 한다. -- 지원하지 않는 Python 버전에서는 실행을 정상 동작으로 간주하지 않는다. -- 콘솔 진입점 또는 모듈 진입점이 애플리케이션 시작 함수를 찾지 못하면 실행은 실패해야 하며, 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않는다. -- 의존성 버전 제약을 만족하지 못하는 환경에서는 호환되는 런타임으로 자동 대체하거나 외부 서비스를 호출하지 않는다. -- 테스트 의존성 설치 실패는 제품 런타임 의존성의 정상 설치와 별개의 실패로 식별되어야 한다. -- 스캐폴드 변경으로 기존 대화 동작이나 종료 동작이 달라지면 인수에 실패한 것으로 판정한다. -- 설치 또는 실행 실패 시 프로젝트 파일에 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다. +- 패키지 설치에 필요한 메타데이터가 누락되거나 유효하지 않으면 설치를 성공으로 판정하지 않아야 하며 원인을 확인할 수 있는 오류를 반환해야 한다. +- 지원하지 않는 Python 버전에서는 설치 또는 실행을 정상 동작으로 간주하지 않는다. +- 콘솔 진입점이나 모듈 진입점이 애플리케이션 시작 함수를 찾지 못하면 실행은 실패해야 하며 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않아야 한다. +- 의존성 버전 제약을 만족하지 못하는 환경에서는 호환되지 않는 런타임으로 자동 대체하거나 외부 서비스를 호출하지 않는다. +- 테스트 의존성 설치 실패는 제품 런타임 의존성의 정상 설치 실패와 구별되어야 한다. +- 설치 또는 실행 실패 시 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다. +- 패키징 변경으로 별도 대화 요구사항에서 보장하는 동작이나 종료 동작이 달라지면 스캐폴드 인수에 실패한 것으로 판정한다. +- 이 문서와 별도 대화 요구사항 사이에 계약 충돌이 발생하면 프로젝트 실행 기반은 이 문서가, 대화 상호작용은 별도 문서가 정본이며 어느 한쪽의 범위를 임의로 확장하지 않는다. ## 9. 데이터 및 인터페이스 계약 -- 프로젝트 패키지의 정본 위치는 `src/chat_tui`이며, 패키지 검색 기준은 `src`이다. -- 프로젝트 메타데이터는 패키지 이름, 버전, 설명, README 위치, 지원 Python 버전 및 런타임 의존성을 제공해야 한다. +- 프로젝트 패키지의 정본 위치는 `src/chat_tui`이며 패키지 검색 기준은 `src`이다. +- 프로젝트 메타데이터는 프로젝트 이름, 버전, 설명, README 위치, 지원 Python 버전 및 런타임 의존성을 제공해야 한다. - 테스트 의존성은 별도 선택적 의존성 그룹으로 선언되어야 한다. - 콘솔 인터페이스는 `chat-tui` 명령에서 애플리케이션의 `main` 실행 함수를 호출해야 한다. - 모듈 인터페이스는 `python -m chat_tui` 실행 시 패키지의 모듈 진입점에서 동일한 `main` 함수를 호출해야 한다. - 패키지 공개 버전은 프로젝트 메타데이터의 버전과 일치해야 한다. - 실행 진입점은 외부 입력을 별도 프로토콜이나 네트워크 인터페이스로 변환하지 않고 로컬 Textual 애플리케이션을 시작한다. -- 테스트 인터페이스는 표준 unittest 검색 방식으로 저장소 테스트를 실행할 수 있어야 하며, 별도의 서비스나 데이터 저장소를 요구하지 않는다. +- 테스트 인터페이스는 표준 unittest 검색 방식으로 저장소 테스트를 실행할 수 있어야 하며 별도의 서비스나 데이터 저장소를 요구하지 않는다. +- 대화 메시지와 사용자 입력의 데이터 및 화면 인터페이스 계약은 별도 대화 요구사항 문서에서 정의하며 이 문서에서는 재정의하지 않는다. ## 10. 하위 호환성 - 기존의 `chat-tui` 콘솔 실행 방식은 유지되어야 한다. - 기존의 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다. -- Python 3.11 이상 지원 조건과 현재 패키지 이름 및 버전 계약은 유지되어야 한다. +- Python 3.11 이상 지원 조건과 현재 패키지 이름 및 공개 버전 계약은 유지되어야 한다. - `src` 기반 패키지 검색과 애플리케이션 패키지의 공개 버전 노출 방식은 유지되어야 한다. - 기존 README에 설명된 설치 및 실행 명령은 스캐폴드 정리 이후에도 유효해야 한다. -- 대화 동작을 별도 요구사항으로 분리하더라도 현재 구현과 테스트가 보장하는 입력 처리, 응답 표시, 빈 입력 무시 및 종료 동작은 변경하지 않는다. +- 대화 입력, 응답 표시, 빈 입력 처리, 입력창 초기화 및 종료와 같은 상호작용 동작은 별도 대화 요구사항 문서의 정본으로 유지하며 이 문서에서 상세히 반복하지 않는다. - 새 외부 의존성, 외부 연동, 배포 방식 또는 실행 환경을 추가하지 않는다. -- 변경된 요구사항 문서는 프로젝트 스캐폴드와 패키징 및 실행 진입점만 정본 범위로 보유하고, 대화 동작의 세부 계약을 중복해서 정의하지 않는다. +- 스캐폴드 문서의 변경은 프로젝트 구조, 패키징 및 실행 진입점의 범위를 넘어 대화 동작의 의미를 변경해서는 안 된다. ## 11. 검증 계획 -프로젝트 스캐폴드와 패키징 계약은 Python 3.11 이상 환경에서 패키지 설치가 가능한지 검증한다. 패키지 메타데이터, 런타임 의존성, 테스트 선택 의존성, 소스 패키지 검색 설정이 선언된 값과 일치하는지 확인한다. 콘솔 실행 명령과 모듈 실행 명령이 동일한 애플리케이션 진입점으로 연결되는지 확인한다. 기존 대화 동작은 이 문서의 검증 대상에서 제외하고 분리된 대화 요구사항에서 검증한다. 자동화된 저장소 테스트와 패키지 설치 검증을 모두 통과해야 하며, 실행 환경은 지원되는 Python 버전과 선언된 의존성을 기준으로 한다. +Python 3.11 이상 환경에서 패키지 설치와 메타데이터 정합성을 검증한다. 소스 디렉터리 기반 패키지 검색, 런타임 의존성, 선택적 테스트 의존성, 공개 버전이 선언된 계약과 일치하는지 확인한다. 모듈 실행과 콘솔 실행이 동일한 애플리케이션 시작 함수를 호출하는지 확인하고, 기존 저장소 테스트를 실행하여 대화 입력, 응답 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작이 변경되지 않았는지 회귀 검증한다. 테스트 실행 결과와 설치 검증 결과는 실행한 커밋, 환경, 실행 시각 및 성공 여부를 별도 증거로 기록하며, 실행하지 않은 검증을 통과로 간주하지 않는다. ### 테스트 추적성 계약 @@ -253,11 +276,11 @@ Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ## 12. 추적성 -근거는 원본 이슈의 요구사항 재작업 요청과 저장소에 존재하는 프로젝트 메타데이터 및 패키지 진입점 선언이다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 및 콘솔 실행 진입점에 관한 내용만 추적한다. 입력 정규화, 메시지 누적, 응답 선택, 입력창 초기화, 종료 동작과 같은 대화 기능은 별도의 대화 요구사항 문서에서 추적한다. 두 문서 사이에는 프로젝트 실행 기반을 선행 조건으로 하는 의존 관계가 있으며, 각 기능과 수용 기준은 두 문서에 중복 기록하지 않는다. +근거는 Gitea 이슈 #8의 요구사항 재작업 요청과 저장소의 프로젝트 메타데이터, 패키지 구조, 실행 진입점 선언 및 기존 테스트다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 실행과 콘솔 실행 진입점만 추적한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 분리된 대화 상호작용 문서에서만 추적한다. 두 문서는 실행 기반과 대화 동작의 선행 관계만 공유하며 동일한 기능 규칙이나 수용 기준을 반복하지 않는다. 기존 승인 이력은 승인 기록에 보존한다. ## 13. 확정된 결정 -디스커버리에서 확정된 추가 제품 정책이나 구현 변경 결정은 없다. 기존 프로젝트 스캐폴드의 의미와 이력은 유지하고, 대화 동작 요구사항만 별도 문서로 분리한다. 애플리케이션 코드, 테스트 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다. +기존 프로젝트 스캐폴드의 의미와 승인 이력을 보존하고, 혼재되어 있던 대화 상호작용 요구사항과 수용 기준은 별도 문서로 분리한다. 이 문서의 정본 범위는 패키지 구조, 패키징 메타데이터와 두 실행 진입점으로 한정한다. 애플리케이션 코드, 테스트 동작, 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다. ## 14. 미결 사항 @@ -265,4 +288,4 @@ Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ## 15. 승인 기록 -상태는 초안이다. 요구사항 문서 자체의 승인 주체와 승인 근거는 아직 기록되지 않았다. 원본 이슈의 디스커버리는 승인되었으나, 이 문서의 최종 요구사항 승인은 별도 절차에서 수행해야 한다. +상태는 승인이다. 기존 승인 주체인 spec-agent와 기존 승인 근거를 보존하며, 이번 문서 정리는 승인 상태를 초안으로 되돌리지 않는다. 승인된 프로젝트 스캐폴드 범위와 기존 승인 이력은 유지하고, 대화 상호작용을 별도 요구사항 문서로 분리한 변경만 추적한다. diff --git a/docs/requirements/req-002_conversation-interaction.md b/docs/requirements/req-002_conversation-interaction.md index fd88a20..0d95844 100644 --- a/docs/requirements/req-002_conversation-interaction.md +++ b/docs/requirements/req-002_conversation-interaction.md @@ -22,51 +22,35 @@ ## 1. 목적 -이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 입력한 메시지를 정규화하고 세션 내 대화 영역에 누적 표시하는 동작을 정의한다. 유효한 입력에는 고정된 응답 목록에서 하나를 선택하여 사용자 메시지 바로 뒤에 표시하고, 공백만 포함하거나 비어 있는 입력은 대화 상태를 변경하지 않고 무시한다. 입력을 처리한 뒤 입력창을 비우며, 기존 프로젝트 스캐폴드와 실행 진입점에 의존하여 동일한 애플리케이션 흐름 안에서 동작하도록 보장한다. +이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 제출한 입력을 정규화하고, 유효한 메시지와 고정 응답을 세션 내 대화 영역에 순서대로 누적 표시하는 동작을 정의한다. 공백만 포함하거나 비어 있는 입력은 대화 상태를 변경하지 않고 무시하며, 모든 제출 후 입력창을 비운다. 사용자와 에이전트의 역할을 라벨과 구조적 스타일로 구분하고, Escape 및 Ctrl+Q를 통한 종료 요청을 보장한다. 이 대화 동작은 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 원본 Gitea 이슈 #8의 재작업 범위에서 관리한다. ## 2. 배경 -현재 애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 메시지를 작성하고 Enter를 눌러 제출하며, 애플리케이션은 입력 양끝의 공백을 제거한 결과를 세션의 사용자 메시지로 기록한다. 정규화 결과가 유효하면 고정된 다섯 개 응답 중 하나를 표준 난수 선택 방식으로 결정하고, 사용자 메시지와 에이전트 응답을 정해진 순서로 대화 영역에 표시한다. +애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 문자열을 작성하고 Enter로 제출하며, 시스템은 입력 양끝의 공백을 제거한 뒤 유효성을 판단한다. 유효한 입력에는 사전에 정의된 다섯 개의 고정 응답 중 하나를 표준 난수 선택 방식으로 연결하고, 사용자 메시지와 에이전트 응답을 제출 순서대로 표시한다. -대화 기능은 외부 API, LLM, 데이터베이스 또는 영속 저장소를 사용하지 않는다. 메시지와 선택 결과는 실행 중인 세션의 메모리 상태로 관리하며, 프로젝트의 설치 및 실행 기반은 선행 요구사항에 정의된 계약을 따른다. +메시지와 응답은 실행 중인 세션의 메모리 상태로만 관리하며 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 사용하지 않는다. 프로젝트 설치와 실행 진입점은 선행 스캐폴드 요구사항의 계약을 따르고, 대화 상호작용의 상세 규칙과 수용 기준은 이 문서에서 단일 정본으로 관리한다. 원본 근거는 Gitea 이슈 #8이다. ## 3. 범위 -포함 범위는 다음과 같다. +포함 범위는 입력 양끝의 공백 제거와 유효 입력 판정, 유효한 사용자 메시지와 고정 응답의 세션 내 누적, 표준 난수 방식의 응답 선택, 사용자 메시지 뒤에 응답을 배치하는 순서 보장, 사용자와 에이전트의 라벨 및 구조적 스타일 구분, 빈 입력과 공백 입력의 무시, 제출 후 입력창 초기화, Escape 및 Ctrl+Q 종료 요청이다. 선행 프로젝트 스캐폴드 요구사항과의 의존 관계 및 Gitea 이슈 #8 추적성도 포함한다. -- 입력값의 양끝 공백 제거와 정규화 결과 판정 -- 유효한 사용자 입력과 선택된 에이전트 응답의 세션 내 누적 -- 고정된 응답 목록에서 표준 난수 선택 방식으로 응답 결정 -- 사용자 메시지를 먼저 표시하고 그 바로 뒤에 에이전트 응답을 표시하는 순서 보장 -- 작성자 역할에 따른 사용자 및 에이전트 라벨과 구조적 표시 스타일 제공 -- 공백만 포함하거나 비어 있는 입력의 무시 -- 입력 제출 후 입력창 초기화 -- Escape 및 Ctrl+Q를 통한 애플리케이션 종료 요청 -- 선행 프로젝트 스캐폴드 요구사항과의 의존 관계 및 원본 이슈 추적 - -제외 범위는 다음과 같다. - -- 프로젝트 패키징, 설치 설정 및 실행 진입점 자체의 변경 -- 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작의 변경 -- 외부 API, LLM, 네트워크 서비스, 데이터베이스 및 영속 저장소 연동 -- 사용자 인증, 권한 관리, 다중 세션 관리 및 메시지 복원 -- 새로운 런타임 의존성, 배포 방식 또는 실행 환경 추가 +프로젝트 패키징, 설치 설정, 실행 진입점 자체의 변경은 포함하지 않는다. 고정 응답 문구, 입력 처리 순서와 사용자 인터페이스 의미를 변경하지 않으며, 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 인증, 권한 관리, 다중 세션, 메시지 복원, 새 의존성, 배포 방식 또는 실행 환경의 추가도 포함하지 않는다. ### 포함 -사용자 입력의 trim 정규화, 유효한 메시지의 세션 내 누적, 고정된 응답 목록에서의 응답 선택과 표시, 사용자 메시지와 에이전트 응답의 순서 보장, 빈 입력 무시, 입력창 초기화, Escape 및 Ctrl+Q 종료 동작을 다룬다. REQ-001이 제공하는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용한다. +사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 세션 내 누적 및 표시, 응답 선택 순서, 사용자와 에이전트의 역할별 표시, 빈 입력 무시, 입력창 초기화, Escape와 Ctrl+Q 종료 동작 및 REQ-001 의존 관계와 원본 이슈 #8 추적성을 포함한다. ### 제외 -프로젝트 스캐폴드, 패키징 메타데이터와 실행 진입점의 변경은 다루지 않는다. 고정 응답 문구, 입력 처리 순서와 사용자 인터페이스 의미를 변경하지 않으며, LLM, 외부 API, 네트워크 연동, 영속 저장소, 새 의존성, 배포 환경 변경도 포함하지 않는다. +프로젝트 패키징, 설치 설정 및 실행 진입점의 변경, 외부 API·LLM·네트워크 서비스·데이터베이스·영속 저장소 연동, 사용자 인증과 다중 세션 관리, 새로운 의존성·배포 방식·실행 환경 추가는 포함하지 않는다. ## 4. 용어와 기준 -입력은 사용자가 입력창에서 제출한 문자열이며, 정규화는 문자열 양끝의 공백을 제거하는 것을 의미한다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. +입력은 사용자가 입력창에서 제출한 문자열이고, 정규화는 문자열 양끝의 공백을 제거하는 처리다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. -유효한 메시지는 정규화된 사용자 입력과 고정 응답 목록에서 선택된 응답으로 구성된 한 쌍의 대화 항목이다. 사용자 메시지는 사용자 역할을 가지며, 선택된 응답은 에이전트 역할을 가진다. 화면 라벨은 각각 사용자와 에이전트로 표시하고 역할에 대응하는 구조적 스타일을 적용한다. +유효한 제출은 정규화된 사용자 메시지와 고정 응답 목록에서 선택된 에이전트 응답으로 구성된다. 사용자 메시지는 사용자 역할과 사용자 라벨을 가지며, 응답은 에이전트 역할과 에이전트 라벨을 가진다. 각 역할의 표시는 서로 다른 구조적 스타일을 사용하고, 역할과 본문은 세션 메시지의 정본 상태로 함께 보존한다. -고정 응답 목록은 다음 다섯 문구를 정본으로 사용한다. +고정 응답 목록은 다음 다섯 문구로 구성한다. - 안녕하세요! 무엇을 도와드릴까요? - 그것은 제가 처리하기 불가능합니다. @@ -74,68 +58,72 @@ - 지금 처리 중입니다. - 작업을 완료하였습니다. -응답 선택은 표준 난수 선택 기능에 이 목록 전체를 전달하여 수행한다. 선택 결과는 입력마다 하나만 생성하며, 사용자 메시지 다음에 즉시 배치한다. 세션의 메시지 순서와 입력별 선택 결과는 실행 중 메모리 상태를 정본으로 삼는다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며, 종료 과정에서 외부 상태나 영속 데이터는 생성하지 않는다. +응답 선택은 유효한 입력마다 이 목록 전체를 대상으로 표준 난수 선택을 한 번 수행한다. 선택된 응답은 해당 사용자 메시지 바로 뒤에 배치한다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며 종료 과정에서 외부 상태나 영속 데이터를 생성하지 않는다. ## 5. 요구사항 -시스템은 다음 대화 상호작용 요구를 충족해야 한다. +시스템은 다음 대화 상호작용을 제공해야 한다. -- 사용자가 입력을 제출하면 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. -- 정규화한 값이 비어 있지 않은 경우에만 유효한 사용자 메시지로 기록하고 화면에 표시해야 한다. -- 유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 선택 방식으로 응답 하나를 선택해야 한다. +- 입력 제출 시 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. +- 정규화 결과가 비어 있지 않을 때만 사용자 메시지를 세션 상태와 화면에 기록해야 한다. +- 유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 방식으로 응답 하나를 선택해야 한다. - 사용자 메시지는 사용자 역할과 사용자 라벨로 표시하고, 선택된 응답은 에이전트 역할과 에이전트 라벨로 표시해야 한다. -- 각 입력의 사용자 메시지와 응답은 사용자 메시지가 먼저 오고 응답이 바로 뒤따르는 순서로 대화 영역에 누적해야 한다. -- 여러 입력을 제출한 경우 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서를 유지해야 한다. -- 유효한 입력을 처리한 뒤 입력창의 값은 빈 문자열로 초기화해야 한다. -- 비어 있거나 공백만 포함한 입력은 응답을 선택하지 않고 메시지 상태와 화면을 변경하지 않아야 한다. -- 공백 입력을 무시하더라도 입력창은 초기화해야 한다. -- Escape와 Ctrl+Q 입력은 애플리케이션 종료 동작을 요청해야 한다. -- 대화 동작은 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. -- 기존 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 선행 요구사항이 제공하는 실행 환경에서 동작해야 한다. +- 각 사용자 메시지는 대응하는 에이전트 응답보다 먼저 표시되어야 하며, 두 항목은 인접한 순서를 유지해야 한다. +- 여러 입력을 제출해도 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적해야 한다. +- 유효한 입력을 처리한 뒤 입력창은 빈 문자열로 초기화되어야 한다. +- 빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 입력은 응답 선택과 메시지 추가 없이 무시해야 한다. +- 무효 입력을 무시하더라도 입력창은 빈 문자열로 초기화되어야 한다. +- 역할에 따라 라벨과 구조적 스타일을 일관되게 적용해야 하며, 스타일만으로 역할을 판단하는 구조를 사용해서는 안 된다. +- Escape와 Ctrl+Q 입력은 동일한 애플리케이션 종료 동작을 요청해야 한다. +- 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 되며, 종료 시 새 대화 항목을 추가해서는 안 된다. +- 대화 처리는 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. +- 선행 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 해당 실행 환경에서 동작해야 한다. +- 기존 구현과 테스트가 보장하는 입력 정규화, 메시지 누적, 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작을 유지해야 한다. +- 이 대화 동작의 근거와 변경 추적 대상은 Gitea 이슈 #8로 명시해야 하며, 패키징과 실행 기반의 상세 계약은 선행 요구사항에서 중복 정의하지 않아야 한다. ### REQ-002.01 — 입력 정규화와 유효 입력 판정 -사용자가 입력을 제출하면 시스템은 앞뒤 공백을 제거한 값을 정규화한다. 정규화한 값이 빈 문자열이면 해당 제출을 유효한 메시지로 처리하지 않고, 응답을 선택하거나 대화 영역에 항목을 추가하지 않는다. 하나 이상의 문자가 남은 입력만 유효한 사용자 메시지로 처리한다. +사용자가 입력창에서 문자열을 제출하면 시스템은 문자열 양끝의 공백을 제거한 값을 정규화된 입력으로 사용해야 한다. 정규화 결과가 하나 이상의 문자를 포함하면 유효한 사용자 메시지로 처리하고, 빈 문자열이면 유효한 메시지로 처리하지 않아야 한다. 공백, 탭 또는 줄바꿈만 포함한 입력은 응답 선택이나 대화 항목 추가 없이 무시해야 한다. **영향 범위** -인터페이스: 입력 위젯의 제출 처리와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 확인하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 앞뒤 공백 제거와 공백 입력 무시 동작을 유지한다. 배포 전제 조건: 선언된 Textual 런타임에서 입력 이벤트를 처리할 수 있어야 한다. +인터페이스: 입력 위젯의 제출 이벤트와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 검증하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 양끝 공백 제거와 빈 입력 무시 동작을 유지한다. 배포 전제 조건: REQ-001이 제공하는 Textual 실행 환경이 필요하다. -### REQ-002.02 — 유효 메시지와 고정 응답을 순서대로 누적 표시한다 +### REQ-002.02 — 유효 메시지와 고정 응답을 순서대로 누적한다 -유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 먼저 대화 상태와 대화 영역에 추가하고, 고정된 응답 목록에서 표준 난수 선택으로 하나의 응답을 선택한 뒤 바로 이어서 에이전트 메시지로 추가한다. 제출이 반복될 때마다 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적한다. +유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 사용자 역할로 먼저 대화 상태와 대화 영역에 추가해야 한다. 이어서 다음 다섯 개의 고정 응답 목록 전체를 표준 난수 선택 기능에 전달하여 응답 하나를 선택하고, 선택된 응답을 에이전트 역할로 사용자 메시지 바로 뒤에 추가해야 한다: 안녕하세요! 무엇을 도와드릴까요?, 그것은 제가 처리하기 불가능합니다., 맡겨만 주세요., 지금 처리 중입니다., 작업을 완료하였습니다. 여러 입력을 제출하면 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적해야 한다. **영향 범위** -인터페이스: 대화 영역의 메시지 순서와 작성자 표시 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, TUI 렌더링 계층 및 회귀 테스트. 마이그레이션: 필요 없음. 호환성: 기존 고정 응답 목록과 표준 난수 선택 방식을 유지한다. 배포 전제 조건: Textual 대화 영역과 표준 Python 난수 모듈을 사용할 수 있어야 한다. +인터페이스: 대화 영역의 메시지 순서, 본문 및 작성자 역할 표시 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, TUI 렌더링 계층 및 회귀 테스트. 마이그레이션: 필요 없음. 호환성: 기존 고정 응답 문구와 표준 난수 선택 방식을 유지한다. 배포 전제 조건: Textual 대화 영역과 Python 표준 난수 기능을 사용할 수 있어야 한다. ### REQ-002.03 — 제출 후 입력창을 초기화한다 -입력 제출 이벤트가 발생하면 시스템은 제출된 값이 유효한지와 관계없이 입력 위젯의 값을 즉시 빈 문자열로 초기화한다. 초기화는 유효 메시지 처리와 독립적으로 수행되어야 하며, 사용자가 다음 메시지를 입력할 수 있는 상태를 제공한다. +입력 제출 이벤트가 발생하면 시스템은 제출된 값이 유효한지와 관계없이 입력 위젯의 값을 빈 문자열로 초기화해야 한다. 입력창 초기화는 유효한 메시지 처리와 독립적으로 수행되어야 하며, 초기화 이후 사용자가 다음 입력을 제출할 수 있어야 한다. **영향 범위** -인터페이스: 입력 위젯의 값과 연속 입력 경험에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 제출 후 입력창이 비워지는 기존 동작을 유지한다. 배포 전제 조건: Textual Input 위젯이 제출 이벤트에서 갱신 가능해야 한다. +인터페이스: 입력 위젯의 값과 연속 입력 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 유효 입력과 무효 입력 제출 후 입력창을 비우는 기존 동작을 유지한다. 배포 전제 조건: Textual Input 위젯을 제출 이벤트에서 갱신할 수 있어야 한다. ### REQ-002.04 — 역할 기반 메시지 표시를 유지한다 -시스템은 대화 메시지의 작성자 역할을 사용자와 에이전트로 명시적으로 보유하고, 역할에 맞는 라벨과 구조적 스타일을 적용해 표시한다. 사용자 메시지는 사용자 라벨과 사용자 스타일을 사용하고, 응답 메시지는 에이전트 라벨과 응답 스타일을 사용한다. +시스템은 각 대화 메시지에 사용자 또는 에이전트의 작성자 역할을 명시적으로 보유해야 한다. 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로 표시하고, 고정 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시해야 한다. 라벨과 스타일은 임의의 본문 문자열이나 색상만으로 결정하지 않고 메시지 역할에서 일관되게 파생해야 한다. **영향 범위** -인터페이스: 대화 영역의 라벨, 스타일 클래스 및 시각적 구분에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 접근 가능한 화면 검증 및 렌더링 테스트. 마이그레이션: 필요 없음. 호환성: 기존 사용자와 에이전트 역할 구분을 유지한다. 배포 전제 조건: Textual Label 및 CSS 스타일 처리를 사용할 수 있어야 한다. +인터페이스: 대화 영역의 라벨, 스타일 식별자와 시각적 역할 구분에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 화면 검수자 및 렌더링 테스트. 마이그레이션: 필요 없음. 호환성: 기존 사용자와 에이전트 역할 구분 및 표시 순서를 유지한다. 배포 전제 조건: Textual Label과 CSS 스타일 처리를 사용할 수 있어야 한다. -### REQ-002.05 — 종료 단축키로 애플리케이션을 종료한다 +### REQ-002.05 — 종료 단축키로 애플리케이션 종료를 요청한다 -사용자가 Escape 또는 Ctrl+Q를 누르면 시스템은 현재 TUI 애플리케이션의 종료 동작을 요청한다. 종료 요청은 해당 단축키 입력에 대해 수행되며, 종료 과정에서 대화 기능을 위해 기록된 상태를 임의로 변경하거나 외부 서비스를 호출하지 않는다. +사용자가 Escape 또는 Ctrl+Q를 입력하면 시스템은 현재 Textual 애플리케이션의 종료 동작을 요청해야 한다. 두 단축키는 동일한 종료 경로를 사용해야 하며, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 이 요구사항은 원본 Gitea 이슈 #8의 대화 상호작용 재작업 범위를 추적한다. **영향 범위** -인터페이스: TUI 키 바인딩과 애플리케이션 종료 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: Textual 애플리케이션의 종료 명령을 사용할 수 있어야 한다. +인터페이스: TUI 키 바인딩과 애플리케이션 생명 주기에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: REQ-001의 Textual 애플리케이션 실행 계약이 충족되어야 한다. ## 6. 제약과 불변조건 -- 모든 입력은 제출 시점에 앞뒤 공백을 제거한 값으로 정규화한다. +- 모든 입력은 제출 시점에 문자열 양끝의 공백을 제거한 값으로 정규화한다. - 정규화 결과가 빈 문자열이면 응답 선택, 메시지 목록 변경, 화면 항목 추가를 수행하지 않는다. - 유효한 입력은 세션 내 대화 상태에 사용자 메시지와 에이전트 응답을 순서대로 추가한다. - 에이전트 응답은 사전에 정의된 다섯 개의 고정 응답 중 표준 난수 선택으로 하나를 결정한다. @@ -143,10 +131,10 @@ - 유효한 입력을 처리한 뒤 입력창은 항상 빈 값으로 초기화한다. - 빈 입력 또는 공백만 포함한 입력을 처리해도 기존 대화 상태와 응답 선택 상태는 변경되지 않아야 한다. - 대화 메시지는 현재 실행 세션에만 누적하며 외부 API, 데이터베이스 또는 영속 저장소를 사용하지 않는다. -- 입력 제출 순서와 메시지 표시 순서를 보존해야 하며, 각 사용자 메시지 바로 뒤에 해당 응답을 배치한다. +- 입력 제출 순서와 메시지 표시 순서를 보존하며, 각 사용자 메시지 바로 뒤에 해당 응답을 배치한다. - 종료 동작은 Escape와 Ctrl+Q 입력에 대해 애플리케이션 종료를 요청해야 하며, 종료 시 새로운 대화 메시지를 추가하지 않는다. -- 프로젝트 실행 기반과 패키징 계약은 선행 요구사항의 범위를 유지하며, 이 문서에서는 이를 변경하지 않는다. -- 구현은 승인된 분리 범위를 벗어나 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 도입하지 않는다. +- 프로젝트 실행 기반과 패키징 계약은 선행 프로젝트 스캐폴드 요구사항의 범위를 유지하며, 이 문서에서는 변경하지 않는다. +- 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 도입하지 않는다. ## 7. 인수 기준 @@ -163,15 +151,15 @@ - 종료 단축키를 처리해도 대화 메시지나 입력 처리 상태가 새로 기록되어서는 안 된다. - 패키지 실행 진입점에서 대화 화면을 시작할 수 있어야 하며, 대화 기능 검증은 선행 프로젝트 스캐폴드 계약과 함께 수행할 수 있어야 한다. -### REQ-002.01-AC01 — 앞뒤 공백을 제거한 입력을 처리한다 +### REQ-002.01-AC01 — 양끝 공백을 제거하여 유효 입력을 처리한다 **판정 기준** -앞뒤 공백이 포함된 입력을 제출했을 때 대화 상태와 화면에는 공백이 제거된 본문만 사용자 메시지로 남으면 통과로 판정한다. +양끝에 공백이 포함된 유효 입력을 제출했을 때 대화 상태와 화면에 공백이 제거된 본문만 사용자 메시지로 기록되면 통과로 판정한다. **검증** -TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입력 목록, 메시지 본문 및 표시 라벨을 확인한다. +Textual 테스트에서 양끝 공백이 포함된 입력을 제출하고 제출된 입력, 메시지 본문 및 화면 표시값을 비교한다. **검증 분류** @@ -179,17 +167,17 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -성공 시 정규화된 본문만 사용자 메시지로 기록되어야 한다. 원본의 앞뒤 공백은 표시되거나 후속 응답 선택의 입력으로 사용되지 않아야 한다. +성공 시 정규화된 본문만 사용자 메시지로 기록되어야 하며 원본의 양끝 공백은 표시되거나 후속 처리에 사용되지 않아야 한다. ### REQ-002.01-AC02 — 빈 입력과 공백 입력을 무시한다 **판정 기준** -빈 문자열 또는 공백과 탭 및 줄바꿈만 포함한 값을 제출해도 응답 선택, 메시지 추가, 화면 항목 생성이 모두 발생하지 않으면 통과로 판정한다. +빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 값을 제출해도 응답 선택과 메시지 추가 및 새 화면 항목 생성이 발생하지 않으면 통과로 판정한다. **검증** -빈 입력과 공백만 포함한 입력을 각각 제출하고 메시지 목록, 제출 입력 목록, 선택 응답 목록 및 대화 영역의 표시 항목 수를 확인한다. +각 경계 입력을 제출하고 메시지 목록, 응답 선택 기록 및 대화 영역 항목 수를 확인하며 응답 선택 함수가 호출되지 않았는지 검증한다. **검증 분류** @@ -197,35 +185,35 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -무효 입력 처리 후 대화 상태와 표시 영역은 변경되지 않아야 한다. 응답 선택 함수는 호출되지 않아야 하며 부분 메시지도 남지 않아야 한다. +무효 입력 처리 후 기존 대화 상태와 화면은 변경되지 않아야 하며 부분 사용자 메시지나 응답이 남아서는 안 된다. -### REQ-002.02-AC01 — 사용자 메시지 뒤에 선택 응답을 표시한다 +### REQ-002.02-AC01 — 사용자 메시지 뒤에 고정 응답을 표시한다 **판정 기준** -유효 입력 하나를 제출했을 때 사용자 메시지와 선택된 응답이 같은 제출 순서로 연속 표시되고 작성자 라벨이 각각 사용자와 에이전트로 구분되면 통과로 판정한다. +유효 입력 하나를 제출했을 때 정규화된 사용자 메시지와 고정 목록에서 선택된 응답이 인접한 순서로 표시되고 각각 사용자와 에이전트 역할로 구분되면 통과로 판정한다. **검증** -응답 선택을 고정한 상태에서 입력을 제출하고 내부 메시지 목록과 대화 영역의 표시 순서를 비교한다. +응답 선택 결과를 고정한 상태에서 입력을 제출하고 내부 메시지 목록과 대화 영역의 전체 순서를 확인한다. **검증 분류** -수준: integration; 백엔드: Textual 렌더링과 대화 모델; 케이스: positive +수준: integration; 백엔드: Textual 렌더링과 대화 상태; 케이스: positive **상태 불변조건** -성공 시 사용자 메시지가 응답보다 먼저 존재해야 한다. 두 메시지는 동일 제출에 속하지만 역할과 본문을 서로 바꾸거나 합쳐서는 안 된다. +사용자 메시지는 응답보다 먼저 존재해야 하며 두 메시지의 역할과 본문은 서로 바뀌거나 합쳐지지 않아야 한다. -### REQ-002.02-AC02 — 응답을 고정 목록에서 표준 방식으로 선택한다 +### REQ-002.02-AC02 — 고정 목록에서 표준 방식으로 응답을 선택한다 **판정 기준** -유효 입력마다 고정된 응답 목록을 대상으로 표준 난수 선택이 한 번 수행되고 선택 결과가 상태와 화면에 동일하게 반영되면 통과로 판정한다. +유효 입력마다 선언된 다섯 개 응답 목록 전체를 대상으로 표준 난수 선택이 한 번 수행되고 그 결과가 상태와 화면에 동일하게 반영되면 통과로 판정한다. **검증** -난수 선택 함수를 감시하거나 고정된 결과를 반환하도록 설정한 뒤 유효 입력을 제출하고 호출 인자와 표시 결과를 확인한다. +난수 선택 함수를 감시하거나 결과를 고정하여 유효 입력을 제출하고 호출 인자와 표시된 응답을 비교한다. **검증 분류** @@ -233,17 +221,17 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -응답은 선언된 고정 목록 밖의 값이 될 수 없다. 무효 입력에서는 선택이 발생하지 않아야 하며 선택 결과와 표시 결과가 달라서는 안 된다. +응답은 고정 목록 밖의 값이 될 수 없으며 무효 입력에서는 선택이 발생하지 않아야 한다. ### REQ-002.02-AC03 — 여러 제출을 기존 순서 뒤에 누적한다 **판정 기준** -두 번 이상의 유효 입력을 순서대로 제출했을 때 각 입력과 응답 쌍이 제출 순서와 동일하게 대화 상태 및 화면에 누적되면 통과로 판정한다. +서로 다른 유효 입력을 두 번 이상 제출했을 때 각 입력과 응답 쌍이 제출 순서와 동일하게 상태와 화면에 누적되면 통과로 판정한다. **검증** -서로 다른 두 입력을 제출하고 제출 입력 목록, 선택 응답 목록, 메시지 목록 및 렌더링된 라벨의 전체 순서를 확인한다. +두 개 이상의 입력을 순서대로 제출하고 제출 입력, 선택 응답, 메시지 목록 및 렌더링 순서를 확인한다. **검증 분류** @@ -251,7 +239,7 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -새 제출은 기존 메시지를 삭제하거나 재정렬하지 않아야 한다. 각 유효 입력은 사용자 메시지 하나와 응답 하나를 추가해야 하며 이전 상태는 보존되어야 한다. +새 제출은 기존 메시지를 삭제하거나 재정렬하지 않아야 하며 각 유효 입력은 사용자 메시지 하나와 응답 하나를 추가해야 한다. ### REQ-002.03-AC01 — 유효 입력 제출 후 입력창을 비운다 @@ -261,7 +249,7 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **검증** -입력 위젯에 정규화 전 공백을 포함한 값을 설정하고 Enter를 누른 뒤 위젯 값을 확인한다. +입력 위젯에 양끝 공백을 포함한 유효값을 설정하고 Enter를 누른 뒤 위젯 값과 대화 메시지를 확인한다. **검증 분류** @@ -269,17 +257,17 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -입력창 초기화는 사용자 메시지와 응답의 기록을 삭제하거나 변경해서는 안 된다. 초기화 후 다음 제출을 위한 위젯이 재사용 가능해야 한다. +입력창 초기화는 이미 기록된 사용자 메시지와 응답을 삭제하거나 변경해서는 안 된다. ### REQ-002.03-AC02 — 무효 입력 제출 후에도 입력창을 비운다 **판정 기준** -빈 값 또는 공백만 있는 값을 제출한 뒤에도 입력 위젯의 값이 빈 문자열이면 통과로 판정한다. +빈 값 또는 공백만 포함한 값을 제출한 뒤 입력 위젯의 값이 빈 문자열이고 대화 상태가 변경되지 않으면 통과로 판정한다. **검증** -빈 입력과 공백 입력을 제출하고 각각 제출 후 입력 위젯 값을 확인한다. +빈 입력과 공백 입력을 각각 제출하고 제출 후 입력 위젯 값, 메시지 목록 및 응답 선택 기록을 확인한다. **검증 분류** @@ -287,35 +275,35 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -입력창은 비워져야 하지만 대화 상태, 선택 응답 및 표시 영역은 그대로 유지되어야 한다. +입력창은 비워져야 하지만 기존 대화 상태, 응답 선택 상태와 표시 영역은 그대로 유지되어야 한다. ### REQ-002.04-AC01 — 역할에 따라 라벨과 스타일을 구분한다 **판정 기준** -사용자 메시지가 사용자 라벨과 사용자 메시지 스타일을 갖고 응답 메시지가 에이전트 라벨과 응답 메시지 스타일을 가지면 통과로 판정한다. +사용자 메시지가 사용자 라벨과 사용자 스타일을 갖고 에이전트 응답이 에이전트 라벨과 에이전트 스타일을 가지면 통과로 판정한다. **검증** -각 역할의 메시지를 대화 영역에 표시한 뒤 렌더링 텍스트와 스타일 클래스를 확인한다. +각 역할의 메시지를 대화 영역에 표시한 뒤 렌더링 텍스트와 구조적 스타일 식별자를 확인하고 역할과의 대응을 비교한다. **검증 분류** -수준: unit; 백엔드: 메시지 모델과 Textual 렌더링; 케이스: positive +수준: integration; 백엔드: 메시지 모델과 Textual 렌더링; 케이스: positive **상태 불변조건** -메시지 역할과 표시 라벨이 서로 불일치해서는 안 된다. 역할에 따른 정렬과 경계 스타일은 반대 역할에 적용되지 않아야 한다. +메시지 역할과 표시 라벨 및 스타일은 서로 불일치해서는 안 되며 한 역할의 스타일이 다른 역할에 적용되어서는 안 된다. ### REQ-002.05-AC01 — Escape 입력으로 종료를 요청한다 **판정 기준** -실행 중인 애플리케이션에서 Escape를 누르면 애플리케이션 종료 함수가 인자 없이 호출되면 통과로 판정한다. +실행 중인 애플리케이션에서 Escape를 입력했을 때 애플리케이션 종료 동작이 정확히 한 번 요청되면 통과로 판정한다. **검증** -테스트 실행 중 종료 함수를 감시하고 Escape 키를 입력한 뒤 정확히 한 번 호출되었는지 확인한다. +종료 동작을 감시하는 Textual 테스트에서 Escape를 입력하고 종료 요청 횟수와 대화 상태 변경 여부를 확인한다. **검증 분류** @@ -323,17 +311,17 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -종료 요청은 입력 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 함수 호출 전후에 외부 연동이나 영속 상태 변경이 발생하지 않아야 한다. +Escape 입력은 새 메시지나 응답을 생성하거나 입력 제출로 처리되어서는 안 된다. -### REQ-002.05-AC02 — Ctrl+Q 입력으로 종료를 요청한다 +### REQ-002.05-AC02 — Ctrl+Q 입력으로 동일한 종료를 요청한다 **판정 기준** -실행 중인 애플리케이션에서 Ctrl+Q를 누르면 Escape와 동일한 종료 동작이 수행되면 통과로 판정한다. +실행 중인 애플리케이션에서 Ctrl+Q를 입력했을 때 Escape와 동일한 종료 동작이 정확히 한 번 요청되면 통과로 판정한다. **검증** -종료 함수를 감시한 상태에서 Ctrl+Q를 입력하고 종료 요청이 정확히 한 번 발생하는지 확인한다. +종료 동작을 감시한 상태에서 Ctrl+Q를 입력하고 Escape 테스트와 동일한 종료 경로, 호출 횟수 및 상태 불변조건을 확인한다. **검증 분류** @@ -341,11 +329,11 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 **상태 불변조건** -두 종료 단축키는 동일한 종료 경로를 사용해야 한다. 종료 입력은 새 메시지나 응답을 생성하거나 기존 대화 순서를 변경해서는 안 된다. +Ctrl+Q는 Escape와 다른 메시지 처리 경로를 사용해서는 안 되며 종료 시 대화 순서와 기존 세션 상태를 변경해서는 안 된다. ## 8. 오류 및 충돌 계약 -- 입력 제출 이벤트를 사용할 수 없는 초기화 실패나 위젯 조회 실패가 발생하면 정상적인 메시지 추가로 판정하지 않으며 부분적으로 생성된 대화 상태를 성공 상태로 남기지 않는다. +- 입력 제출 이벤트를 사용할 수 없는 초기화 실패나 위젯 조회 실패가 발생하면 정상적인 메시지 추가로 판정하지 않으며, 부분적으로 생성된 대화 상태를 성공 상태로 남기지 않는다. - 입력값이 빈 문자열 또는 공백만 포함한 값이면 오류가 아니라 무시 가능한 입력으로 처리하고, 응답 선택과 메시지 추가를 수행하지 않는다. - 응답 선택에 실패하면 해당 입력에 대한 사용자 메시지와 에이전트 응답을 부분적으로 기록하지 않아야 한다. - 고정 응답 목록이 비어 있거나 정의된 계약과 다르면 응답을 생성하지 않고 처리 실패로 식별해야 한다. @@ -387,7 +375,11 @@ TUI 테스트에서 앞뒤에 공백이 있는 입력을 제출하고 제출 입 ## 11. 검증 계획 -Python 3.11 이상 환경에서 애플리케이션을 실행하고 대화 입력과 종료 동작을 검증한다. 정상 입력에서는 앞뒤 공백이 제거된 사용자 메시지와 고정 응답이 입력 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 세션 내 메시지와 내부 누적 상태가 사용자 메시지와 응답의 쌍으로 유지되는지 확인한다. 공백 또는 빈 입력에서는 응답 선택, 메시지 누적, 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택은 사전에 정의된 다섯 개 문구에서 표준 난수 선택으로 수행되는지 확인하며, 선택된 응답이 에이전트 역할과 구분되어 표시되는지 검증한다. 입력창 초기화는 유효 입력과 무효 입력 모두에서 제출 직후 수행되는지 확인한다. Escape와 Ctrl+Q 입력은 애플리케이션 종료를 요청하고 종료 전에 추가 메시지나 응답을 생성하지 않는지 확인한다. 기존 패키지 설치와 두 실행 진입점의 검증을 통과한 뒤 대화 기능 회귀 검증을 수행하며, 외부 API나 영속 저장소 없이 저장소의 자동화 테스트로 결과를 판정한다. +Python 3.11 이상 환경에서 애플리케이션을 실행하여 대화 입력과 종료 동작을 검증한다. 정상 입력에서는 앞뒤 공백이 제거된 사용자 메시지와 고정 응답이 제출 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 세션 내 메시지가 사용자 메시지와 응답의 인접한 쌍으로 누적되는지 확인한다. 빈 입력이나 공백만 포함한 입력에서는 응답 선택, 메시지 누적 및 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택이 정본으로 정의된 다섯 개 문구 중 하나를 표준 난수 방식으로 결정하는지와 선택 결과가 에이전트 메시지로 표시되는지 확인한다. 사용자와 에이전트 메시지의 라벨과 구조적 스타일이 역할에 맞는지 검증한다. Escape와 Ctrl+Q 입력은 애플리케이션 종료를 요청하고 종료 전에 새 메시지나 응답을 생성하지 않는지 확인한다. 프로젝트 설치 및 두 실행 진입점의 검증을 선행한 뒤 대화 기능 회귀 검증을 수행하며, 외부 API나 영속 저장소 없이 저장소의 자동화 테스트로 결과를 판정한다. + +테스트 추적성 계약: + +테스트 정의와 실행 증거는 별도 테스트 카탈로그 및 증거 산출물에서 관리한다. 대화 입력 정규화, 빈 입력 무시, 메시지와 응답의 순서 및 누적, 고정 응답 선택, 입력창 초기화, 역할별 표시와 종료 단축키에 대한 각 인수 기준의 검증 연결을 빠짐없이 기록한다. 실행 증거에는 요구사항 개정, 검증한 커밋, 실행 환경, 실행 시각과 결과를 포함하며, 실행하지 않은 검증은 성공으로 간주하지 않는다. ### 테스트 추적성 계약 @@ -407,7 +399,7 @@ Verifies: - REQ-002.05-AC01 - REQ-002.05-AC02 Test reference: tests/test_app.py 및 python -m unittest discover -s tests -v -Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스트를 사용하여 입력, 응답, 빈 입력, 스타일과 종료 동작을 자동 검증한다. +Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스트로 입력, 응답, 빈 입력, 역할별 표시, 입력창 초기화 및 종료 동작을 자동 검증한다. ``` 실행 증거: @@ -416,18 +408,18 @@ Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스 Test ID: TC-002-001 Requirement revision: REQ-002@0.1 Commit: d0ac7fc7bcfaf402bbda24776f051fa9992993e1 -Environment: Python 3.11 이상, 선언된 Textual 런타임 의존성이 설치된 환경 +Environment: Python 3.11 이상 및 선언된 Textual 런타임 의존성이 설치된 환경 Result: 미실행 Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ``` ## 12. 추적성 -근거는 원본 이슈의 요구사항 재작업 요청, 기존 프로젝트 스캐폴드 요구사항 문서, README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하며, 그 선행 요구사항의 의미나 실행 계약을 변경하지 않는다. 사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 패키징 메타데이터와 실행 진입점은 선행 문서에서 추적하고 이 문서에서는 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 응답 목록, 역할별 표시 구조와 종료 바인딩 및 관련 테스트가 각 동작의 근거와 검증 지점이다. +근거는 원본 Gitea 이슈 #8인 「요구사항명세서의 재작업」, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소 README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 원본 이슈 #8에서 요구한 대화 기능 분리의 결과로 작성되며, 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하되 그 의미와 실행 계약을 변경하지 않는다. 사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서만 추적한다. 패키징 메타데이터와 실행 진입점은 선행 프로젝트 스캐폴드 문서에서 추적하며 이 문서에서는 상세 규칙과 수용 기준을 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 고정 응답 목록, 역할별 표시 구조, 종료 바인딩과 관련 테스트는 각 동작의 근거 및 검증 지점이다. ## 13. 확정된 결정 -기존 구현과 테스트가 정의한 대화 동작을 별도 요구사항으로 분리하여 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 아무 대화 항목도 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 사전 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. 사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 애플리케이션 종료 동작을 요청한다. 외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. +원본 이슈 #8의 분리 범위에 따라 기존 구현과 테스트가 정의한 대화 동작을 독립된 요구사항 문서로 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 대화 항목을 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 정본으로 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. 사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 애플리케이션 종료 동작을 요청한다. 프로젝트 스캐폴드의 승인 상태와 기존 승인 이력은 선행 문서에서 보존하며, 이 문서는 대화 동작의 의미와 검증 기준만 관리한다. 외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. ## 14. 미결 사항 @@ -435,4 +427,4 @@ Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ## 15. 승인 기록 -상태는 초안이다. 승인 주체는 아직 지정되지 않았으며, 승인 근거도 기록되지 않았다. 디스커버리 승인에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행해야 한다. +상태는 초안이다. 승인 주체는 아직 지정되지 않았으며 승인 근거도 기록되지 않았다. 원본 Gitea 이슈 #8의 디스커버리 결과에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행해야 한다. -- 2.54.0 From 7bfe2b62f4d0e4cd0ef86a04e7ca329a49d64f07 Mon Sep 17 00:00:00 2001 From: code-agent Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH 3/5] code-agent: rework issue 8 Review-ID: 39 Previous-SHA: 925c107f9acc4c73a03f2f0daac837716d420b8d Plan-SHA256: 7ceaf8e0c832478852e3fde7d13d060cbb688be09c1b131deb5ccc32c85ed2ff Bundle-SHA256: 29ce1ef1917864f79938459725201e6e74d67e21b1f817ac53d7b294eca8f1a2 --- docs/requirements/req-001_project-scaffold.md | 244 +++++++++++------- .../req-002_conversation-interaction.md | 193 +++++++------- 2 files changed, 247 insertions(+), 190 deletions(-) diff --git a/docs/requirements/req-001_project-scaffold.md b/docs/requirements/req-001_project-scaffold.md index df48721..e49c995 100644 --- a/docs/requirements/req-001_project-scaffold.md +++ b/docs/requirements/req-001_project-scaffold.md @@ -19,29 +19,29 @@ ## 1. 목적 -이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 지정된 콘솔 명령 또는 모듈 실행 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 별도 요구사항에서 관리하며 이 문서에서는 정본으로 정의하지 않는다. +이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 `chat-tui` 콘솔 명령 또는 `python -m chat_tui` 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 REQ-002에서 단일 정본으로 관리하며 이 문서에서는 정의하지 않는다. -기존 프로젝트 스캐폴드 요구사항의 정체성과 승인 이력은 유지한다. 기존 승인 상태와 승인 근거를 임의로 초안 상태로 되돌리거나 삭제하지 않으며, 이번 문서 정리는 프로젝트 스캐폴드와 실행 기반의 범위만 명확히 하는 변경으로 한정한다. +기존 REQ-001의 프로젝트 스캐폴드 정체성, 승인 상태, 승인 주체인 `spec-agent`, 승인 근거인 승인 댓글 923 및 디스커버리 승인 결과를 보존한다. 이번 정리는 승인 상태를 초안으로 되돌리거나 승인 근거를 삭제하지 않으며, 프로젝트 스캐폴드와 실행 기반의 범위만 명확히 하는 변경으로 한정한다. ## 2. 배경 -프로젝트는 소스 코드를 `src` 레이아웃 아래에 두고 `chat_tui` 패키지로 제공한다. 패키징은 setuptools 빌드 백엔드를 사용하며 Python 3.11 이상을 실행 환경으로 요구한다. 런타임에는 Textual 0.47 이상 1.0 미만을 사용하고, 테스트용 선택 의존성으로 pytest 8.0 이상을 제공한다. 패키지 버전은 현재 0.1.0으로 관리한다. +프로젝트는 소스 코드를 `src` 레이아웃 아래에 두고 `chat_tui` 패키지로 제공한다. 패키징은 setuptools 빌드 백엔드를 사용하며 Python 3.11 이상을 실행 환경으로 요구한다. 런타임에는 Textual 0.47 이상 1.0 미만을 사용하고, 테스트용 선택 의존성으로 pytest 8.0 이상을 제공한다. 패키지 버전은 현재 `0.1.0`으로 관리한다. -패키지 설치와 실행 진입점은 대화 기능과 독립적으로 검증할 수 있는 프로젝트 기반 계약이다. 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 원본 이슈인 Gitea 이슈 #8의 재작업 범위에 따라 별도 대화 요구사항 문서에서 추적한다. +패키지 설치와 실행 진입점은 대화 기능과 독립적으로 검증할 수 있는 프로젝트 기반 계약이다. 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 원본 Gitea 이슈 #8의 재작업 범위에 따라 REQ-002에서 추적한다. REQ-002는 REQ-001의 실행 기반을 의존 대상으로 사용하지만, 패키징과 실행 진입점의 상세 계약을 중복 정의하지 않는다. ## 3. 범위 이 문서는 `src/chat_tui` Python 패키지의 기본 구조, 패키지 버전 공개, `pyproject.toml`의 빌드 시스템과 프로젝트 메타데이터, Python 및 런타임 의존성, 테스트 선택 의존성, `chat-tui` 콘솔 스크립트와 `python -m chat_tui` 모듈 실행 진입점을 포함한다. 소스 디렉터리를 패키지 탐색 대상으로 사용하는 설치 구조도 포함한다. -대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 역할별 대화 표시, 빈 입력 처리, 입력창 초기화와 종료 단축키의 상세 동작 및 수용 기준은 포함하지 않는다. 해당 내용은 별도 대화 상호작용 요구사항에서 단일 정본으로 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경 변경도 포함하지 않는다. +대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 역할별 대화 표시, 빈 입력 처리, 입력창 초기화와 종료 단축키의 상세 동작 및 수용 기준은 포함하지 않는다. 해당 내용은 REQ-002에서 단일 정본으로 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경 변경도 포함하지 않는다. ### 포함 -Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구조, setuptools 패키징 설정, 런타임 의존성, 테스트 선택 의존성, 콘솔 스크립트 진입점과 python -m 실행 진입점을 다룬다. +Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 src 기반 프로젝트 구조, setuptools 패키징 설정, 프로젝트 메타데이터, 런타임 및 선택적 테스트 의존성, chat-tui 콘솔 스크립트와 python -m chat_tui 실행 진입점을 포함한다. 기존 REQ-001의 승인 상태와 승인 주체 spec-agent, 승인 근거 승인 댓글 923 및 디스커버리 승인 결과를 보존한다. ### 제외 -사용자 입력 정규화, 대화 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용 동작은 다루지 않는다. 외부 API 연동, 영속성, 배포 환경 변경과 새 의존성 추가도 포함하지 않는다. +대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용의 상세 동작과 수용 기준은 별도 REQ-002에서 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 및 실행 환경 변경도 제외한다. ## 4. 용어와 기준 @@ -50,12 +50,13 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 - 프로젝트 이름은 `gitea-agent-testbed`이고 Python 패키지 이름은 `chat_tui`이다. - 소스 루트는 `src`이며 패키지 탐색 설정은 해당 루트를 기준으로 한다. - 패키지 초기화 모듈은 패키지 버전 `0.1.0`을 공개한다. -- 모듈 실행 진입점은 애플리케이션 모듈의 공개 실행 함수를 호출한다. +- 모듈 실행 진입점은 애플리케이션 모듈의 공개 실행 함수인 `main`을 호출한다. - 콘솔 스크립트 진입점은 `chat_tui.app:main`으로 연결한다. - 빌드 백엔드는 setuptools를 사용하고 빌드 요구 버전은 68 이상이다. - 테스트 설정은 `src`를 Python 경로에 포함하고 `tests` 디렉터리를 검색 대상으로 한다. - 프로젝트 스캐폴드 설명은 실제 패키지 구조와 패키징 설정에 부합해야 한다. -- 대화 상호작용의 의미와 세부 검증 기준은 이 문서가 아니라 분리된 대화 요구사항을 기준으로 한다. +- 대화 상호작용의 의미와 세부 검증 기준은 REQ-002를 기준으로 하며 이 문서의 기준과 중복하지 않는다. +- 기존 REQ-001의 승인 상태와 승인 이력은 승인된 프로젝트 스캐폴드 범위의 기록으로 보존한다. ## 5. 요구사항 @@ -70,83 +71,82 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 - 패키지 버전은 초기 스캐폴드 기준인 `0.1.0`을 일관되게 노출해야 한다. - 패키징 및 실행 진입점 검증은 대화 기능의 상세 동작과 독립적으로 수행할 수 있어야 한다. -**Python 패키지 구조와 메타데이터** +프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 3.11 이상 실행 조건과 Textual 0.47 이상 1.0 미만의 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. -프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전, 설명, Python 3.11 이상 실행 조건과 Textual 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있어야 한다. - -영향 범위는 Python 패키지 설치와 import 경계, 개발자와 패키지 설치 도구 및 실행 진입점에 한정된다. 영속성 변경과 마이그레이션은 없으며, Python 3.11 이상과 기존 패키지 이름을 유지한다. setuptools 기반 editable 설치가 가능해야 한다. - -**모듈 실행 진입점** - -프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수를 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. - -영향 범위는 모듈 실행 계약과 Python 모듈 실행 환경에 한정된다. 영속성 변경과 마이그레이션은 없으며, 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다. - -**콘솔 스크립트 실행 진입점** - -패키징 설정은 `chat-tui` 콘솔 명령을 애플리케이션 모듈의 공개 실행 함수에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 한다. - -영향 범위는 설치 후 제공되는 콘솔 명령과 최종 사용자 및 운영 스크립트에 한정된다. 영속성 변경과 마이그레이션은 없으며, 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 패키지 설치 시 console script가 생성되어야 한다. - -대화 입력, 응답, 메시지 표시와 종료 동작의 상세 요구사항 및 수용 기준은 이 문서에 중복해서 정의하지 않고 분리된 대화 요구사항에서 관리한다. - -### REQ-001.01 — Python 패키지 구조와 메타데이터를 제공한다 - -프로젝트는 Python 3.11 이상에서 설치 및 실행 가능한 표준 Python 패키지 구조를 제공해야 한다. 소스 루트는 `src`이며 `src/chat_tui` 패키지를 배포 대상으로 포함해야 한다. setuptools 빌드 백엔드와 소스 디렉터리 패키지 검색 설정을 사용하고, 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 최소 버전 및 Textual 0.47 이상 1.0 미만의 런타임 의존성을 패키징 메타데이터에 선언해야 한다. 테스트용 pytest 8.0 이상 의존성은 선택적으로 설치할 수 있어야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. - -**영향 범위** - -인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구와 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상, 프로젝트 이름, 패키지 이름과 버전 계약을 유지한다. 배포 전제 조건: setuptools 기반 설치와 `src` 패키지 탐색이 가능해야 한다. - -### REQ-001.02 — 모듈 실행 진입점을 제공한다 - -프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 진입점은 애플리케이션의 공개 실행 함수인 `main`을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. 실행 진입점은 설치된 패키지와 선언된 런타임 환경에서 동일한 애플리케이션 시작 흐름으로 연결되어야 한다. - -**영향 범위** - -인터페이스: `python -m chat_tui` 실행 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자와 운영자가 사용하는 Python 모듈 실행 환경. 마이그레이션: 필요 없음. 호환성: 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다. - -### REQ-001.03 — 콘솔 스크립트 실행 진입점을 제공한다 +프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수인 `main`을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. 패키징 설정은 `chat-tui` 콘솔 명령을 `chat_tui.app:main`에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 하며, 콘솔 명령과 모듈 실행 명령은 동일한 애플리케이션 시작 동작을 호출해야 한다. +대화 입력, 응답, 메시지 표시와 종료 동작의 상세 요구사항 및 수용 기준은 REQ-002에서 관리한다. 이 문서에 이를 중복 기록하지 않으며, REQ-001의 승인 상태와 기존 승인 이력은 변경하지 않는다. + +### REQ-001.01 — Python 패키지 구조와 메타데이터를 제공한다 + +프로젝트는 Python 3.11 이상에서 설치 및 실행 가능한 표준 Python 패키지 구조를 제공해야 한다. 소스 루트는 src이며 src/chat_tui 패키지를 배포 대상으로 포함해야 한다. setuptools 빌드 백엔드와 소스 디렉터리 패키지 검색 설정을 사용하고, 프로젝트 이름, 버전 0.1.0, 설명, README 참조, Python 최소 버전 및 Textual 0.47 이상 1.0 미만의 런타임 의존성을 패키징 메타데이터에 선언해야 한다. 테스트용 pytest 8.0 이상 의존성은 선택적으로 설치할 수 있어야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. + **영향 범위** -인터페이스: 설치 후 제공되는 `chat-tui` 콘솔 명령에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 최종 사용자와 운영 스크립트. 마이그레이션: 필요 없음. 호환성: 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지 설치 시 console script가 생성되어야 한다. +인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구와 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상, 프로젝트 이름, 패키지 이름과 버전 계약을 유지한다. 배포 전제 조건: setuptools 기반 설치와 src 패키지 탐색이 가능해야 한다. + +### REQ-001.02 — 모듈 실행 진입점을 제공한다 + +프로젝트는 python -m chat_tui 명령으로 실행할 수 있어야 한다. 모듈 진입점은 애플리케이션의 공개 실행 함수인 main을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. 실행 진입점은 설치된 패키지와 선언된 런타임 환경에서 동일한 애플리케이션 시작 흐름으로 연결되어야 한다. + +**영향 범위** + +인터페이스: python -m chat_tui 실행 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자와 운영자가 사용하는 Python 모듈 실행 환경. 마이그레이션: 필요 없음. 호환성: 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다. + +### REQ-001.03 — 콘솔 스크립트 실행 진입점을 제공한다 + +패키징 설정은 chat-tui 콘솔 명령을 chat_tui.app:main에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 하며, 콘솔 명령과 모듈 실행 명령은 동일한 애플리케이션 시작 동작을 호출해야 한다. + +**영향 범위** + +인터페이스: 설치 후 제공되는 chat-tui 콘솔 명령에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 최종 사용자와 운영 스크립트. 마이그레이션: 필요 없음. 호환성: 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지 설치 시 console script가 생성되어야 한다. + +### REQ-001.04 — 기존 승인 상태와 승인 근거를 보존한다 + +프로젝트 스캐affold 요구사항 문서는 기존 요구사항의 정체성과 승인 이력을 유지해야 한다. 기존 승인 상태는 approved로 보존하고, 승인 주체는 spec-agent로 명시하며, 승인 근거는 승인 댓글 923 및 디스커버리 승인 결과로 구조화하여 기록해야 한다. 문서 분리와 범위 정리만으로 승인 상태를 초안으로 되돌리거나 승인 근거를 삭제하거나 일반적인 서술로 대체해서는 안 된다. 실행되지 않은 검증은 특정 커밋의 실행 증거로 제시하지 않고 미기록 상태로 명확히 표시해야 한다. + +**영향 범위** + +인터페이스: 요구사항 문서의 승인 기록과 검증 추적성에 영향을 준다. 영속성: 문서 이력과 승인 메타데이터를 보존한다. 후속 사용 주체: 요구사항 검토자, 구현자와 승인 담당자. 마이그레이션: 기존 승인 기록을 삭제하지 않고 보존해야 한다. 호환성: 승인된 프로젝트 스캐폴드의 의미와 이력을 유지한다. 배포 전제 조건: 검증 증거가 실제 실행 상태와 일치해야 한다. ## 6. 제약과 불변조건 - 프로젝트는 Python 3.11 이상에서 실행되어야 한다. -- 패키지 구성은 `src` 기반 레이아웃을 유지하고 애플리케이션 패키지와 테스트 패키지의 책임을 분리해야 한다. -- 런타임 의존성은 호환되는 Textual 범위에서 관리하고 테스트 의존성은 선택적 설치 항목으로 제공해야 한다. -- 패키징 메타데이터, 공개 버전, 설명 및 지원 Python 버전은 서로 일관되어야 한다. -- 콘솔 실행 진입점과 모듈 실행 진입점은 동일한 애플리케이션 시작 함수를 호출해야 한다. -- 이 문서는 프로젝트 구조, 패키징 및 실행 진입점만 정본으로 관리하며 대화 상호작용의 상세 규칙과 인수 기준은 별도 요구사항 문서에서 관리한다. -- 외부 API, LLM, 데이터베이스, 영속 저장소 또는 추가 배포 환경을 도입하지 않는다. -- 기존 프로젝트 구조와 실행 계약을 사용하는 호출자는 별도 변환 없이 계속 사용할 수 있어야 한다. +- 패키지 구성은 `src` 기반 레이아웃을 유지하고 `src/chat_tui`를 배포 대상으로 포함해야 한다. +- 빌드 백엔드는 setuptools를 사용하며, 런타임 의존성은 Textual 0.47 이상 1.0 미만 범위로 관리해야 한다. +- 테스트 의존성은 제품 런타임 의존성과 분리된 선택 항목으로 제공하며 pytest 8.0 이상을 지정해야 한다. +- 프로젝트 메타데이터의 이름, 버전, 설명, README 참조, Python 최소 버전, 의존성 및 패키지 검색 설정은 서로 일치해야 한다. +- 패키지 공개 버전과 패키징 메타데이터의 버전은 `0.1.0`으로 일치해야 한다. +- `chat-tui` 콘솔 진입점과 `python -m chat_tui` 모듈 진입점은 동일한 공개 애플리케이션 시작 함수를 호출해야 한다. +- 패키지를 import하는 것만으로 애플리케이션이 시작되어서는 안 된다. +- 이 문서는 프로젝트 구조, 패키징 및 실행 진입점만 정본으로 관리한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 대화 상호작용 요구사항에서만 정본으로 관리한다. +- 대화 상호작용 요구사항은 이 문서가 제공하는 설치 및 실행 기반에 의존하지만, 이 문서의 스캐폴드 계약을 변경하지 않는다. +- 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경을 추가하지 않는다. ## 7. 인수 기준 -- Python 3.11 이상 환경에서 프로젝트를 설치하면 `src` 아래의 패키지와 선언된 런타임 의존성이 정상적으로 구성되어야 한다. -- 패키징 설정에 프로젝트 이름, 버전, 설명, README 참조, Python 최소 버전, Textual 의존성 및 소스 디렉터리 검색 설정이 포함되어야 한다. -- 테스트 선택 의존성을 별도로 설치할 수 있고 저장소의 테스트를 검색하여 실행할 수 있어야 한다. -- 설치된 `chat-tui` 명령은 애플리케이션의 공개 시작 함수를 호출해야 한다. -- `python -m chat_tui` 실행도 동일한 공개 시작 함수를 통해 애플리케이션을 시작해야 한다. -- 패키지에서 조회되는 공개 버전과 패키징 메타데이터의 버전은 일치해야 한다. -- 모듈을 단순히 import하는 것만으로 애플리케이션이 시작되어서는 안 된다. -- 패키징 설정에 명시되지 않은 외부 연동이나 추가 실행 전제 조건이 없어야 한다. -- 대화 입력과 응답 동작의 기존 회귀 검증은 별도 요구사항 문서의 범위에서 계속 확인되어야 하며, 이 문서에서는 해당 기준을 반복하지 않는다. -- 검증은 지원되는 Python 환경에서 패키지 설치, 공개 버전 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행한다. +- Python 3.11 이상 환경에서 프로젝트를 설치하면 `src` 아래의 `chat_tui` 패키지가 정상적으로 검색되고 설치되어야 한다. +- 패키징 설정에는 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성 및 `src` 기반 패키지 검색 설정이 포함되어야 한다. +- 테스트 선택 의존성은 런타임 의존성과 별도로 설치할 수 있어야 하며 저장소 테스트를 검색하고 실행할 수 있어야 한다. +- 설치된 `chat-tui` 명령은 `chat_tui.app:main`에 연결되어 애플리케이션 시작 절차로 진입해야 한다. +- `python -m chat_tui` 실행은 콘솔 명령과 동일한 공개 시작 함수를 통해 애플리케이션을 시작해야 한다. +- `chat_tui`에서 조회되는 공개 버전과 패키징 메타데이터의 버전은 `0.1.0`으로 일치해야 한다. +- 패키지를 단순히 import하는 것만으로 TUI가 시작되어서는 안 된다. +- 설치 또는 실행에 필요한 메타데이터와 진입점이 누락되면 정상 동작으로 판정하지 않아야 한다. +- 프로젝트 스캐폴드 변경 후에도 대화 상호작용 요구사항에서 정본으로 관리하는 입력, 응답, 빈 입력, 입력창 초기화 및 종료 동작의 기존 회귀 검증이 유지되어야 한다. +- 검증은 패키지 설치, 메타데이터 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행하며 실행하지 않은 검증은 통과로 판정하지 않는다. ### REQ-001.01-AC01 — 패키징 메타데이터가 프로젝트 계약과 일치한다 **판정 기준** -프로젝트 이름, 버전, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성, pytest 선택 의존성 및 `src` 기반 패키지 검색 설정이 모두 선언되어 있으면 통과로 판정한다. +프로젝트 이름, 버전, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성, pytest 선택 의존성 및 src 기반 패키지 검색 설정이 모두 선언되어 있으면 통과로 판정한다. **검증** -`pyproject.toml`을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 설치를 수행하여 패키지와 선언된 의존성이 정상적으로 구성되는지 검증한다. +pyproject.toml을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 설치를 수행하여 패키지와 선언된 의존성이 정상적으로 구성되는지 검증한다. **검증 분류** @@ -160,11 +160,11 @@ Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 프로젝트 구 **판정 기준** -`chat_tui` 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되고 패키징 메타데이터의 `0.1.0`과 일치하면 통과로 판정한다. +chat_tui 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되고 패키징 메타데이터의 0.1.0과 일치하면 통과로 판정한다. **검증** -Python에서 `chat_tui.__version__`을 조회하고 프로젝트 메타데이터의 버전 선언과 비교한다. +Python에서 chat_tui.__version__을 조회하고 프로젝트 메타데이터의 버전 선언과 비교한다. **검증 분류** @@ -178,11 +178,11 @@ Python에서 `chat_tui.__version__`을 조회하고 프로젝트 메타데이터 **판정 기준** -설치된 패키지 환경에서 `python -m chat_tui`를 실행했을 때 공개 실행 함수를 통해 TUI가 시작되면 통과로 판정한다. +설치된 패키지 환경에서 python -m chat_tui를 실행했을 때 공개 실행 함수를 통해 TUI가 시작되면 통과로 판정한다. **검증** -모듈 진입점이 애플리케이션의 공개 실행 함수를 직접 실행 조건에서 호출하는지 확인하고, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다. +모듈 진입점이 애플리케이션의 공개 실행 함수를 실행 조건에서 호출하는지 확인하고, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다. **검증 분류** @@ -196,11 +196,11 @@ Python에서 `chat_tui.__version__`을 조회하고 프로젝트 메타데이터 **판정 기준** -설치가 완료된 환경에서 `chat-tui` 명령이 실행 경로에 생성되고 애플리케이션을 시작하면 통과로 판정한다. +설치가 완료된 환경에서 chat-tui 명령이 실행 경로에 생성되고 애플리케이션을 시작하면 통과로 판정한다. **검증** -패키지를 설치한 뒤 `chat-tui` 명령의 생성 여부와 연결된 실행 대상을 확인하고 명령을 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다. +패키지를 설치한 뒤 chat-tui 명령의 생성 여부와 연결된 실행 대상을 확인하고 명령을 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다. **검증 분류** @@ -210,43 +210,83 @@ Python에서 `chat_tui.__version__`을 조회하고 프로젝트 메타데이터 성공 시 콘솔 명령은 지정된 공개 실행 함수를 호출해야 한다. 명령 생성 과정에서 대화 상태나 사용자 입력이 변경되어서는 안 된다. 설치가 완료되지 않은 환경에서는 명령이 존재한다고 판정하지 않는다. +### REQ-001.04-AC01 — 기존 승인 기록을 구조적으로 보존한다 + +**판정 기준** + +승인 상태가 approved이고 승인 주체가 spec-agent이며 승인 근거가 승인 댓글 923 및 디스커버리 승인 결과로 명시되어 있으면 통과로 판정한다. + +**검증** + +요구사항 문서의 승인 기록을 검토하여 상태, 주체 및 근거가 기존 기록과 동일하게 보존되었는지 확인한다. + +**검증 분류** + +수준: integration; 백엔드: 요구사항 문서와 승인 이력; 케이스: unchanged-state + +**상태 불변조건** + +기존 승인 상태를 draft로 변경하거나 승인 주체와 근거를 삭제해서는 안 된다. 승인 기록은 프로젝트 스캐폴드 범위 변경과 독립적으로 보존되어야 한다. + +### REQ-001.04-AC02 — 실행되지 않은 검증을 실행 증거로 가장하지 않는다 + +**판정 기준** + +검증을 실제로 실행하지 않은 경우 특정 커밋, 실행 시각 또는 성공 결과를 실행 증거로 기록하지 않고 미기록 또는 미실행 상태로 명확히 표시하면 통과로 판정한다. + +**검증** + +요구사항 문서의 테스트 추적성 계약을 검토하여 실행되지 않은 검증에 임의의 커밋 해시나 성공 결과가 연결되지 않았는지 확인한다. + +**검증 분류** + +수준: integration; 백엔드: 요구사항 추적성 기록; 케이스: unchanged-state + +**상태 불변조건** + +실행 증거는 실제 검증 결과와 일치해야 한다. 검증하지 않은 항목을 PASS로 기록하거나 현재 변경과 무관한 커밋을 실행 증거로 제시해서는 안 된다. + ## 8. 오류 및 충돌 계약 -- 패키지 설치에 필요한 메타데이터가 누락되거나 유효하지 않으면 설치를 성공으로 판정하지 않아야 하며 원인을 확인할 수 있는 오류를 반환해야 한다. -- 지원하지 않는 Python 버전에서는 설치 또는 실행을 정상 동작으로 간주하지 않는다. -- 콘솔 진입점이나 모듈 진입점이 애플리케이션 시작 함수를 찾지 못하면 실행은 실패해야 하며 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않아야 한다. -- 의존성 버전 제약을 만족하지 못하는 환경에서는 호환되지 않는 런타임으로 자동 대체하거나 외부 서비스를 호출하지 않는다. -- 테스트 의존성 설치 실패는 제품 런타임 의존성의 정상 설치 실패와 구별되어야 한다. -- 설치 또는 실행 실패 시 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다. -- 패키징 변경으로 별도 대화 요구사항에서 보장하는 동작이나 종료 동작이 달라지면 스캐폴드 인수에 실패한 것으로 판정한다. -- 이 문서와 별도 대화 요구사항 사이에 계약 충돌이 발생하면 프로젝트 실행 기반은 이 문서가, 대화 상호작용은 별도 문서가 정본이며 어느 한쪽의 범위를 임의로 확장하지 않는다. +- 필수 패키징 메타데이터가 누락되거나 유효하지 않으면 설치를 성공으로 판정하지 않아야 하며 원인을 확인할 수 있는 오류를 반환해야 한다. +- 지원하지 않는 Python 버전이나 호환되지 않는 의존성 환경에서는 설치 또는 실행을 정상 동작으로 간주하지 않는다. +- 콘솔 진입점이나 모듈 진입점이 공개 시작 함수를 찾지 못하면 실행은 실패해야 하며 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않아야 한다. +- 패키징 설정에 선언되지 않은 외부 연동이나 실행 전제를 자동으로 추가하지 않는다. +- 테스트 의존성 설치 실패는 제품 런타임 의존성의 설치 실패와 구별되어야 한다. +- 설치 또는 실행 실패로 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다. +- 패키징 또는 실행 진입점 변경으로 대화 상호작용 요구사항의 정본 동작이 달라지면 프로젝트 스캐폴드 인수를 충족한 것으로 판정하지 않는다. +- 프로젝트 스캐폴드와 대화 상호작용 사이에 충돌이 발생하면 프로젝트 구조, 패키징 및 실행 기반은 이 문서가 정본이며, 입력·응답·표시·입력창·종료 동작은 대화 상호작용 요구사항이 정본이다. +- 어느 문서도 다른 문서의 범위를 임의로 확장하거나 동일한 기능 규칙과 인수 기준을 중복 정의하지 않는다. ## 9. 데이터 및 인터페이스 계약 - 프로젝트 패키지의 정본 위치는 `src/chat_tui`이며 패키지 검색 기준은 `src`이다. -- 프로젝트 메타데이터는 프로젝트 이름, 버전, 설명, README 위치, 지원 Python 버전 및 런타임 의존성을 제공해야 한다. +- 프로젝트 메타데이터는 프로젝트 이름, 버전, 설명, README 위치, 지원 Python 버전 및 Textual 런타임 의존성을 제공해야 한다. - 테스트 의존성은 별도 선택적 의존성 그룹으로 선언되어야 한다. -- 콘솔 인터페이스는 `chat-tui` 명령에서 애플리케이션의 `main` 실행 함수를 호출해야 한다. +- 콘솔 인터페이스는 `chat-tui` 명령에서 `chat_tui.app:main`을 호출해야 한다. - 모듈 인터페이스는 `python -m chat_tui` 실행 시 패키지의 모듈 진입점에서 동일한 `main` 함수를 호출해야 한다. -- 패키지 공개 버전은 프로젝트 메타데이터의 버전과 일치해야 한다. -- 실행 진입점은 외부 입력을 별도 프로토콜이나 네트워크 인터페이스로 변환하지 않고 로컬 Textual 애플리케이션을 시작한다. +- 패키지 공개 버전은 프로젝트 메타데이터의 `0.1.0`과 일치해야 한다. +- 실행 진입점은 외부 프로토콜이나 네트워크 인터페이스로 변환하지 않고 로컬 Textual 애플리케이션을 시작해야 한다. - 테스트 인터페이스는 표준 unittest 검색 방식으로 저장소 테스트를 실행할 수 있어야 하며 별도의 서비스나 데이터 저장소를 요구하지 않는다. -- 대화 메시지와 사용자 입력의 데이터 및 화면 인터페이스 계약은 별도 대화 요구사항 문서에서 정의하며 이 문서에서는 재정의하지 않는다. +- 대화 메시지, 사용자 입력, 고정 응답 목록, 역할별 표시, 입력창 상태 및 종료 키의 상세 데이터와 인터페이스 계약은 대화 상호작용 요구사항에서 정의하며 이 문서에서는 재정의하지 않는다. ## 10. 하위 호환성 - 기존의 `chat-tui` 콘솔 실행 방식은 유지되어야 한다. - 기존의 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다. -- Python 3.11 이상 지원 조건과 현재 패키지 이름 및 공개 버전 계약은 유지되어야 한다. -- `src` 기반 패키지 검색과 애플리케이션 패키지의 공개 버전 노출 방식은 유지되어야 한다. +- Python 3.11 이상 지원 조건, 프로젝트 이름, 패키지 이름 `chat_tui` 및 공개 버전 `0.1.0` 계약은 유지되어야 한다. +- `src` 기반 패키지 검색과 패키지 공개 버전 노출 방식은 유지되어야 한다. - 기존 README에 설명된 설치 및 실행 명령은 스캐폴드 정리 이후에도 유효해야 한다. -- 대화 입력, 응답 표시, 빈 입력 처리, 입력창 초기화 및 종료와 같은 상호작용 동작은 별도 대화 요구사항 문서의 정본으로 유지하며 이 문서에서 상세히 반복하지 않는다. -- 새 외부 의존성, 외부 연동, 배포 방식 또는 실행 환경을 추가하지 않는다. -- 스캐폴드 문서의 변경은 프로젝트 구조, 패키징 및 실행 진입점의 범위를 넘어 대화 동작의 의미를 변경해서는 안 된다. +- 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 대화 상호작용 요구사항의 정본으로 유지하며 이 문서에서 상세히 반복하지 않는다. +- 새 외부 의존성, 외부 연동, 영속성, 배포 방식 또는 실행 환경을 추가하지 않는다. +- 스캐폴드 문서의 변경은 프로젝트 구조, 패키징 및 실행 진입점의 범위를 넘어 대화 상호작용의 의미를 변경해서는 안 된다. +- 대화 상호작용 요구사항은 이 문서의 설치 및 실행 계약을 선행 조건으로 사용하되, 해당 계약을 별도로 복제하거나 변경해서는 안 된다. ## 11. 검증 계획 -Python 3.11 이상 환경에서 패키지 설치와 메타데이터 정합성을 검증한다. 소스 디렉터리 기반 패키지 검색, 런타임 의존성, 선택적 테스트 의존성, 공개 버전이 선언된 계약과 일치하는지 확인한다. 모듈 실행과 콘솔 실행이 동일한 애플리케이션 시작 함수를 호출하는지 확인하고, 기존 저장소 테스트를 실행하여 대화 입력, 응답 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작이 변경되지 않았는지 회귀 검증한다. 테스트 실행 결과와 설치 검증 결과는 실행한 커밋, 환경, 실행 시각 및 성공 여부를 별도 증거로 기록하며, 실행하지 않은 검증을 통과로 간주하지 않는다. +Python 3.11 이상 환경에서 패키지 설치와 메타데이터 정합성을 검증한다. 소스 디렉터리 기반 패키지 검색, 런타임 의존성, 선택적 테스트 의존성 및 공개 버전이 선언된 계약과 일치하는지 확인한다. 모듈 실행과 콘솔 실행이 동일한 애플리케이션 시작 함수를 호출하는지 확인하고, 기존 저장소 테스트를 실행하여 대화 동작이 변경되지 않았는지 회귀 검증한다. 실행하지 않은 검증은 통과로 간주하지 않는다. + +검증 정의는 저장소의 패키징 설정 검토와 표준 unittest 검색을 대상으로 한다. 패키징 메타데이터, 공개 버전 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 함께 확인한다. 현재 문서 작성 시점에는 검증을 실행하지 않았으므로 특정 커밋에 결합된 실행 증거와 성공 결과를 기록하지 않는다. ### 테스트 추적성 계약 @@ -259,8 +299,10 @@ Verifies: - REQ-001.01-AC02 - REQ-001.02-AC01 - REQ-001.03-AC01 +- REQ-001.04-AC01 +- REQ-001.04-AC02 Test reference: pyproject.toml 설정 검토 및 python -m unittest discover -s tests -v -Automated: 기존 패키징 및 실행 진입점 검증 테스트를 사용한다. +Automated: 기존 패키징 및 실행 진입점 검증 테스트와 대화 동작 회귀 테스트를 사용한다. ``` 실행 증거: @@ -268,19 +310,23 @@ Automated: 기존 패키징 및 실행 진입점 검증 테스트를 사용한 ```text Test ID: TC-001-001 Requirement revision: REQ-001@0.1 -Commit: d0ac7fc7bcfaf402bbda24776f051fa9992993e1 -Environment: Python 3.11 이상, setuptools 기반 설치 환경 +Commit: 검증 커밋 미기록 +Environment: Python 3.11 이상 및 setuptools 기반 설치 환경 Result: 미실행 -Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 +Executed at: 검증 실행 시각 미기록 ``` ## 12. 추적성 -근거는 Gitea 이슈 #8의 요구사항 재작업 요청과 저장소의 프로젝트 메타데이터, 패키지 구조, 실행 진입점 선언 및 기존 테스트다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 실행과 콘솔 실행 진입점만 추적한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 분리된 대화 상호작용 문서에서만 추적한다. 두 문서는 실행 기반과 대화 동작의 선행 관계만 공유하며 동일한 기능 규칙이나 수용 기준을 반복하지 않는다. 기존 승인 이력은 승인 기록에 보존한다. +근거는 원본 Gitea 이슈의 요구사항 재작업 요청과 저장소의 프로젝트 메타데이터, 패키지 구조, 실행 진입점 선언 및 기존 테스트다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 실행과 콘솔 실행 진입점만 추적한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 분리된 대화 상호작용 문서에서만 추적한다. + +두 문서는 실행 기반과 대화 동작의 선행 관계만 공유하며 동일한 기능 규칙이나 수용 기준을 반복하지 않는다. 프로젝트 스캐폴드의 승인 이력은 승인 기록에 보존하고, 대화 상호작용의 근거와 검증 연결은 분리된 문서에서 관리한다. ## 13. 확정된 결정 -기존 프로젝트 스캐폴드의 의미와 승인 이력을 보존하고, 혼재되어 있던 대화 상호작용 요구사항과 수용 기준은 별도 문서로 분리한다. 이 문서의 정본 범위는 패키지 구조, 패키징 메타데이터와 두 실행 진입점으로 한정한다. 애플리케이션 코드, 테스트 동작, 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다. +기존 프로젝트 스캐폴드의 의미와 승인 이력을 보존하고, 혼재되어 있던 대화 상호작용 요구사항과 수용 기준은 별도 문서로 분리한다. 이 문서의 정본 범위는 패키지 구조, 패키징 메타데이터와 두 실행 진입점으로 한정한다. + +애플리케이션 코드, 테스트 동작, 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다. 대화 동작의 상세 규칙과 수용 기준은 분리된 문서에서 단일 정본으로 관리한다. ## 14. 미결 사항 @@ -288,4 +334,8 @@ Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ## 15. 승인 기록 -상태는 승인이다. 기존 승인 주체인 spec-agent와 기존 승인 근거를 보존하며, 이번 문서 정리는 승인 상태를 초안으로 되돌리지 않는다. 승인된 프로젝트 스캐폴드 범위와 기존 승인 이력은 유지하고, 대화 상호작용을 별도 요구사항 문서로 분리한 변경만 추적한다. +상태: approved +승인 주체: spec-agent +승인 근거: 승인 댓글 923 및 디스커버리 승인 결과 + +기존 프로젝트 스캐폴드의 승인 상태와 승인 근거는 유지한다. 이번 문서 정리는 승인 상태를 초안으로 되돌리지 않으며, 승인된 프로젝트 스캐폴드 범위와 기존 승인 이력을 보존한 채 대화 상호작용을 별도 요구사항 문서로 분리한 변경만 추적한다. diff --git a/docs/requirements/req-002_conversation-interaction.md b/docs/requirements/req-002_conversation-interaction.md index 0d95844..73ccac4 100644 --- a/docs/requirements/req-002_conversation-interaction.md +++ b/docs/requirements/req-002_conversation-interaction.md @@ -22,31 +22,35 @@ ## 1. 목적 -이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 제출한 입력을 정규화하고, 유효한 메시지와 고정 응답을 세션 내 대화 영역에 순서대로 누적 표시하는 동작을 정의한다. 공백만 포함하거나 비어 있는 입력은 대화 상태를 변경하지 않고 무시하며, 모든 제출 후 입력창을 비운다. 사용자와 에이전트의 역할을 라벨과 구조적 스타일로 구분하고, Escape 및 Ctrl+Q를 통한 종료 요청을 보장한다. 이 대화 동작은 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 원본 Gitea 이슈 #8의 재작업 범위에서 관리한다. +이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 제출한 입력을 정규화하고, 유효한 메시지와 고정 응답을 세션 내 대화 영역에 제출 순서대로 누적 표시하는 동작을 정의한다. 입력의 양끝 공백은 제거하며, 비어 있거나 공백만 포함한 입력은 대화 상태와 응답 선택을 변경하지 않고 무시한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비운다. + +사용자 메시지와 에이전트 응답은 각각 명시적인 역할, 라벨 및 구조적 스타일로 구분한다. 유효한 입력마다 사전에 정의된 다섯 개의 고정 응답 중 하나를 표준 난수 방식으로 선택하고, 사용자 메시지 바로 뒤에 에이전트 응답을 표시한다. Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청해야 한다. 이 대화 동작은 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 원본 Gitea 이슈 #8의 재작업 범위에서 관리한다. ## 2. 배경 -애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 문자열을 작성하고 Enter로 제출하며, 시스템은 입력 양끝의 공백을 제거한 뒤 유효성을 판단한다. 유효한 입력에는 사전에 정의된 다섯 개의 고정 응답 중 하나를 표준 난수 선택 방식으로 연결하고, 사용자 메시지와 에이전트 응답을 제출 순서대로 표시한다. +애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 문자열을 작성하고 Enter로 제출하며, 시스템은 입력 양끝의 공백을 제거한 뒤 정규화 결과의 유효성을 판단한다. 유효한 입력에는 사전에 정의된 다섯 개의 고정 응답 중 하나를 연결하고, 사용자 메시지와 에이전트 응답을 제출 순서대로 표시한다. -메시지와 응답은 실행 중인 세션의 메모리 상태로만 관리하며 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 사용하지 않는다. 프로젝트 설치와 실행 진입점은 선행 스캐폴드 요구사항의 계약을 따르고, 대화 상호작용의 상세 규칙과 수용 기준은 이 문서에서 단일 정본으로 관리한다. 원본 근거는 Gitea 이슈 #8이다. +메시지와 응답은 실행 중인 세션의 메모리 상태로만 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소는 사용하지 않는다. 프로젝트 설치와 실행 진입점은 REQ-001의 계약을 따르며, 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 이 문서에서 단일 정본으로 관리한다. 근거는 원본 Gitea 이슈 #8이다. ## 3. 범위 -포함 범위는 입력 양끝의 공백 제거와 유효 입력 판정, 유효한 사용자 메시지와 고정 응답의 세션 내 누적, 표준 난수 방식의 응답 선택, 사용자 메시지 뒤에 응답을 배치하는 순서 보장, 사용자와 에이전트의 라벨 및 구조적 스타일 구분, 빈 입력과 공백 입력의 무시, 제출 후 입력창 초기화, Escape 및 Ctrl+Q 종료 요청이다. 선행 프로젝트 스캐폴드 요구사항과의 의존 관계 및 Gitea 이슈 #8 추적성도 포함한다. +포함 범위는 입력 양끝의 공백 제거와 유효 입력 판정, 유효한 사용자 메시지와 고정 응답의 세션 내 누적, 표준 난수 방식의 응답 선택, 사용자 메시지 뒤에 응답을 배치하는 순서 보장, 사용자와 에이전트의 라벨 및 구조적 스타일 구분, 빈 입력과 공백 입력의 무시, 제출 후 입력창 초기화, Escape 및 Ctrl+Q 종료 요청이다. REQ-001과의 의존 관계 및 Gitea 이슈 #8 추적성도 포함한다. -프로젝트 패키징, 설치 설정, 실행 진입점 자체의 변경은 포함하지 않는다. 고정 응답 문구, 입력 처리 순서와 사용자 인터페이스 의미를 변경하지 않으며, 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 인증, 권한 관리, 다중 세션, 메시지 복원, 새 의존성, 배포 방식 또는 실행 환경의 추가도 포함하지 않는다. +사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 표시, 응답 선택 순서, 역할별 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작을 정본 범위로 관리한다. 프로젝트 패키징, 설치 설정 및 실행 진입점 자체의 변경은 포함하지 않는다. + +고정 응답 문구, 입력 처리 순서와 사용자 인터페이스의 의미는 변경하지 않는다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 인증, 권한 관리, 다중 세션, 메시지 복원, 새 의존성, 배포 방식 또는 실행 환경의 추가도 제외한다. ### 포함 -사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 세션 내 누적 및 표시, 응답 선택 순서, 사용자와 에이전트의 역할별 표시, 빈 입력 무시, 입력창 초기화, Escape와 Ctrl+Q 종료 동작 및 REQ-001 의존 관계와 원본 이슈 #8 추적성을 포함한다. +사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 세션 내 누적 및 표시, 표준 난수 방식의 응답 선택, 사용자와 에이전트의 역할별 표시, 빈 입력 무시, 제출 후 입력창 초기화, Escape와 Ctrl+Q 종료 요청 및 REQ-001 의존 관계와 Gitea 이슈 #8 추적성을 포함한다. ### 제외 -프로젝트 패키징, 설치 설정 및 실행 진입점의 변경, 외부 API·LLM·네트워크 서비스·데이터베이스·영속 저장소 연동, 사용자 인증과 다중 세션 관리, 새로운 의존성·배포 방식·실행 환경 추가는 포함하지 않는다. +프로젝트 패키징, 설치 설정 및 실행 진입점의 변경, 외부 API·LLM·네트워크 서비스·데이터베이스·영속 저장소 연동, 사용자 인증과 다중 세션 관리, 메시지 복원, 새로운 의존성·배포 방식·실행 환경 추가는 포함하지 않는다. ## 4. 용어와 기준 -입력은 사용자가 입력창에서 제출한 문자열이고, 정규화는 문자열 양끝의 공백을 제거하는 처리다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. +입력은 사용자가 입력창에서 제출한 문자열이고, 정규화는 문자열 양끝의 공백을 제거하는 처리다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. 문자열 내부의 공백은 제거하거나 변환하지 않는다. 유효한 제출은 정규화된 사용자 메시지와 고정 응답 목록에서 선택된 에이전트 응답으로 구성된다. 사용자 메시지는 사용자 역할과 사용자 라벨을 가지며, 응답은 에이전트 역할과 에이전트 라벨을 가진다. 각 역할의 표시는 서로 다른 구조적 스타일을 사용하고, 역할과 본문은 세션 메시지의 정본 상태로 함께 보존한다. @@ -58,40 +62,29 @@ - 지금 처리 중입니다. - 작업을 완료하였습니다. -응답 선택은 유효한 입력마다 이 목록 전체를 대상으로 표준 난수 선택을 한 번 수행한다. 선택된 응답은 해당 사용자 메시지 바로 뒤에 배치한다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며 종료 과정에서 외부 상태나 영속 데이터를 생성하지 않는다. +유효한 입력마다 목록 전체를 대상으로 표준 난수 선택을 한 번 수행한다. 선택된 응답은 해당 사용자 메시지 바로 뒤에 배치한다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며, 종료 과정에서 외부 상태나 영속 데이터를 생성하지 않는다. ## 5. 요구사항 -시스템은 다음 대화 상호작용을 제공해야 한다. +시스템은 입력 제출 시 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. 정규화 결과가 비어 있지 않을 때만 사용자 메시지를 세션 상태와 화면에 기록해야 하며, 빈 문자열이나 공백·탭·줄바꿈만 포함한 입력은 응답 선택과 메시지 추가 없이 무시해야 한다. -- 입력 제출 시 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. -- 정규화 결과가 비어 있지 않을 때만 사용자 메시지를 세션 상태와 화면에 기록해야 한다. -- 유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 방식으로 응답 하나를 선택해야 한다. -- 사용자 메시지는 사용자 역할과 사용자 라벨로 표시하고, 선택된 응답은 에이전트 역할과 에이전트 라벨로 표시해야 한다. -- 각 사용자 메시지는 대응하는 에이전트 응답보다 먼저 표시되어야 하며, 두 항목은 인접한 순서를 유지해야 한다. -- 여러 입력을 제출해도 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적해야 한다. -- 유효한 입력을 처리한 뒤 입력창은 빈 문자열로 초기화되어야 한다. -- 빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 입력은 응답 선택과 메시지 추가 없이 무시해야 한다. -- 무효 입력을 무시하더라도 입력창은 빈 문자열로 초기화되어야 한다. -- 역할에 따라 라벨과 구조적 스타일을 일관되게 적용해야 하며, 스타일만으로 역할을 판단하는 구조를 사용해서는 안 된다. -- Escape와 Ctrl+Q 입력은 동일한 애플리케이션 종료 동작을 요청해야 한다. -- 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 되며, 종료 시 새 대화 항목을 추가해서는 안 된다. -- 대화 처리는 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. -- 선행 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 해당 실행 환경에서 동작해야 한다. -- 기존 구현과 테스트가 보장하는 입력 정규화, 메시지 누적, 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작을 유지해야 한다. -- 이 대화 동작의 근거와 변경 추적 대상은 Gitea 이슈 #8로 명시해야 하며, 패키징과 실행 기반의 상세 계약은 선행 요구사항에서 중복 정의하지 않아야 한다. +유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 방식으로 응답 하나를 선택해야 한다. 사용자 메시지는 사용자 역할과 사용자 라벨로 표시하고, 선택된 응답은 에이전트 역할과 에이전트 라벨로 표시해야 한다. 사용자 메시지는 대응하는 에이전트 응답보다 먼저 표시되어야 하며 두 항목은 인접한 순서를 유지해야 한다. 여러 입력을 제출해도 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적해야 한다. + +유효하거나 무효인 입력 제출이 발생하면 입력창은 빈 문자열로 초기화되어야 한다. 역할별 라벨과 구조적 스타일은 메시지 역할에서 일관되게 파생해야 하며 스타일만으로 역할을 판단해서는 안 된다. Escape와 Ctrl+Q 입력은 동일한 애플리케이션 종료 동작을 요청해야 하고, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. + +대화 처리는 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 REQ-001이 제공하는 실행 환경에서 동작해야 하며, 이 문서의 상세 대화 규칙과 수용 기준은 프로젝트 스캐폴드 요구사항에서 중복 정의하지 않는다. ### REQ-002.01 — 입력 정규화와 유효 입력 판정 -사용자가 입력창에서 문자열을 제출하면 시스템은 문자열 양끝의 공백을 제거한 값을 정규화된 입력으로 사용해야 한다. 정규화 결과가 하나 이상의 문자를 포함하면 유효한 사용자 메시지로 처리하고, 빈 문자열이면 유효한 메시지로 처리하지 않아야 한다. 공백, 탭 또는 줄바꿈만 포함한 입력은 응답 선택이나 대화 항목 추가 없이 무시해야 한다. +사용자가 입력창에서 문자열을 제출하면 시스템은 문자열 양끝의 공백을 제거한 값을 정규화된 입력으로 사용해야 한다. 정규화 결과가 하나 이상의 문자를 포함하면 유효한 사용자 메시지로 처리하고, 결과가 빈 문자열이면 유효한 메시지로 처리하지 않아야 한다. 공백, 탭 또는 줄바꿈만 포함한 입력은 응답 선택이나 대화 항목 추가 없이 무시해야 한다. **영향 범위** -인터페이스: 입력 위젯의 제출 이벤트와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 검증하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 양끝 공백 제거와 빈 입력 무시 동작을 유지한다. 배포 전제 조건: REQ-001이 제공하는 Textual 실행 환경이 필요하다. +인터페이스: 입력 위젯의 제출 이벤트와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 검증하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 양끝 공백 제거와 빈 입력 무시 동작을 유지한다. 배포 전제 조건: 선행 프로젝트 스캐폴드가 제공하는 Textual 실행 환경이 필요하다. ### REQ-002.02 — 유효 메시지와 고정 응답을 순서대로 누적한다 -유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 사용자 역할로 먼저 대화 상태와 대화 영역에 추가해야 한다. 이어서 다음 다섯 개의 고정 응답 목록 전체를 표준 난수 선택 기능에 전달하여 응답 하나를 선택하고, 선택된 응답을 에이전트 역할로 사용자 메시지 바로 뒤에 추가해야 한다: 안녕하세요! 무엇을 도와드릴까요?, 그것은 제가 처리하기 불가능합니다., 맡겨만 주세요., 지금 처리 중입니다., 작업을 완료하였습니다. 여러 입력을 제출하면 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적해야 한다. +유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 사용자 역할로 먼저 대화 상태와 대화 영역에 추가해야 한다. 이어서 고정된 다섯 개 응답 목록 전체를 표준 난수 선택 기능에 전달하여 응답 하나를 선택하고, 선택된 응답을 에이전트 역할로 사용자 메시지 바로 뒤에 추가해야 한다. 고정 응답 목록은 안녕하세요! 무엇을 도와드릴까요?, 그것은 제가 처리하기 불가능합니다., 맡겨만 주세요., 지금 처리 중입니다., 작업을 완료하였습니다.로 구성한다. 여러 입력을 제출하면 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적해야 한다. **영향 범위** @@ -103,7 +96,7 @@ **영향 범위** -인터페이스: 입력 위젯의 값과 연속 입력 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 유효 입력과 무효 입력 제출 후 입력창을 비우는 기존 동작을 유지한다. 배포 전제 조건: Textual Input 위젯을 제출 이벤트에서 갱신할 수 있어야 한다. +인터페이스: 입력 위젯의 값과 연속 입력 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 유효 입력과 무효 입력 제출 후 입력창을 비우는 기존 동작을 유지한다. 배포 전제 조건: Textual 입력 위젯을 제출 이벤트에서 갱신할 수 있어야 한다. ### REQ-002.04 — 역할 기반 메시지 표시를 유지한다 @@ -115,41 +108,41 @@ ### REQ-002.05 — 종료 단축키로 애플리케이션 종료를 요청한다 -사용자가 Escape 또는 Ctrl+Q를 입력하면 시스템은 현재 Textual 애플리케이션의 종료 동작을 요청해야 한다. 두 단축키는 동일한 종료 경로를 사용해야 하며, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 이 요구사항은 원본 Gitea 이슈 #8의 대화 상호작용 재작업 범위를 추적한다. +사용자가 Escape 또는 Ctrl+Q를 입력하면 시스템은 현재 Textual 애플리케이션의 종료 동작을 요청해야 한다. 두 단축키는 동일한 종료 경로를 사용해야 하며, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 이 요구사항은 원본 Gitea 이슈 8의 대화 상호작용 재작업 범위를 추적한다. **영향 범위** -인터페이스: TUI 키 바인딩과 애플리케이션 생명 주기에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: REQ-001의 Textual 애플리케이션 실행 계약이 충족되어야 한다. +인터페이스: TUI 키 바인딩과 애플리케이션 생명 주기에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: 선행 프로젝트 스캐폴드의 Textual 애플리케이션 실행 계약이 충족되어야 한다. ## 6. 제약과 불변조건 -- 모든 입력은 제출 시점에 문자열 양끝의 공백을 제거한 값으로 정규화한다. -- 정규화 결과가 빈 문자열이면 응답 선택, 메시지 목록 변경, 화면 항목 추가를 수행하지 않는다. -- 유효한 입력은 세션 내 대화 상태에 사용자 메시지와 에이전트 응답을 순서대로 추가한다. -- 에이전트 응답은 사전에 정의된 다섯 개의 고정 응답 중 표준 난수 선택으로 하나를 결정한다. -- 화면에 표시되는 사용자 메시지와 에이전트 응답의 작성자 역할, 라벨, 스타일은 메시지 역할에서 일관되게 파생되어야 한다. -- 유효한 입력을 처리한 뒤 입력창은 항상 빈 값으로 초기화한다. -- 빈 입력 또는 공백만 포함한 입력을 처리해도 기존 대화 상태와 응답 선택 상태는 변경되지 않아야 한다. -- 대화 메시지는 현재 실행 세션에만 누적하며 외부 API, 데이터베이스 또는 영속 저장소를 사용하지 않는다. -- 입력 제출 순서와 메시지 표시 순서를 보존하며, 각 사용자 메시지 바로 뒤에 해당 응답을 배치한다. -- 종료 동작은 Escape와 Ctrl+Q 입력에 대해 애플리케이션 종료를 요청해야 하며, 종료 시 새로운 대화 메시지를 추가하지 않는다. -- 프로젝트 실행 기반과 패키징 계약은 선행 프로젝트 스캐폴드 요구사항의 범위를 유지하며, 이 문서에서는 변경하지 않는다. +- 입력은 제출 시 문자열 양끝의 공백을 제거한 값으로 정규화한다. +- 정규화 결과가 빈 문자열이면 응답 선택, 메시지 목록 변경 및 새 화면 항목 추가를 수행하지 않는다. +- 유효한 입력은 사용자 메시지를 먼저 추가하고, 고정 응답 목록에서 선택한 에이전트 응답을 바로 뒤에 추가한다. +- 고정 응답은 정본으로 정의된 다섯 문장 중 표준 난수 선택으로 하나를 결정한다. +- 여러 제출의 메시지와 응답은 기존 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적한다. +- 사용자와 에이전트의 역할, 라벨 및 구조적 스타일은 메시지 역할에서 일관되게 파생한다. +- 유효 입력과 무효 입력 모두 제출 후 입력창을 빈 문자열로 초기화한다. +- 무효 입력을 처리해도 기존 대화 상태와 응답 선택 상태는 변경하지 않는다. +- Escape와 Ctrl+Q는 동일한 애플리케이션 종료 요청 경로를 사용하며, 종료 입력으로 새 메시지나 응답을 추가하지 않는다. +- 메시지와 응답은 현재 실행 세션의 메모리에만 보관하며 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 사용하지 않는다. +- 프로젝트 설치, 패키징 및 실행 진입점 계약은 REQ-001을 따르며 이 문서에서 변경하거나 중복 정의하지 않는다. - 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 도입하지 않는다. ## 7. 인수 기준 -- 앞뒤에 공백이 포함된 유효한 입력을 제출하면 공백이 제거된 사용자 메시지가 대화 영역과 세션 상태에 기록되어야 한다. -- 유효한 입력마다 사용자 메시지 하나와 고정 응답 하나가 생성되고, 대화 영역에는 사용자 메시지 다음에 해당 응답이 표시되어야 한다. -- 선택된 응답은 정의된 다섯 개의 고정 응답 중 하나여야 하며, 표준 난수 선택 절차가 호출되어야 한다. -- 여러 입력을 연속해서 제출하면 각 입력과 응답 쌍이 제출 순서대로 누적되어야 한다. -- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로 표시되고, 에이전트 응답은 에이전트 라벨과 응답용 구조적 스타일로 표시되어야 한다. -- 유효한 입력을 제출한 뒤 입력창 값은 빈 문자열이어야 한다. -- 빈 문자열을 제출하면 대화 목록, 제출 입력 목록, 선택 응답 목록 및 화면 항목이 변경되지 않아야 한다. -- 공백과 탭 또는 줄바꿈만 포함한 입력을 제출해도 빈 입력과 동일하게 처리되어야 하며 응답 선택이 호출되지 않아야 한다. -- Escape를 누르면 애플리케이션 종료 요청이 발생해야 한다. +- 양끝에 공백이 포함된 유효한 입력을 제출하면 공백이 제거된 본문만 사용자 메시지로 대화 상태와 화면에 기록되어야 한다. +- 유효한 입력마다 사용자 메시지 하나와 고정 응답 하나가 생성되어야 하며, 사용자 메시지가 응답보다 먼저 인접한 순서로 표시되어야 한다. +- 선택된 응답은 정본으로 정의된 다섯 개의 고정 응답 중 하나여야 하며 표준 난수 선택 절차가 사용되어야 한다. +- 여러 입력을 연속 제출하면 각 사용자 메시지와 응답 쌍이 제출 순서대로 누적되어야 한다. +- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로, 에이전트 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시되어야 한다. +- 유효한 입력을 제출한 뒤 입력창 값은 빈 문자열이어야 하며, 이미 기록된 메시지는 변경되지 않아야 한다. +- 빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 입력을 제출하면 메시지 목록, 제출 입력 기록, 응답 선택 기록 및 화면 항목이 변경되지 않아야 한다. +- 무효 입력을 제출한 뒤에도 입력창은 빈 문자열이어야 한다. +- Escape를 누르면 애플리케이션 종료 요청이 발생해야 하며 메시지 제출이나 응답 선택이 발생하지 않아야 한다. - Ctrl+Q를 누르면 Escape와 동일한 종료 동작이 발생해야 한다. -- 종료 단축키를 처리해도 대화 메시지나 입력 처리 상태가 새로 기록되어서는 안 된다. -- 패키지 실행 진입점에서 대화 화면을 시작할 수 있어야 하며, 대화 기능 검증은 선행 프로젝트 스캐폴드 계약과 함께 수행할 수 있어야 한다. +- 종료 단축키 처리 후에는 새 대화 메시지나 입력 처리 기록이 생성되지 않아야 한다. +- 대화 기능은 REQ-001의 설치 및 실행 기반에서 동작해야 하며, 패키징과 실행 진입점의 상세 기준을 중복 판정하지 않는다. ### REQ-002.01-AC01 — 양끝 공백을 제거하여 유효 입력을 처리한다 @@ -333,53 +326,55 @@ Ctrl+Q는 Escape와 다른 메시지 처리 경로를 사용해서는 안 되며 ## 8. 오류 및 충돌 계약 -- 입력 제출 이벤트를 사용할 수 없는 초기화 실패나 위젯 조회 실패가 발생하면 정상적인 메시지 추가로 판정하지 않으며, 부분적으로 생성된 대화 상태를 성공 상태로 남기지 않는다. -- 입력값이 빈 문자열 또는 공백만 포함한 값이면 오류가 아니라 무시 가능한 입력으로 처리하고, 응답 선택과 메시지 추가를 수행하지 않는다. -- 응답 선택에 실패하면 해당 입력에 대한 사용자 메시지와 에이전트 응답을 부분적으로 기록하지 않아야 한다. -- 고정 응답 목록이 비어 있거나 정의된 계약과 다르면 응답을 생성하지 않고 처리 실패로 식별해야 한다. -- 메시지 렌더링에 실패하면 화면에 일부 항목만 남은 상태를 완전한 처리 성공으로 간주하지 않으며, 세션 상태와 화면 상태의 불일치를 정상 결과로 기록하지 않는다. -- 입력창 초기화에 실패하면 처리 결과를 완전한 성공으로 판정하지 않아야 하며, 이후 입력 처리에서 이전 값이 재사용되지 않도록 실패 원인을 확인할 수 있어야 한다. -- 종료 요청은 이미 종료된 애플리케이션에서 중복 메시지나 대화 상태를 추가하지 않아야 한다. +- 입력 제출 이벤트나 입력 위젯을 사용할 수 없는 초기화 실패가 발생하면 정상적인 메시지 처리로 판정하지 않으며 부분 대화 상태를 성공 결과로 남기지 않는다. +- 빈 문자열 또는 공백만 포함한 입력은 오류가 아니라 무시 가능한 입력으로 처리하고 응답 선택과 메시지 추가를 수행하지 않는다. +- 응답 선택에 실패하면 해당 입력의 사용자 메시지와 에이전트 응답을 부분적으로 기록하지 않아야 하며, 앞서 성공한 세션 메시지는 변경하지 않는다. +- 고정 응답 목록이 비어 있거나 정본과 다르면 응답을 생성하지 않고 처리 실패로 식별해야 한다. +- 메시지 렌더링에 실패하면 일부 화면 항목만 남은 상태를 완전한 처리 성공으로 간주하지 않아야 한다. +- 입력창 초기화에 실패하면 처리 결과를 완전한 성공으로 판정하지 않아야 하며, 이전 입력이 다음 처리에 재사용되지 않도록 실패 원인을 확인할 수 있어야 한다. +- 종료 요청은 이미 종료된 애플리케이션에서 중복 메시지나 응답을 추가하지 않아야 한다. - 외부 API, 네트워크, 파일 저장소 또는 데이터베이스 오류를 대화 처리의 대체 경로로 사용하지 않는다. -- 지원되지 않는 실행 환경이나 선행 패키지 실행 조건을 충족하지 못한 상태에서는 대화 동작이 정상적으로 제공된 것으로 판정하지 않는다. -- 오류가 발생한 입력은 응답 선택 목록과 메시지 목록에 부분 기록을 남기지 않아야 하며, 앞서 성공한 세션 메시지는 변경하지 않는다. +- 지원되지 않는 실행 환경이나 REQ-001의 선행 실행 조건을 충족하지 못한 상태에서는 대화 동작을 정상 제공된 것으로 판정하지 않는다. +- REQ-001의 패키징 및 실행 기반과 이 문서의 대화 동작 사이에 충돌이 발생하면 프로젝트 실행 기반은 REQ-001이, 대화 상호작용의 의미와 검증 기준은 REQ-002가 정본이다. +- 어느 문서도 다른 문서의 범위를 임의로 확장하거나 동일한 기능 규칙과 인수 기준을 중복 정의하지 않는다. ## 9. 데이터 및 인터페이스 계약 -- 입력 인터페이스는 대화 입력 위젯에서 Enter로 제출되는 문자열 값을 사용한다. -- 입력값은 문자열로 취급하고 제출 시 앞뒤 공백을 제거한다. 문자열 내부의 공백은 정규화하지 않는다. +- 입력 인터페이스는 대화 입력 위젯에서 Enter로 제출되는 문자열 값이다. +- 입력값은 제출 시 양끝 공백을 제거하며 문자열 내부의 공백은 변경하지 않는다. - 정규화된 입력이 비어 있지 않으면 사용자 메시지의 본문으로 저장하고 화면에 표시한다. - 고정 응답 목록은 다음 다섯 문장을 정본으로 사용한다: "안녕하세요! 무엇을 도와드릴까요?", "그것은 제가 처리하기 불가능합니다.", "맡겨만 주세요.", "지금 처리 중입니다.", "작업을 완료하였습니다.". -- 응답 선택은 정본 고정 응답 목록을 표준 난수 선택 함수에 전달하여 수행한다. -- 세션 대화 상태의 각 메시지는 작성자 역할과 본문을 함께 보유한다. 작성자 역할은 사용자 또는 에이전트 중 하나이며, 본문은 비어 있지 않은 문자열이다. -- 화면 표시 문자열은 사용자 메시지의 경우 "사용자: 본문" 형식으로, 에이전트 응답의 경우 "에이전트: 본문" 형식으로 구성한다. -- 사용자 메시지와 에이전트 응답은 서로 다른 구조적 스타일을 사용하며, 스타일은 임의의 본문 문자열이 아니라 작성자 역할에서 파생한다. -- 유효한 제출 하나는 사용자 메시지와 그에 대응하는 에이전트 응답의 두 항목으로 구성되며, 두 항목은 인접한 순서를 유지한다. -- 빈 입력 제출은 입력창을 빈 값으로 만들 수 있지만 대화 메시지, 선택 응답 및 화면 항목을 생성하지 않는다. -- 입력창은 초기 화면에서 사용자 입력을 받을 수 있어야 하며, 유효한 제출 처리 후에도 다시 입력 가능한 상태를 유지한다. -- Escape와 Ctrl+Q는 별도 데이터 값을 생성하지 않고 애플리케이션 종료 동작을 요청하는 키 입력 인터페이스이다. -- 메시지와 선택 응답은 현재 프로세스의 세션 메모리에만 보관하며, 애플리케이션 종료 후 재조회하거나 복구하는 인터페이스는 제공하지 않는다. +- 응답 선택은 정본 고정 응답 목록 전체를 표준 난수 선택 기능에 전달하여 수행한다. +- 세션 대화 상태의 각 메시지는 사용자 또는 에이전트 작성자 역할과 비어 있지 않은 본문을 함께 보유한다. +- 사용자 메시지는 "사용자: 본문" 형식으로, 에이전트 응답은 "에이전트: 본문" 형식으로 표시한다. +- 사용자 메시지와 에이전트 응답은 서로 다른 구조적 스타일을 사용하며, 스타일은 본문 문자열이 아니라 작성자 역할에서 파생한다. +- 유효한 제출 하나는 사용자 메시지와 대응하는 에이전트 응답의 두 항목으로 구성하고 두 항목의 인접 순서를 유지한다. +- 빈 입력 제출은 입력창을 빈 값으로 만들 수 있지만 대화 메시지, 응답 선택 및 화면 항목을 생성하지 않는다. +- 입력창은 초기 화면에서 입력을 받을 수 있어야 하며 유효하거나 무효인 제출 처리 후 다시 입력 가능한 상태여야 한다. +- Escape와 Ctrl+Q는 별도 데이터 값을 생성하지 않고 동일한 애플리케이션 종료 동작을 요청하는 키 입력이다. +- 메시지와 선택 응답은 현재 프로세스의 세션 메모리에만 보관하며 애플리케이션 종료 후 재조회하거나 복구하는 인터페이스는 제공하지 않는다. +- 프로젝트 패키지 위치, 패키징 메타데이터 및 실행 진입점 계약은 REQ-001을 참조하며 이 문서에서 재정의하지 않는다. ## 10. 하위 호환성 -- `chat-tui`와 `python -m chat_tui` 실행 방식은 선행 프로젝트 스캐폴드 요구사항에 정의된 계약을 유지해야 한다. -- 기존 Textual 기반 화면 진입과 입력 위젯의 역할을 유지하며, 대화 기능 분리로 설치 방법이나 실행 명령을 변경하지 않는다. -- 기존의 입력 정규화, 메시지 누적, 고정 응답 선택, 응답 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 의미를 변경하지 않는다. -- 기존에 공백이 포함된 유효한 입력을 제출하면 정규화된 값만 대화에 기록해야 하며, 공백만 입력한 경우에는 아무 대화 항목도 추가하지 않아야 한다. -- 고정 응답 문구와 사용자 및 에이전트 표시 라벨은 기존 동작과 호환되도록 유지한다. -- Escape와 Ctrl+Q를 통한 종료 방식은 기존 호출자와 사용자의 추가 변환 없이 계속 사용할 수 있어야 한다. -- 세션 내 메시지 누적은 유지하되, 영속성이나 외부 서비스 연동을 새로 도입하지 않는다. -- 테스트와 문서는 기능을 신규 요구사항으로 분리하더라도 실제 애플리케이션 코드가 제공하는 동작과 일치해야 한다. -- 프로젝트 스캐폴드, Python 지원 버전, Textual 의존성, 패키지 이름과 실행 진입점은 이 요구사항의 변경 대상이 아니다. -- 대화 기능을 사용하는 기존 호출자는 별도 마이그레이션 없이 동일한 입력과 키 조작으로 동일한 관찰 결과를 얻을 수 있어야 한다. +- REQ-001에 정의된 `chat-tui` 콘솔 실행 방식과 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다. +- 대화 기능 분리로 프로젝트 설치 방법, Python 지원 버전, 패키지 이름, Textual 의존성 및 실행 진입점 계약을 변경하지 않는다. +- 기존 Textual 화면 진입과 입력 위젯의 역할을 유지해야 한다. +- 기존의 입력 양끝 공백 제거, 유효 입력 판정, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 의미를 변경하지 않는다. +- 공백이 포함된 유효한 입력은 정규화된 값만 대화에 기록하고, 공백만 포함한 입력은 대화 항목을 추가하지 않아야 한다. +- 고정 응답 문구와 사용자 및 에이전트 표시 라벨은 기존 동작과 호환되도록 유지해야 한다. +- Escape와 Ctrl+Q 종료 방식은 별도 변환 없이 계속 사용할 수 있어야 하며 두 키는 동일한 종료 동작을 요청해야 한다. +- 세션 내 메시지 누적은 유지하되 영속성이나 외부 서비스 연동을 새로 도입하지 않는다. +- 대화 기능을 사용하는 기존 호출자는 추가 마이그레이션 없이 동일한 입력과 키 조작으로 동일한 관찰 결과를 얻어야 한다. +- 테스트와 문서는 실제 애플리케이션이 제공하는 입력, 응답, 표시, 입력창 및 종료 동작과 일치해야 한다. +- REQ-001의 프로젝트 구조, 패키징 및 실행 진입점은 이 요구사항의 변경 대상이 아니며, REQ-002는 해당 선행 계약을 의존한다. +- 대화 상호작용의 상세 규칙은 REQ-002에서만 정본으로 관리하고 REQ-001에 중복 기록하지 않는다. ## 11. 검증 계획 Python 3.11 이상 환경에서 애플리케이션을 실행하여 대화 입력과 종료 동작을 검증한다. 정상 입력에서는 앞뒤 공백이 제거된 사용자 메시지와 고정 응답이 제출 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 세션 내 메시지가 사용자 메시지와 응답의 인접한 쌍으로 누적되는지 확인한다. 빈 입력이나 공백만 포함한 입력에서는 응답 선택, 메시지 누적 및 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택이 정본으로 정의된 다섯 개 문구 중 하나를 표준 난수 방식으로 결정하는지와 선택 결과가 에이전트 메시지로 표시되는지 확인한다. 사용자와 에이전트 메시지의 라벨과 구조적 스타일이 역할에 맞는지 검증한다. Escape와 Ctrl+Q 입력은 애플리케이션 종료를 요청하고 종료 전에 새 메시지나 응답을 생성하지 않는지 확인한다. 프로젝트 설치 및 두 실행 진입점의 검증을 선행한 뒤 대화 기능 회귀 검증을 수행하며, 외부 API나 영속 저장소 없이 저장소의 자동화 테스트로 결과를 판정한다. -테스트 추적성 계약: - -테스트 정의와 실행 증거는 별도 테스트 카탈로그 및 증거 산출물에서 관리한다. 대화 입력 정규화, 빈 입력 무시, 메시지와 응답의 순서 및 누적, 고정 응답 선택, 입력창 초기화, 역할별 표시와 종료 단축키에 대한 각 인수 기준의 검증 연결을 빠짐없이 기록한다. 실행 증거에는 요구사항 개정, 검증한 커밋, 실행 환경, 실행 시각과 결과를 포함하며, 실행하지 않은 검증은 성공으로 간주하지 않는다. +테스트 정의와 실행 증거는 별도 테스트 카탈로그 및 증거 산출물에서 관리한다. 대화 입력 정규화, 빈 입력 무시, 메시지와 응답의 순서 및 누적, 고정 응답 선택, 입력창 초기화, 역할별 표시와 종료 단축키에 대한 각 인수 기준의 검증 연결을 빠짐없이 기록한다. 실행 증거에는 요구사항 개정, 검증한 커밋, 실행 환경, 실행 시각과 결과를 포함하며, 아직 실행하지 않은 검증은 성공으로 간주하지 않는다. 현재 문서 작성 시점에는 이 요구사항을 검증한 실행 커밋과 실행 시각을 기록하지 않는다. ### 테스트 추적성 계약 @@ -399,7 +394,7 @@ Verifies: - REQ-002.05-AC01 - REQ-002.05-AC02 Test reference: tests/test_app.py 및 python -m unittest discover -s tests -v -Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스트로 입력, 응답, 빈 입력, 역할별 표시, 입력창 초기화 및 종료 동작을 자동 검증한다. +Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스트로 입력 정규화, 응답 선택, 메시지 순서, 빈 입력, 역할별 표시, 입력창 초기화 및 종료 동작을 자동 검증한다. ``` 실행 증거: @@ -407,19 +402,27 @@ Automated: 저장소의 기존 unittest 기반 Textual 애플리케이션 테스 ```text Test ID: TC-002-001 Requirement revision: REQ-002@0.1 -Commit: d0ac7fc7bcfaf402bbda24776f051fa9992993e1 +Commit: 검증 커밋 미기록 Environment: Python 3.11 이상 및 선언된 Textual 런타임 의존성이 설치된 환경 Result: 미실행 -Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 +Executed at: 검증 실행 시각 미기록 ``` ## 12. 추적성 -근거는 원본 Gitea 이슈 #8인 「요구사항명세서의 재작업」, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소 README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 원본 이슈 #8에서 요구한 대화 기능 분리의 결과로 작성되며, 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하되 그 의미와 실행 계약을 변경하지 않는다. 사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서만 추적한다. 패키징 메타데이터와 실행 진입점은 선행 프로젝트 스캐폴드 문서에서 추적하며 이 문서에서는 상세 규칙과 수용 기준을 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 고정 응답 목록, 역할별 표시 구조, 종료 바인딩과 관련 테스트는 각 동작의 근거 및 검증 지점이다. +근거는 원본 Gitea 이슈 #8인 「요구사항명세서의 재작업」, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소 README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 원본 이슈 #8에서 요구한 대화 기능 분리의 결과로 작성되며, 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하되 그 의미와 실행 계약을 변경하지 않는다. + +사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서만 추적한다. 패키징 메타데이터와 실행 진입점은 선행 프로젝트 스캐폴드 문서에서 추적하며 이 문서에서는 상세 규칙과 수용 기준을 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 고정 응답 목록, 역할별 표시 구조, 종료 바인딩과 관련 테스트는 각 동작의 근거 및 검증 지점이다. + +프로젝트 스캐폴드 문서와의 의존 관계는 설치 및 실행 기반에 한정한다. 두 문서는 동일한 기능 규칙이나 인수 기준을 중복 정의하지 않으며, 대화 동작의 검증 결과는 실제 실행된 검증 기록이 있을 때만 별도 증거로 연결한다. ## 13. 확정된 결정 -원본 이슈 #8의 분리 범위에 따라 기존 구현과 테스트가 정의한 대화 동작을 독립된 요구사항 문서로 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 대화 항목을 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 정본으로 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. 사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 애플리케이션 종료 동작을 요청한다. 프로젝트 스캐폴드의 승인 상태와 기존 승인 이력은 선행 문서에서 보존하며, 이 문서는 대화 동작의 의미와 검증 기준만 관리한다. 외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. +원본 이슈 #8의 분리 범위에 따라 기존 구현과 테스트가 정의한 대화 동작을 독립된 요구사항 문서로 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 대화 항목을 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 정본으로 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. + +사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청한다. 프로젝트 스캐폴드의 승인 상태와 기존 승인 이력은 선행 문서에서 보존하며, 이 문서는 대화 동작의 의미와 검증 기준만 관리한다. + +외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. 실행되지 않은 검증은 특정 커밋의 실행 증거 또는 성공 결과로 기록하지 않는다. ## 14. 미결 사항 @@ -427,4 +430,8 @@ Executed at: 문서 작성 시점에는 실행 증거를 기록하지 않음 ## 15. 승인 기록 -상태는 초안이다. 승인 주체는 아직 지정되지 않았으며 승인 근거도 기록되지 않았다. 원본 Gitea 이슈 #8의 디스커버리 결과에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행해야 한다. +상태: draft +승인 주체: 미승인 +승인 근거: 없음 + +원본 Gitea 이슈 #8의 디스커버리 결과에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행한다. 승인 전에는 대화 상호작용의 범위, 검증 기준 및 선행 프로젝트 스캐폴드와의 의존 관계를 검토하고, 실제로 실행되지 않은 검증을 승인 근거나 실행 증거로 기록하지 않는다. -- 2.54.0 From 15d8c7530837f4ebd94fdf84510ad9b48c972b2d Mon Sep 17 00:00:00 2001 From: code-agent Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH 4/5] code-agent: rework issue 8 Review-ID: 40 Previous-SHA: 7bfe2b62f4d0e4cd0ef86a04e7ca329a49d64f07 Plan-SHA256: 917511183e1494310bb6a0ce480788a8bfadfef0c6f6b309f7324f212964d9fb Bundle-SHA256: 29ce1ef1917864f79938459725201e6e74d67e21b1f817ac53d7b294eca8f1a2 --- docs/requirements/req-001_project-scaffold.md | 326 ++++++++---------- .../req-002_conversation-interaction.md | 323 +++++++++-------- 2 files changed, 324 insertions(+), 325 deletions(-) diff --git a/docs/requirements/req-001_project-scaffold.md b/docs/requirements/req-001_project-scaffold.md index e49c995..ae65bfb 100644 --- a/docs/requirements/req-001_project-scaffold.md +++ b/docs/requirements/req-001_project-scaffold.md @@ -2,291 +2,249 @@ { "schema": "proofline.requirement/v1", "id": "REQ-001", - "title": "프로젝트 스캐폴드와 실행 진입점", + "title": "프로젝트 스캐폴드의 메시지 작성자 구분", "revision": "0.1", "status": "approved", "depends_on": [], "applies_to": [ - "프로젝트 스캐폴드", - "Python 패키징", - "콘솔 실행 진입점" + "chat-tui-message-rendering" ], "language": "ko" } --- -# REQ-001 — 프로젝트 스캐폴드와 실행 진입점 +# REQ-001 — 프로젝트 스캐폴드의 메시지 작성자 구분 ## 1. 목적 -이 요구사항은 Python 3.11 이상에서 실행되는 Textual 기반 대화형 TUI 프로젝트의 스캐폴드, 패키징 메타데이터와 실행 진입점을 정의한다. 프로젝트가 표준 Python 패키지로 설치되고 `chat-tui` 콘솔 명령 또는 `python -m chat_tui` 방식으로 시작되는 상태를 보장한다. 대화 입력 처리와 응답 표시 동작은 REQ-002에서 단일 정본으로 관리하며 이 문서에서는 정의하지 않는다. - -기존 REQ-001의 프로젝트 스캐폴드 정체성, 승인 상태, 승인 주체인 `spec-agent`, 승인 근거인 승인 댓글 923 및 디스커버리 승인 결과를 보존한다. 이번 정리는 승인 상태를 초안으로 되돌리거나 승인 근거를 삭제하지 않으며, 프로젝트 스캐폴드와 실행 기반의 범위만 명확히 하는 변경으로 한정한다. +대화형 Textual TUI에서 사용자가 입력한 메시지와 에이전트의 응답을 작성자 라벨과 구조적 스타일로 명확하게 구분한다. 각 메시지의 작성자 의미를 명시적인 데이터 역할로 관리하여 화면 표시, 실행 흐름 및 자동 테스트에서 일관되게 검증할 수 있게 한다. ## 2. 배경 -프로젝트는 소스 코드를 `src` 레이아웃 아래에 두고 `chat_tui` 패키지로 제공한다. 패키징은 setuptools 빌드 백엔드를 사용하며 Python 3.11 이상을 실행 환경으로 요구한다. 런타임에는 Textual 0.47 이상 1.0 미만을 사용하고, 테스트용 선택 의존성으로 pytest 8.0 이상을 제공한다. 패키지 버전은 현재 `0.1.0`으로 관리한다. +현재 애플리케이션은 사용자 메시지와 에이전트 응답을 서로 다른 CSS 클래스를 가진 Label로 표시하지만 화면에 작성자 라벨이 없고 작성자 의미가 데이터 개념으로 표현되지 않는다. 따라서 메시지의 작성자를 화면에서 구분하기 어렵고, 테스트도 표시 순서와 내용만 검증할 뿐 작성자 역할과 구조적 구분을 검증하지 못한다. -패키지 설치와 실행 진입점은 대화 기능과 독립적으로 검증할 수 있는 프로젝트 기반 계약이다. 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 원본 Gitea 이슈 #8의 재작업 범위에 따라 REQ-002에서 추적한다. REQ-002는 REQ-001의 실행 기반을 의존 대상으로 사용하지만, 패키징과 실행 진입점의 상세 계약을 중복 정의하지 않는다. +이번 요구사항은 외부 API나 LLM 연동 없이 현재 Textual 기반 대화 흐름을 유지하면서 작성자 의미를 명시적으로 모델링하고, 색상에만 의존하지 않는 라벨·테두리·정렬 기반의 구분을 제공하기 위한 것이다. ## 3. 범위 -이 문서는 `src/chat_tui` Python 패키지의 기본 구조, 패키지 버전 공개, `pyproject.toml`의 빌드 시스템과 프로젝트 메타데이터, Python 및 런타임 의존성, 테스트 선택 의존성, `chat-tui` 콘솔 스크립트와 `python -m chat_tui` 모듈 실행 진입점을 포함한다. 소스 디렉터리를 패키지 탐색 대상으로 사용하는 설치 구조도 포함한다. +포함 범위는 다음과 같다. -대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 역할별 대화 표시, 빈 입력 처리, 입력창 초기화와 종료 단축키의 상세 동작 및 수용 기준은 포함하지 않는다. 해당 내용은 REQ-002에서 단일 정본으로 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경 변경도 포함하지 않는다. +- 사용자 메시지와 에이전트 응답을 각각 별도의 Label 대화 항목으로 표시한다. +- 각 메시지에 사용자 또는 에이전트라는 명시적인 작성자 역할을 부여한다. +- 화면에 사용자와 에이전트 작성자 라벨을 표시한다. +- `user-message`와 `response-message` 식별자를 유지하고, 테두리 또는 정렬 차이 같은 구조적 스타일을 적용한다. +- 유효한 입력의 정규화, 응답 선택, 메시지 표시 순서 및 공백 입력 무시 동작을 유지한다. +- 작성자 역할, 라벨, 구조적 스타일 및 기존 동작을 자동 테스트로 검증한다. +- 관련 요구사항, 데이터 모델, 인터페이스 계약 및 실행 흐름 문서와의 추적성을 유지한다. + +제외 범위는 다음과 같다. + +- LLM 연동 또는 외부 API 호출 +- 대화 저장, 사용자 인증 또는 사용자별 기록 관리 +- 고정 응답 목록과 응답 생성 방식의 변경 +- 대화 영역 전체 레이아웃의 재설계 +- 색상만으로 작성자를 구분하는 방식 +- 별도 영속성 백엔드나 데이터베이스 도입 ### 포함 -Python 3.11 이상을 대상으로 하는 chat_tui 패키지의 src 기반 프로젝트 구조, setuptools 패키징 설정, 프로젝트 메타데이터, 런타임 및 선택적 테스트 의존성, chat-tui 콘솔 스크립트와 python -m chat_tui 실행 진입점을 포함한다. 기존 REQ-001의 승인 상태와 승인 주체 spec-agent, 승인 근거 승인 댓글 923 및 디스커버리 승인 결과를 보존한다. +대화형 Textual TUI에서 사용자 메시지와 에이전트 응답을 명시적인 작성자 역할로 관리하고, 사용자·에이전트 라벨과 구조적 스타일로 구분하여 표시한다. 유효한 입력의 정규화, 고정 응답 선택, 메시지 순서, 공백 입력 무시 및 관련 자동 검증을 포함한다. ### 제외 -대화 입력 정규화, 메시지 누적, 고정 응답 선택 및 표시, 빈 입력 처리, 입력창 초기화, 종료 단축키를 포함한 대화 상호작용의 상세 동작과 수용 기준은 별도 REQ-002에서 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 및 실행 환경 변경도 제외한다. +외부 API 또는 LLM 연동, 대화 저장과 사용자 인증, 고정 응답 목록과 생성 방식의 변경, 대화 영역 전체 레이아웃 재설계, 색상만으로 작성자를 구분하는 방식 및 별도 영속성 백엔드 도입은 포함하지 않는다. ## 4. 용어와 기준 -스캐폴드는 다음 기준을 따른다. +사용자 메시지는 입력창에 사용자가 제출한 공백 제거 후의 유효한 문자열이다. 에이전트 응답은 유효한 사용자 입력마다 고정된 응답 목록에서 표준 난수 선택으로 생성되는 문자열이다. 메시지 역할은 메시지를 작성한 주체를 나타내는 명시적인 값이며 `user` 또는 `agent` 중 하나다. -- 프로젝트 이름은 `gitea-agent-testbed`이고 Python 패키지 이름은 `chat_tui`이다. -- 소스 루트는 `src`이며 패키지 탐색 설정은 해당 루트를 기준으로 한다. -- 패키지 초기화 모듈은 패키지 버전 `0.1.0`을 공개한다. -- 모듈 실행 진입점은 애플리케이션 모듈의 공개 실행 함수인 `main`을 호출한다. -- 콘솔 스크립트 진입점은 `chat_tui.app:main`으로 연결한다. -- 빌드 백엔드는 setuptools를 사용하고 빌드 요구 버전은 68 이상이다. -- 테스트 설정은 `src`를 Python 경로에 포함하고 `tests` 디렉터리를 검색 대상으로 한다. -- 프로젝트 스캐폴드 설명은 실제 패키지 구조와 패키징 설정에 부합해야 한다. -- 대화 상호작용의 의미와 세부 검증 기준은 REQ-002를 기준으로 하며 이 문서의 기준과 중복하지 않는다. -- 기존 REQ-001의 승인 상태와 승인 이력은 승인된 프로젝트 스캐폴드 범위의 기록으로 보존한다. +작성자 라벨은 사용자 역할을 `사용자`, 에이전트 역할을 `에이전트`로 화면에 표시하는 문자열이다. 구조적 스타일은 색상에만 의존하지 않고 CSS 클래스, 테두리 또는 정렬 차이로 작성자를 구분하는 표현이다. + +정본 기준은 `ChatMessage.role`과 `ChatMessage.content`의 조합을 메시지 의미의 단일 기준으로 삼는 것이다. 작성자 라벨과 CSS 클래스는 이 역할에서 파생하며, CSS 클래스만으로 메시지 역할을 판정하지 않는다. ## 5. 요구사항 -시스템은 다음 프로젝트 기반 요구를 충족해야 한다. +`REQ-001`은 대화 메시지의 작성자 의미를 명시적으로 관리하고 화면 및 검증 절차에서 일관되게 구분하기 위한 요구사항 묶음의 식별자다. -- 프로젝트는 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`여야 하며, 역할과 본문은 하나의 대화 메시지 단위로 보존되어야 한다. 이 요구사항은 `ChatMessage`, `MessageRole`, 대화 영역의 Label 렌더링, 세션 메모리의 메시지 목록 및 UI 렌더러와 자동 테스트에 영향을 준다. 유효한 입력의 정규화, 응답 선택, 입력·응답 배열 및 표시 순서는 유지하며 별도 영속성이나 마이그레이션은 필요하지 않다. -프로젝트는 소스 디렉터리 기반의 `chat_tui` Python 패키지로 구성되어야 하며, 패키징 메타데이터에 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 3.11 이상 실행 조건과 Textual 0.47 이상 1.0 미만의 런타임 의존성을 선언해야 한다. 패키지는 setuptools 빌드 백엔드와 소스 디렉터리 검색 설정을 사용해야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. +시스템은 각 메시지의 명시적인 역할을 작성자 라벨과 구조적 스타일로 변환하여 표시해야 한다. 사용자 메시지는 `사용자` 라벨과 `user-message` 식별자를 사용하고, 에이전트 응답은 `에이전트` 라벨과 `response-message` 식별자를 사용해야 한다. 사용자 Label에는 `chat-message user-message user-role` 클래스가 포함되고 에이전트 Label에는 `chat-message response-message agent-role` 클래스가 포함되어야 한다. 구조적 스타일은 색상만으로 작성자를 구분하지 않아야 하며 역할별 테두리 또는 정렬 차이를 포함해야 한다. 기존 식별자와 사용자·응답의 표시 순서는 유지하고, 화면 위젯과 세션 메모리만 변경하며 별도 영속성이나 마이그레이션은 필요하지 않다. -프로젝트는 `python -m chat_tui` 명령으로 실행할 수 있어야 한다. 모듈 실행은 애플리케이션의 공개 실행 함수인 `main`을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. +### REQ-001.01 — 명시적인 메시지 역할 관리 -패키징 설정은 `chat-tui` 콘솔 명령을 `chat_tui.app:main`에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 하며, 콘솔 명령과 모듈 실행 명령은 동일한 애플리케이션 시작 동작을 호출해야 한다. - -대화 입력, 응답, 메시지 표시와 종료 동작의 상세 요구사항 및 수용 기준은 REQ-002에서 관리한다. 이 문서에 이를 중복 기록하지 않으며, REQ-001의 승인 상태와 기존 승인 이력은 변경하지 않는다. - -### REQ-001.01 — Python 패키지 구조와 메타데이터를 제공한다 - -프로젝트는 Python 3.11 이상에서 설치 및 실행 가능한 표준 Python 패키지 구조를 제공해야 한다. 소스 루트는 src이며 src/chat_tui 패키지를 배포 대상으로 포함해야 한다. setuptools 빌드 백엔드와 소스 디렉터리 패키지 검색 설정을 사용하고, 프로젝트 이름, 버전 0.1.0, 설명, README 참조, Python 최소 버전 및 Textual 0.47 이상 1.0 미만의 런타임 의존성을 패키징 메타데이터에 선언해야 한다. 테스트용 pytest 8.0 이상 의존성은 선택적으로 설치할 수 있어야 하며, 패키지 버전은 애플리케이션에서 조회할 수 있고 프로젝트 메타데이터와 일치해야 한다. +시스템은 유효한 사용자 입력과 그에 대응하는 에이전트 응답을 각각 명시적인 작성자 역할을 가진 메시지로 관리해야 한다. 사용자 메시지의 역할은 user, 에이전트 응답의 역할은 agent여야 하며, 역할과 본문은 하나의 대화 메시지 단위로 함께 보존되어야 한다. 유효한 입력의 정규화, 응답 선택, 메시지 목록의 순서와 기존 세션 내 동작은 유지해야 한다. **영향 범위** -인터페이스: Python 패키지 설치와 import 경계에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자, 패키지 설치 도구와 실행 진입점. 마이그레이션: 필요 없음. 호환성: Python 3.11 이상, 프로젝트 이름, 패키지 이름과 버전 계약을 유지한다. 배포 전제 조건: setuptools 기반 설치와 src 패키지 탐색이 가능해야 한다. +인터페이스는 ChatMessage, MessageRole 및 대화 영역의 Label 렌더링에 영향을 받는다. 영속성은 없으며 메시지는 애플리케이션 세션 메모리에만 유지한다. 후속 사용 주체는 UI 렌더러와 자동 테스트다. 마이그레이션은 필요하지 않다. Python 3.11 이상과 현재 Textual 실행 환경을 유지한다. -### REQ-001.02 — 모듈 실행 진입점을 제공한다 +### REQ-001.02 — 작성자 라벨과 구조적 표시 -프로젝트는 python -m chat_tui 명령으로 실행할 수 있어야 한다. 모듈 진입점은 애플리케이션의 공개 실행 함수인 main을 호출해야 하며, 패키지를 단순히 import하는 것만으로 애플리케이션을 시작해서는 안 된다. 실행 진입점은 설치된 패키지와 선언된 런타임 환경에서 동일한 애플리케이션 시작 흐름으로 연결되어야 한다. +시스템은 각 메시지의 명시적인 역할을 작성자 라벨과 구조적 스타일로 변환하여 표시해야 한다. 사용자 메시지는 사용자 라벨과 user-message 식별자를 사용하고, 에이전트 응답은 에이전트 라벨과 response-message 식별자를 사용해야 한다. 구조적 스타일은 색상만으로 작성자를 구분하지 않아야 하며 역할별 테두리 또는 정렬 차이를 포함해야 한다. **영향 범위** -인터페이스: python -m chat_tui 실행 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 개발자와 운영자가 사용하는 Python 모듈 실행 환경. 마이그레이션: 필요 없음. 호환성: 기존 모듈 실행 방식과 공개 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지가 Python 모듈 검색 경로에 설치되어 있어야 한다. - -### REQ-001.03 — 콘솔 스크립트 실행 진입점을 제공한다 - -패키징 설정은 chat-tui 콘솔 명령을 chat_tui.app:main에 연결해야 한다. 설치 후 사용자는 별도의 경로 지정이나 내부 모듈 호출 없이 해당 명령으로 TUI를 시작할 수 있어야 하며, 콘솔 명령과 모듈 실행 명령은 동일한 애플리케이션 시작 동작을 호출해야 한다. - -**영향 범위** - -인터페이스: 설치 후 제공되는 chat-tui 콘솔 명령에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 최종 사용자와 운영 스크립트. 마이그레이션: 필요 없음. 호환성: 프로젝트에서 정의한 콘솔 명령 이름과 실행 함수 연결을 유지한다. 배포 전제 조건: 패키지 설치 시 console script가 생성되어야 한다. - -### REQ-001.04 — 기존 승인 상태와 승인 근거를 보존한다 - -프로젝트 스캐affold 요구사항 문서는 기존 요구사항의 정체성과 승인 이력을 유지해야 한다. 기존 승인 상태는 approved로 보존하고, 승인 주체는 spec-agent로 명시하며, 승인 근거는 승인 댓글 923 및 디스커버리 승인 결과로 구조화하여 기록해야 한다. 문서 분리와 범위 정리만으로 승인 상태를 초안으로 되돌리거나 승인 근거를 삭제하거나 일반적인 서술로 대체해서는 안 된다. 실행되지 않은 검증은 특정 커밋의 실행 증거로 제시하지 않고 미기록 상태로 명확히 표시해야 한다. - -**영향 범위** - -인터페이스: 요구사항 문서의 승인 기록과 검증 추적성에 영향을 준다. 영속성: 문서 이력과 승인 메타데이터를 보존한다. 후속 사용 주체: 요구사항 검토자, 구현자와 승인 담당자. 마이그레이션: 기존 승인 기록을 삭제하지 않고 보존해야 한다. 호환성: 승인된 프로젝트 스캐폴드의 의미와 이력을 유지한다. 배포 전제 조건: 검증 증거가 실제 실행 상태와 일치해야 한다. +인터페이스는 conversation 영역 내부 Label의 표시 문자열과 CSS 클래스에 영향을 받는다. 영속성은 없으며 화면 위젯과 세션 메모리만 변경한다. 후속 사용 주체는 사용자, UI 검수자 및 자동 회귀 테스트다. 마이그레이션은 필요하지 않다. Textual의 Label, VerticalScroll 및 CSS 스타일 기능을 사용할 수 있어야 한다. ## 6. 제약과 불변조건 -- 프로젝트는 Python 3.11 이상에서 실행되어야 한다. -- 패키지 구성은 `src` 기반 레이아웃을 유지하고 `src/chat_tui`를 배포 대상으로 포함해야 한다. -- 빌드 백엔드는 setuptools를 사용하며, 런타임 의존성은 Textual 0.47 이상 1.0 미만 범위로 관리해야 한다. -- 테스트 의존성은 제품 런타임 의존성과 분리된 선택 항목으로 제공하며 pytest 8.0 이상을 지정해야 한다. -- 프로젝트 메타데이터의 이름, 버전, 설명, README 참조, Python 최소 버전, 의존성 및 패키지 검색 설정은 서로 일치해야 한다. -- 패키지 공개 버전과 패키징 메타데이터의 버전은 `0.1.0`으로 일치해야 한다. -- `chat-tui` 콘솔 진입점과 `python -m chat_tui` 모듈 진입점은 동일한 공개 애플리케이션 시작 함수를 호출해야 한다. -- 패키지를 import하는 것만으로 애플리케이션이 시작되어서는 안 된다. -- 이 문서는 프로젝트 구조, 패키징 및 실행 진입점만 정본으로 관리한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 대화 상호작용 요구사항에서만 정본으로 관리한다. -- 대화 상호작용 요구사항은 이 문서가 제공하는 설치 및 실행 기반에 의존하지만, 이 문서의 스캐폴드 계약을 변경하지 않는다. -- 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 새 의존성, 배포 방식 또는 실행 환경을 추가하지 않는다. +- Python 3.11 이상과 현재 Textual 기반 TUI 구조를 유지한다. +- 유효한 입력은 앞뒤 공백을 제거한 뒤 사용자 메시지로 한 번만 기록한다. +- 공백만 있거나 빈 입력은 응답을 선택하지 않고 메시지 목록과 화면을 변경하지 않는다. +- 유효한 입력 하나마다 사용자 메시지가 먼저 표시되고 그 뒤에 에이전트 응답이 표시되어야 한다. +- 에이전트 응답은 기존 고정 응답 목록에서 표준 난수 선택으로 결정한다. +- 모든 메시지는 명시적인 메시지 역할을 통해 작성자 의미를 가져야 하며 CSS 클래스만으로 역할을 판정하지 않는다. +- 사용자와 에이전트는 화면의 텍스트 라벨로 구분되어야 한다. +- 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다. +- 메시지 표시와 테스트에서 사용자 및 에이전트 역할의 순서와 의미가 일치해야 한다. +- 외부 API, 인증, 영속 저장소 및 민감정보 처리는 추가하지 않는다. ## 7. 인수 기준 -- Python 3.11 이상 환경에서 프로젝트를 설치하면 `src` 아래의 `chat_tui` 패키지가 정상적으로 검색되고 설치되어야 한다. -- 패키징 설정에는 프로젝트 이름, 버전 `0.1.0`, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성 및 `src` 기반 패키지 검색 설정이 포함되어야 한다. -- 테스트 선택 의존성은 런타임 의존성과 별도로 설치할 수 있어야 하며 저장소 테스트를 검색하고 실행할 수 있어야 한다. -- 설치된 `chat-tui` 명령은 `chat_tui.app:main`에 연결되어 애플리케이션 시작 절차로 진입해야 한다. -- `python -m chat_tui` 실행은 콘솔 명령과 동일한 공개 시작 함수를 통해 애플리케이션을 시작해야 한다. -- `chat_tui`에서 조회되는 공개 버전과 패키징 메타데이터의 버전은 `0.1.0`으로 일치해야 한다. -- 패키지를 단순히 import하는 것만으로 TUI가 시작되어서는 안 된다. -- 설치 또는 실행에 필요한 메타데이터와 진입점이 누락되면 정상 동작으로 판정하지 않아야 한다. -- 프로젝트 스캐폴드 변경 후에도 대화 상호작용 요구사항에서 정본으로 관리하는 입력, 응답, 빈 입력, 입력창 초기화 및 종료 동작의 기존 회귀 검증이 유지되어야 한다. -- 검증은 패키지 설치, 메타데이터 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 확인하는 방식으로 수행하며 실행하지 않은 검증은 통과로 판정하지 않는다. +인수 기준은 각 소속 요구사항을 포함하는 식별 체계로 관리하며, 판정 조건과 검증 방법 및 상태 불변조건을 함께 기록한다. -### REQ-001.01-AC01 — 패키징 메타데이터가 프로젝트 계약과 일치한다 +**메시지 역할이 순서대로 보존됨** + +판정 기준은 유효한 입력의 앞뒤 공백이 제거된 사용자 메시지가 사용자 역할로 기록되고, 같은 제출에서 선택된 응답이 에이전트 역할로 기록되는지 확인하는 것이다. 여러 입력을 제출할 때 메시지 목록은 각 입력에 대해 사용자 메시지 다음에 에이전트 응답이 오는 순서를 유지해야 하며, 역할과 본문은 함께 비교 가능해야 한다. 역할은 CSS 클래스에서 추론하지 않는다. + +검증은 Textual 테스트 앱에서 두 개의 유효한 입력을 제출하고 제출 입력, 선택 응답 및 메시지의 값과 순서를 비교하는 방식으로 수행한다. 메시지가 사용자와 에이전트 역할을 번갈아 포함하는지 확인하고, 응답 선택을 고정하여 입력 정규화와 역할 보존을 결정적으로 검증한다. 검증 수준은 통합 테스트이며 별도 백엔드는 없고 정상 사례를 대상으로 한다. + +성공하면 입력과 응답이 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다. 기존 입력과 응답의 순서 및 내용은 변경되지 않아야 하며, 실패 또는 공백 입력에서는 응답 선택과 메시지 추가가 발생하지 않아야 한다. + +**공백 입력이 역할 없는 메시지를 만들지 않음** + +판정 기준은 빈 문자열 또는 공백, 탭, 개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않고 응답 선택 함수가 호출되지 않는지 확인하는 것이다. 제출 후 입력창은 비워져야 한다. + +검증은 공백만 포함한 입력과 빈 입력을 각각 Textual 테스트 앱에 제출하고 메시지 목록과 대화 영역 항목 수가 변경되지 않는지 확인하는 방식으로 수행한다. 응답 선택 함수가 호출되지 않았는지와 입력창이 비워지는지를 확인한다. 검증 수준은 통합 테스트이며 경계 사례를 대상으로 한다. + +무시 처리가 성공하면 메시지 목록, 제출 입력 기록 및 응답 기록은 변경되지 않아야 한다. 대화 영역에 작성자 라벨을 포함한 새 항목이 추가되어서는 안 되며, 실패 시 부분적인 사용자 메시지 또는 응답이 남아서는 안 된다. + +**작성자 라벨과 구조적 스타일이 역할과 일치함** + +판정 기준은 사용자 메시지가 사용자 라벨과 사용자 식별자를 사용하고, 에이전트 응답이 에이전트 라벨과 에이전트 식별자를 사용하는지 확인하는 것이다. 사용자 표시에는 사용자 역할 클래스가, 에이전트 표시에는 에이전트 역할 클래스가 포함되어야 한다. CSS에는 양쪽 역할의 구조적 차이를 나타내는 테두리 또는 정렬 규칙이 있어야 한다. + +검증은 유효한 입력 하나를 제출하고 대화 영역의 두 표시 항목을 조회하여 렌더링 문자열과 클래스가 각각의 역할과 일치하는지 확인하는 방식으로 수행한다. 애플리케이션 CSS에 역할별 테두리와 정렬 규칙이 포함되는지도 확인한다. 검증 수준은 통합 테스트이며 정상 사례를 대상으로 한다. + +성공하면 각 메시지의 라벨과 구조적 클래스가 해당 역할과 일치해야 한다. 메시지 본문, 표시 순서 및 기존 식별자는 변경되지 않아야 하며, 렌더링 실패 시 다른 역할의 라벨이나 일부만 표시된 메시지가 남아서는 안 된다. + +**기존 응답 선택과 종료 동작을 보존함** + +판정 기준은 유효한 입력 제출 시 기존 응답 목록을 인자로 하여 표준 난수 선택이 한 번 호출되고, Escape 입력이 기존처럼 애플리케이션 종료를 요청하는지 확인하는 것이다. 작성자 구분 기능을 추가해도 기존 입력과 응답 회귀 검증이 통과해야 한다. + +검증은 난수 선택을 모의 처리하여 고정 응답 목록이 전달되는지 확인하고, Textual 테스트 앱에서 Escape를 입력하여 종료 요청을 확인하는 방식으로 수행한다. 유효 입력 두 건의 정규화, 응답 내용, 표시 순서 및 입력창 초기화를 함께 검증한다. 검증 수준은 통합 테스트이며 변경 없음 사례를 대상으로 한다. + +성공하면 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다. 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되어서는 안 되며, 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다. + +### REQ-001.01-AC01 — 메시지 역할이 제출 순서대로 보존됨 **판정 기준** -프로젝트 이름, 버전, 설명, README 참조, Python 3.11 이상 조건, Textual 런타임 의존성, pytest 선택 의존성 및 src 기반 패키지 검색 설정이 모두 선언되어 있으면 통과로 판정한다. +유효한 사용자 입력을 제출하면 앞뒤 공백이 제거된 본문이 user 역할로 기록되고, 같은 제출에서 선택된 응답이 agent 역할로 기록되어야 한다. 여러 입력을 제출하면 각 입력에 대해 사용자 메시지 다음에 에이전트 응답이 배치되어야 하며, 역할은 CSS 클래스가 아니라 메시지 데이터에서 확인할 수 있어야 한다. **검증** -pyproject.toml을 확인하고 Python 3.11 이상 환경에서 테스트 선택 사항을 포함한 설치를 수행하여 패키지와 선언된 의존성이 정상적으로 구성되는지 검증한다. +Textual 테스트 앱에서 두 개 이상의 유효한 입력을 제출하고 submitted_inputs, selected_responses 및 messages의 값과 순서를 비교한다. 응답 선택을 고정하여 입력 정규화와 역할 보존을 결정적으로 검증한다. **검증 분류** -수준: integration; 백엔드: Python 패키징 도구와 setuptools; 케이스: positive +integration **상태 불변조건** -성공 시 선언된 패키지와 의존성이 설치되어야 한다. 패키징 설정에 명시되지 않은 외부 연동이나 배포 설정은 추가되지 않아야 한다. 설치 실패 시 유효하지 않은 패키지 계약을 성공으로 간주하지 않아야 한다. +성공 시 입력과 응답은 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다. 기존 입력과 응답의 순서 및 내용은 변경되지 않아야 한다. 실패 또는 공백 입력에서는 응답 선택과 메시지 목록 추가가 발생하지 않아야 한다. -### REQ-001.01-AC02 — 패키지 버전을 조회할 수 있다 +### REQ-001.01-AC02 — 공백 입력이 역할 없는 메시지를 만들지 않음 **판정 기준** -chat_tui 패키지를 import했을 때 비어 있지 않은 버전 값이 제공되고 패키징 메타데이터의 0.1.0과 일치하면 통과로 판정한다. +빈 문자열 또는 공백, 탭, 개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않아야 한다. 공백 입력에서는 응답 선택 함수가 호출되지 않아야 하며, 제출 후 입력창은 비워져야 한다. **검증** -Python에서 chat_tui.__version__을 조회하고 프로젝트 메타데이터의 버전 선언과 비교한다. +공백만 포함한 입력과 빈 입력을 각각 Textual 테스트 앱에 제출한다. 메시지 목록과 대화 영역의 항목 수가 변하지 않는지 확인하고, random.choice가 호출되지 않았으며 입력창 값이 비워지는지 검증한다. **검증 분류** -수준: unit; 백엔드: Python import 시스템; 케이스: positive +integration **상태 불변조건** -성공 시 패키지 import와 버전 조회가 가능해야 한다. 버전 조회가 패키지 초기화 중 외부 상태를 변경해서는 안 된다. 조회 실패 시 패키지 계약을 충족한 것으로 판정하지 않는다. +무시 처리 후 메시지 목록, 제출 입력 기록 및 응답 기록은 변경되지 않아야 한다. 작성자 라벨을 포함한 새 화면 항목이 추가되면 안 된다. 실패 시 부분적인 사용자 메시지 또는 응답이 남아서는 안 된다. -### REQ-001.02-AC01 — 모듈 명령이 애플리케이션을 시작한다 +### REQ-001.02-AC01 — 작성자 라벨과 구조적 스타일이 역할과 일치함 **판정 기준** -설치된 패키지 환경에서 python -m chat_tui를 실행했을 때 공개 실행 함수를 통해 TUI가 시작되면 통과로 판정한다. +사용자 메시지는 사용자: 본문 형식으로, 에이전트 응답은 에이전트: 본문 형식으로 표시되어야 한다. 사용자 Label에는 chat-message, user-message, user-role 클래스가 포함되고 에이전트 Label에는 chat-message, response-message, agent-role 클래스가 포함되어야 한다. CSS에는 양쪽 역할의 구조적 차이를 나타내는 테두리와 역할별 정렬 규칙이 있어야 한다. **검증** -모듈 진입점이 애플리케이션의 공개 실행 함수를 실행 조건에서 호출하는지 확인하고, 격리된 실행 환경에서 모듈 명령을 시작하여 초기 화면이 생성되는지 검증한다. +유효한 입력 하나를 제출하고 대화 영역의 Label 두 개를 조회한다. 렌더링 문자열과 클래스를 각각의 역할과 비교하고, 애플리케이션 CSS에서 사용자와 에이전트의 테두리 및 정렬 규칙을 확인한다. **검증 분류** -수준: end-to-end; 백엔드: Python 모듈 실행기와 Textual 런타임; 케이스: positive +integration **상태 불변조건** -성공 시 모듈 실행은 공개 실행 함수를 통해 애플리케이션을 시작해야 한다. 모듈을 import하는 것만으로 TUI가 시작되어서는 안 된다. 초기화 실패를 정상 시작으로 기록하지 않는다. +성공 시 각 메시지의 라벨과 구조적 클래스는 해당 역할과 일치해야 한다. 메시지 본문, 표시 순서 및 기존 식별자는 변경되지 않아야 한다. 렌더링 실패 시 서로 다른 역할의 라벨이 표시되거나 일부만 표시된 메시지가 남아서는 안 된다. -### REQ-001.03-AC01 — 설치 후 콘솔 명령이 생성되고 실행된다 +### REQ-001.02-AC02 — 기존 응답 선택과 종료 동작을 보존함 **판정 기준** -설치가 완료된 환경에서 chat-tui 명령이 실행 경로에 생성되고 애플리케이션을 시작하면 통과로 판정한다. +유효한 입력 제출 시 기존 응답 목록을 대상으로 표준 random.choice가 한 번 호출되어야 한다. Escape 키 입력은 애플리케이션 종료를 요청해야 하며, 작성자 구분 기능을 추가해도 기존 입력과 응답의 정규화, 내용, 표시 순서 및 입력창 초기화 동작이 유지되어야 한다. **검증** -패키지를 설치한 뒤 chat-tui 명령의 생성 여부와 연결된 실행 대상을 확인하고 명령을 실행하여 Textual 애플리케이션의 초기 상태가 표시되는지 검증한다. +random.choice를 모의 처리하여 기존 응답 목록이 전달되는지 확인한다. Textual 테스트 앱에서 Escape를 입력하고 종료 요청을 확인한 뒤, 두 개의 유효 입력을 제출하여 정규화, 응답 내용, 표시 순서 및 입력창 초기화를 함께 검증한다. **검증 분류** -수준: end-to-end; 백엔드: setuptools console script와 Textual 런타임; 케이스: positive +integration **상태 불변조건** -성공 시 콘솔 명령은 지정된 공개 실행 함수를 호출해야 한다. 명령 생성 과정에서 대화 상태나 사용자 입력이 변경되어서는 안 된다. 설치가 완료되지 않은 환경에서는 명령이 존재한다고 판정하지 않는다. - -### REQ-001.04-AC01 — 기존 승인 기록을 구조적으로 보존한다 - -**판정 기준** - -승인 상태가 approved이고 승인 주체가 spec-agent이며 승인 근거가 승인 댓글 923 및 디스커버리 승인 결과로 명시되어 있으면 통과로 판정한다. - -**검증** - -요구사항 문서의 승인 기록을 검토하여 상태, 주체 및 근거가 기존 기록과 동일하게 보존되었는지 확인한다. - -**검증 분류** - -수준: integration; 백엔드: 요구사항 문서와 승인 이력; 케이스: unchanged-state - -**상태 불변조건** - -기존 승인 상태를 draft로 변경하거나 승인 주체와 근거를 삭제해서는 안 된다. 승인 기록은 프로젝트 스캐폴드 범위 변경과 독립적으로 보존되어야 한다. - -### REQ-001.04-AC02 — 실행되지 않은 검증을 실행 증거로 가장하지 않는다 - -**판정 기준** - -검증을 실제로 실행하지 않은 경우 특정 커밋, 실행 시각 또는 성공 결과를 실행 증거로 기록하지 않고 미기록 또는 미실행 상태로 명확히 표시하면 통과로 판정한다. - -**검증** - -요구사항 문서의 테스트 추적성 계약을 검토하여 실행되지 않은 검증에 임의의 커밋 해시나 성공 결과가 연결되지 않았는지 확인한다. - -**검증 분류** - -수준: integration; 백엔드: 요구사항 추적성 기록; 케이스: unchanged-state - -**상태 불변조건** - -실행 증거는 실제 검증 결과와 일치해야 한다. 검증하지 않은 항목을 PASS로 기록하거나 현재 변경과 무관한 커밋을 실행 증거로 제시해서는 안 된다. +유효 입력 성공 시 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다. 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되어서는 안 된다. 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다. ## 8. 오류 및 충돌 계약 -- 필수 패키징 메타데이터가 누락되거나 유효하지 않으면 설치를 성공으로 판정하지 않아야 하며 원인을 확인할 수 있는 오류를 반환해야 한다. -- 지원하지 않는 Python 버전이나 호환되지 않는 의존성 환경에서는 설치 또는 실행을 정상 동작으로 간주하지 않는다. -- 콘솔 진입점이나 모듈 진입점이 공개 시작 함수를 찾지 못하면 실행은 실패해야 하며 부분적으로 초기화된 애플리케이션을 성공 상태로 남기지 않아야 한다. -- 패키징 설정에 선언되지 않은 외부 연동이나 실행 전제를 자동으로 추가하지 않는다. -- 테스트 의존성 설치 실패는 제품 런타임 의존성의 설치 실패와 구별되어야 한다. -- 설치 또는 실행 실패로 생성된 부분 산출물이나 임시 상태를 정본 실행 상태로 취급하지 않는다. -- 패키징 또는 실행 진입점 변경으로 대화 상호작용 요구사항의 정본 동작이 달라지면 프로젝트 스캐폴드 인수를 충족한 것으로 판정하지 않는다. -- 프로젝트 스캐폴드와 대화 상호작용 사이에 충돌이 발생하면 프로젝트 구조, 패키징 및 실행 기반은 이 문서가 정본이며, 입력·응답·표시·입력창·종료 동작은 대화 상호작용 요구사항이 정본이다. -- 어느 문서도 다른 문서의 범위를 임의로 확장하거나 동일한 기능 규칙과 인수 기준을 중복 정의하지 않는다. +- 입력 오류: 빈 입력과 공백 입력은 오류를 표시하지 않고 무시하며, 응답 선택과 메시지 추가를 수행하지 않는다. +- 상태 충돌: 단일 Textual 이벤트 루프에서 제출 이벤트 순서를 처리하며, 동일 입력을 자동으로 중복 제출하지 않는다. +- 저장 실패: 영속 저장소가 없으므로 저장 실패와 롤백 대상이 없다. 렌더링 실패가 발생하더라도 별도의 부분 영속 기록을 만들지 않는다. +- 역할 오류: 사용자 또는 에이전트로 정의되지 않은 역할은 정상 메시지로 렌더링하지 않으며, 역할 값과 표시 라벨의 매핑은 한 곳의 명시적 기준을 따른다. ## 9. 데이터 및 인터페이스 계약 -- 프로젝트 패키지의 정본 위치는 `src/chat_tui`이며 패키지 검색 기준은 `src`이다. -- 프로젝트 메타데이터는 프로젝트 이름, 버전, 설명, README 위치, 지원 Python 버전 및 Textual 런타임 의존성을 제공해야 한다. -- 테스트 의존성은 별도 선택적 의존성 그룹으로 선언되어야 한다. -- 콘솔 인터페이스는 `chat-tui` 명령에서 `chat_tui.app:main`을 호출해야 한다. -- 모듈 인터페이스는 `python -m chat_tui` 실행 시 패키지의 모듈 진입점에서 동일한 `main` 함수를 호출해야 한다. -- 패키지 공개 버전은 프로젝트 메타데이터의 `0.1.0`과 일치해야 한다. -- 실행 진입점은 외부 프로토콜이나 네트워크 인터페이스로 변환하지 않고 로컬 Textual 애플리케이션을 시작해야 한다. -- 테스트 인터페이스는 표준 unittest 검색 방식으로 저장소 테스트를 실행할 수 있어야 하며 별도의 서비스나 데이터 저장소를 요구하지 않는다. -- 대화 메시지, 사용자 입력, 고정 응답 목록, 역할별 표시, 입력창 상태 및 종료 키의 상세 데이터와 인터페이스 계약은 대화 상호작용 요구사항에서 정의하며 이 문서에서는 재정의하지 않는다. +- 메시지 역할은 문자열 기반 열거형으로 관리하며 사용자 역할의 값은 `user`, 에이전트 역할의 값은 `agent`이다. +- 각 대화 메시지는 필수 역할 값과 필수 본문 문자열을 함께 보유하여 작성자와 내용을 하나의 단위로 표현한다. +- 본문은 앞뒤 공백 제거가 완료된 사용자 입력 또는 선택된 응답을 담는다. +- 역할은 사용자 라벨인 `사용자` 또는 에이전트 라벨인 `에이전트`로 변환할 수 있어야 한다. +- 세션 메시지 목록은 제출 순서를 보유하며 유효한 입력마다 사용자 메시지와 에이전트 응답을 차례로 추가한다. +- 사용자 표시값은 `사용자: 본문` 형식이고 에이전트 표시값은 `에이전트: 본문` 형식이다. +- 사용자 표시 항목은 사용자 메시지 식별자와 사용자 역할 식별자를 포함하고, 에이전트 표시 항목은 응답 메시지 식별자와 에이전트 역할 식별자를 포함한다. +- 제출 입력 기록, 선택 응답 기록 및 기존 고정 응답 목록 계약은 유지한다. +- 식별자는 세션 내 메모리 객체와 CSS 클래스에 한정되며 시간대, 단위 및 정밀도 계약은 없다. ## 10. 하위 호환성 -- 기존의 `chat-tui` 콘솔 실행 방식은 유지되어야 한다. -- 기존의 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다. -- Python 3.11 이상 지원 조건, 프로젝트 이름, 패키지 이름 `chat_tui` 및 공개 버전 `0.1.0` 계약은 유지되어야 한다. -- `src` 기반 패키지 검색과 패키지 공개 버전 노출 방식은 유지되어야 한다. -- 기존 README에 설명된 설치 및 실행 명령은 스캐폴드 정리 이후에도 유효해야 한다. -- 대화 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 대화 상호작용 요구사항의 정본으로 유지하며 이 문서에서 상세히 반복하지 않는다. -- 새 외부 의존성, 외부 연동, 영속성, 배포 방식 또는 실행 환경을 추가하지 않는다. -- 스캐폴드 문서의 변경은 프로젝트 구조, 패키징 및 실행 진입점의 범위를 넘어 대화 상호작용의 의미를 변경해서는 안 된다. -- 대화 상호작용 요구사항은 이 문서의 설치 및 실행 계약을 선행 조건으로 사용하되, 해당 계약을 별도로 복제하거나 변경해서는 안 된다. +- Python 3.11 이상에서 실행되는 기존 패키지와 콘솔 실행 진입점을 유지한다. +- 대화 영역과 입력 위젯의 기존 식별자를 유지한다. +- 사용자 메시지와 에이전트 응답의 표시 항목 구조 및 표시 순서를 유지하되 표시 문자열과 역할 클래스를 통해 작성자 정보를 추가한다. +- Enter 제출, 앞뒤 공백 제거, 공백 입력 무시, 고정 응답 목록 선택, Escape 및 Ctrl+Q 종료 동작을 유지한다. +- 기존 영속 데이터가 없으므로 데이터 마이그레이션은 필요하지 않다. +- 작성자 라벨과 구조적 스타일은 추가하지만 대화 영역 전체 레이아웃을 재설계하지 않는다. +- 외부 API, LLM 연동, 인증, 영속 저장소 및 별도 데이터베이스를 추가하지 않는다. ## 11. 검증 계획 -Python 3.11 이상 환경에서 패키지 설치와 메타데이터 정합성을 검증한다. 소스 디렉터리 기반 패키지 검색, 런타임 의존성, 선택적 테스트 의존성 및 공개 버전이 선언된 계약과 일치하는지 확인한다. 모듈 실행과 콘솔 실행이 동일한 애플리케이션 시작 함수를 호출하는지 확인하고, 기존 저장소 테스트를 실행하여 대화 동작이 변경되지 않았는지 회귀 검증한다. 실행하지 않은 검증은 통과로 간주하지 않는다. +Textual 테스트 앱에서 정상 입력, 여러 메시지의 순서, 메시지 역할 객체, 작성자 라벨과 구조적 CSS 클래스를 검증한다. 입력값의 앞뒤 공백이 제거되는지, 유효한 입력마다 사용자 메시지와 에이전트 응답이 차례로 추가되는지, 기존 메시지가 삭제되거나 재배열되지 않는지 확인한다. -검증 정의는 저장소의 패키징 설정 검토와 표준 unittest 검색을 대상으로 한다. 패키징 메타데이터, 공개 버전 조회, 모듈 실행 경로, 콘솔 실행 경로 및 테스트 검색 결과를 함께 확인한다. 현재 문서 작성 시점에는 검증을 실행하지 않았으므로 특정 커밋에 결합된 실행 증거와 성공 결과를 기록하지 않는다. +빈 문자열과 공백·탭·개행만 포함한 입력을 각각 제출하여 응답 선택이 호출되지 않고 메시지 목록과 대화 영역이 변경되지 않으며 입력창만 비워지는지 검증한다. 응답 선택을 고정하거나 모의 처리하여 정본 응답 목록이 전달되고 선택된 응답이 에이전트 메시지로 표시되는지 확인한다. + +사용자 메시지와 에이전트 응답의 표시 문자열, 역할, 식별자 및 구조적 스타일을 비교하고, 역할별 테두리 또는 정렬 차이가 색상에만 의존하지 않는지 확인한다. Escape와 Ctrl+Q 입력이 동일한 종료 동작을 요청하며 메시지 제출이나 응답 선택을 발생시키지 않는지도 회귀 검증한다. + +실행 가능한 테스트 정의는 별도 테스트 카탈로그에서 관리하고, 요구사항 문서에는 검증 의도와 판정 조건만 기록한다. 실행 결과는 별도 증거 산출물에 기록하며, 실제로 실행하지 않은 검증은 성공으로 기록하지 않는다. 외부 API, 영속성 백엔드 및 데이터베이스를 사용하지 않으므로 저장 후 재조회와 마이그레이션 검증은 해당 없음으로 판정한다. 관련 요구사항과 데이터 모델, 인터페이스 계약 및 실행 흐름 문서의 역할·라벨·스타일·순서 설명이 구현 및 테스트와 일치하는지도 문서 검토로 확인한다. ### 테스트 추적성 계약 @@ -298,11 +256,9 @@ Verifies: - REQ-001.01-AC01 - REQ-001.01-AC02 - REQ-001.02-AC01 -- REQ-001.03-AC01 -- REQ-001.04-AC01 -- REQ-001.04-AC02 -Test reference: pyproject.toml 설정 검토 및 python -m unittest discover -s tests -v -Automated: 기존 패키징 및 실행 진입점 검증 테스트와 대화 동작 회귀 테스트를 사용한다. +- REQ-001.02-AC02 +Test reference: tests/test_app.py의 Textual 애플리케이션 테스트 +Automated: Textual 테스트 앱에서 작성자 역할, 라벨, 구조적 스타일, 입력 정규화, 응답 선택, 표시 순서와 공백 입력 무시 동작을 자동 검증한다. ``` 실행 증거: @@ -310,23 +266,27 @@ Automated: 기존 패키징 및 실행 진입점 검증 테스트와 대화 동 ```text Test ID: TC-001-001 Requirement revision: REQ-001@0.1 -Commit: 검증 커밋 미기록 -Environment: Python 3.11 이상 및 setuptools 기반 설치 환경 +Commit: 실행 증거 미기록 +Environment: Python 3.11 이상, 현재 Textual 테스트 앱, 영속 백엔드 없음 Result: 미실행 Executed at: 검증 실행 시각 미기록 ``` ## 12. 추적성 -근거는 원본 Gitea 이슈의 요구사항 재작업 요청과 저장소의 프로젝트 메타데이터, 패키지 구조, 실행 진입점 선언 및 기존 테스트다. 이 문서는 프로젝트 스캐폴드, 패키징, 모듈 실행과 콘솔 실행 진입점만 추적한다. 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 분리된 대화 상호작용 문서에서만 추적한다. +근거 이슈는 Gitea 이슈 #6인 메시지 표시창의 메시지 작성자 구분 요청이다. 구현 PR은 아직 없으며, 관련 설계 문서는 데이터 모델, 인터페이스 계약, 런타임 흐름 및 프로젝트 구조 문서다. -두 문서는 실행 기반과 대화 동작의 선행 관계만 공유하며 동일한 기능 규칙이나 수용 기준을 반복하지 않는다. 프로젝트 스캐폴드의 승인 이력은 승인 기록에 보존하고, 대화 상호작용의 근거와 검증 연결은 분리된 문서에서 관리한다. +이 문서는 대화 메시지의 역할과 본문을 정본으로 삼고, 사용자와 에이전트의 라벨·식별자·구조적 스타일 및 표시 순서를 구현과 테스트에서 일관되게 추적한다. 입력 정규화, 고정 응답 선택, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 계약으로 보존하며 작성자 구분을 위해 의미를 변경하지 않는다. + +역할은 CSS 클래스나 화면 색상에서 추론하지 않고 명시적인 메시지 데이터에서 확인해야 한다. 테스트는 메시지 역할과 본문, 렌더링 라벨과 클래스, 표시 순서 및 기존 동작의 보존 여부를 함께 비교하며, 실행 결과와 커밋 결합 정보는 별도 증거 산출물에서 관리한다. ## 13. 확정된 결정 -기존 프로젝트 스캐폴드의 의미와 승인 이력을 보존하고, 혼재되어 있던 대화 상호작용 요구사항과 수용 기준은 별도 문서로 분리한다. 이 문서의 정본 범위는 패키지 구조, 패키징 메타데이터와 두 실행 진입점으로 한정한다. +사용자 메시지와 에이전트 응답은 명시적인 작성자 역할과 본문을 함께 가진 대화 메시지로 관리한다. 사용자 역할은 user이고 에이전트 역할은 agent이며, 화면의 라벨과 구조적 스타일은 이 역할에서 파생한다. -애플리케이션 코드, 테스트 동작, 고정 응답 문구, 입력 처리 순서, 사용자 인터페이스 동작, 외부 연동, 의존성, 배포 환경은 변경하지 않는다. 대화 동작의 상세 규칙과 수용 기준은 분리된 문서에서 단일 정본으로 관리한다. +사용자 메시지는 사용자 라벨과 사용자 식별자를 사용하고 에이전트 응답은 에이전트 라벨과 응답 식별자를 사용한다. 역할 구분은 색상에만 의존하지 않으며 역할별 테두리 또는 정렬 차이를 포함한다. + +유효한 입력의 앞뒤 공백 제거, 고정 응답 목록에서의 표준 난수 선택, 사용자 메시지 뒤에 에이전트 응답을 표시하는 순서, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 의미를 유지한다. 외부 API, LLM, 인증, 영속 저장소 및 데이터베이스는 추가하지 않는다. ## 14. 미결 사항 @@ -334,8 +294,6 @@ Executed at: 검증 실행 시각 미기록 ## 15. 승인 기록 -상태: approved -승인 주체: spec-agent -승인 근거: 승인 댓글 923 및 디스커버리 승인 결과 +이 요구사항은 approved 상태로 승인되었다. 승인 주체는 spec-agent이며, 승인 근거는 승인 댓글 923 및 디스커버리 승인 결과다. -기존 프로젝트 스캐폴드의 승인 상태와 승인 근거는 유지한다. 이번 문서 정리는 승인 상태를 초안으로 되돌리지 않으며, 승인된 프로젝트 스캐폴드 범위와 기존 승인 이력을 보존한 채 대화 상호작용을 별도 요구사항 문서로 분리한 변경만 추적한다. +작성자 구분을 명시적인 메시지 역할과 역할에서 파생되는 라벨 및 구조적 스타일로 관리하는 범위는 승인된 정본의 의미로 보존한다. 문서 정리나 관련 문서와의 정합성 검토만으로 승인 상태, 승인 주체 또는 승인 근거를 변경하지 않는다. diff --git a/docs/requirements/req-002_conversation-interaction.md b/docs/requirements/req-002_conversation-interaction.md index 73ccac4..92754a5 100644 --- a/docs/requirements/req-002_conversation-interaction.md +++ b/docs/requirements/req-002_conversation-interaction.md @@ -22,27 +22,43 @@ ## 1. 목적 -이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 제출한 입력을 정규화하고, 유효한 메시지와 고정 응답을 세션 내 대화 영역에 제출 순서대로 누적 표시하는 동작을 정의한다. 입력의 양끝 공백은 제거하며, 비어 있거나 공백만 포함한 입력은 대화 상태와 응답 선택을 변경하지 않고 무시한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비운다. +이 요구사항은 Textual 기반 대화형 TUI에서 사용자가 제출한 입력을 정규화하고, 유효한 사용자 메시지와 고정 응답을 세션 내 대화 영역에 제출 순서대로 누적 표시하는 동작을 정의한다. 입력의 양끝 공백은 제거하고, 빈 문자열이나 공백만 포함한 입력은 응답 선택과 대화 상태 변경 없이 무시한다. 유효하거나 무효인 제출이 끝나면 입력창을 비운다. -사용자 메시지와 에이전트 응답은 각각 명시적인 역할, 라벨 및 구조적 스타일로 구분한다. 유효한 입력마다 사전에 정의된 다섯 개의 고정 응답 중 하나를 표준 난수 방식으로 선택하고, 사용자 메시지 바로 뒤에 에이전트 응답을 표시한다. Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청해야 한다. 이 대화 동작은 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 원본 Gitea 이슈 #8의 재작업 범위에서 관리한다. +사용자 메시지와 에이전트 응답은 명시적인 역할, 라벨 및 구조적 스타일로 구분한다. 유효한 입력마다 정본으로 정의된 고정 응답 목록에서 하나를 표준 난수 방식으로 선택하며, 사용자 메시지 바로 뒤에 에이전트 응답을 표시한다. Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청한다. 프로젝트 설치와 실행 진입점은 선행 프로젝트 스캐폴드 요구사항을 따르며, 이 문서는 대화 상호작용의 의미와 검증 기준만 관리한다. ## 2. 배경 -애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 문자열을 작성하고 Enter로 제출하며, 시스템은 입력 양끝의 공백을 제거한 뒤 정규화 결과의 유효성을 판단한다. 유효한 입력에는 사전에 정의된 다섯 개의 고정 응답 중 하나를 연결하고, 사용자 메시지와 에이전트 응답을 제출 순서대로 표시한다. +애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI로 제공된다. 사용자는 입력창에 문자열을 작성하고 Enter로 제출한다. 시스템은 제출된 문자열의 양끝 공백을 제거한 뒤 유효성을 판단하고, 유효한 입력에 대해서만 사용자 메시지와 고정 응답을 생성하여 표시한다. -메시지와 응답은 실행 중인 세션의 메모리 상태로만 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소는 사용하지 않는다. 프로젝트 설치와 실행 진입점은 REQ-001의 계약을 따르며, 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작의 상세 규칙과 수용 기준은 이 문서에서 단일 정본으로 관리한다. 근거는 원본 Gitea 이슈 #8이다. +메시지와 응답은 실행 중인 세션의 메모리 상태로만 관리한다. 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소는 사용하지 않는다. 프로젝트 패키징과 실행 진입점은 선행 프로젝트 스캐폴드 요구사항에서 관리하며, 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 이 문서에서 단일 정본으로 관리한다. 근거는 원본 Gitea 이슈 8의 요구사항 재작업 요청이다. ## 3. 범위 -포함 범위는 입력 양끝의 공백 제거와 유효 입력 판정, 유효한 사용자 메시지와 고정 응답의 세션 내 누적, 표준 난수 방식의 응답 선택, 사용자 메시지 뒤에 응답을 배치하는 순서 보장, 사용자와 에이전트의 라벨 및 구조적 스타일 구분, 빈 입력과 공백 입력의 무시, 제출 후 입력창 초기화, Escape 및 Ctrl+Q 종료 요청이다. REQ-001과의 의존 관계 및 Gitea 이슈 #8 추적성도 포함한다. +포함 범위는 다음과 같다. -사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 표시, 응답 선택 순서, 역할별 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작을 정본 범위로 관리한다. 프로젝트 패키징, 설치 설정 및 실행 진입점 자체의 변경은 포함하지 않는다. +- 입력 양끝의 공백 제거와 정규화 결과에 따른 유효 입력 판정 +- 유효한 사용자 메시지와 고정 응답의 세션 내 누적 및 표시 +- 정본 고정 응답 목록을 대상으로 하는 표준 난수 선택 +- 사용자 메시지 뒤에 에이전트 응답을 배치하는 순서 보장 +- 사용자와 에이전트의 역할, 라벨 및 구조적 스타일 구분 +- 빈 문자열, 공백, 탭 또는 줄바꿈만 포함한 입력의 무시 +- 유효하거나 무효인 제출 후 입력창 초기화 +- Escape와 Ctrl+Q에 의한 동일한 종료 요청 +- 선행 프로젝트 스캐폴드 요구사항과의 의존 관계 및 원본 이슈 8 추적성 -고정 응답 문구, 입력 처리 순서와 사용자 인터페이스의 의미는 변경하지 않는다. 외부 API, LLM, 네트워크 서비스, 데이터베이스, 영속 저장소, 인증, 권한 관리, 다중 세션, 메시지 복원, 새 의존성, 배포 방식 또는 실행 환경의 추가도 제외한다. +제외 범위는 다음과 같다. + +- 프로젝트 패키징, 설치 설정 및 실행 진입점 자체의 변경 +- 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소 연동 +- 사용자 인증, 권한 관리, 다중 세션, 메시지 복원 또는 대화 저장 +- 고정 응답 문구, 입력 처리 순서와 기존 사용자 인터페이스 의미의 변경 +- 새로운 의존성, 배포 방식 또는 실행 환경의 추가 + +프로젝트 구조, 패키징 메타데이터와 실행 기반은 선행 프로젝트 스캐폴드 요구사항을 정본으로 사용하며 이 문서에서 중복 정의하지 않는다. ### 포함 -사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 세션 내 누적 및 표시, 표준 난수 방식의 응답 선택, 사용자와 에이전트의 역할별 표시, 빈 입력 무시, 제출 후 입력창 초기화, Escape와 Ctrl+Q 종료 요청 및 REQ-001 의존 관계와 Gitea 이슈 #8 추적성을 포함한다. +사용자 입력의 양끝 공백 제거와 유효성 판정, 유효 메시지와 고정 응답의 세션 내 누적 및 표시, 표준 난수 방식의 응답 선택, 사용자와 에이전트의 역할별 표시, 빈 입력 무시, 제출 후 입력창 초기화, Escape와 Ctrl+Q 종료 요청 및 선행 프로젝트 스캐폴드와의 의존 관계와 원본 이슈 추적성을 포함한다. ### 제외 @@ -50,9 +66,9 @@ ## 4. 용어와 기준 -입력은 사용자가 입력창에서 제출한 문자열이고, 정규화는 문자열 양끝의 공백을 제거하는 처리다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. 문자열 내부의 공백은 제거하거나 변환하지 않는다. +입력은 사용자가 입력창에서 제출한 문자열이다. 정규화는 문자열 양끝의 공백을 제거하는 처리이며 문자열 내부의 공백은 변경하지 않는다. 정규화 결과가 빈 문자열이면 유효하지 않은 입력으로 판단한다. -유효한 제출은 정규화된 사용자 메시지와 고정 응답 목록에서 선택된 에이전트 응답으로 구성된다. 사용자 메시지는 사용자 역할과 사용자 라벨을 가지며, 응답은 에이전트 역할과 에이전트 라벨을 가진다. 각 역할의 표시는 서로 다른 구조적 스타일을 사용하고, 역할과 본문은 세션 메시지의 정본 상태로 함께 보존한다. +유효한 제출은 정규화된 사용자 메시지와 고정 응답 목록에서 선택된 에이전트 응답으로 구성된다. 사용자 메시지는 사용자 역할과 사용자 라벨을 갖고, 응답은 에이전트 역할과 에이전트 라벨을 갖는다. 역할과 본문은 세션 메시지의 정본 상태이며, 라벨과 구조적 스타일은 이 역할에서 파생한다. 고정 응답 목록은 다음 다섯 문구로 구성한다. @@ -62,191 +78,196 @@ - 지금 처리 중입니다. - 작업을 완료하였습니다. -유효한 입력마다 목록 전체를 대상으로 표준 난수 선택을 한 번 수행한다. 선택된 응답은 해당 사용자 메시지 바로 뒤에 배치한다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며, 종료 과정에서 외부 상태나 영속 데이터를 생성하지 않는다. +유효한 입력마다 목록 전체를 대상으로 표준 난수 선택을 한 번 수행한다. 선택된 응답은 대응하는 사용자 메시지 바로 뒤에 배치한다. 종료 요청은 Escape 또는 Ctrl+Q 입력으로 발생하며, 종료 과정에서 외부 상태나 영속 데이터를 생성하지 않는다. + +선행 프로젝트 스캐폴드 요구사항은 프로젝트 구조, 패키징 및 실행 진입점의 정본이다. 이 문서는 해당 실행 기반에 의존하지만 그 계약을 재정의하거나 대화 기능과 패키징 기능을 하나의 요구사항 정체성으로 합치지 않는다. ## 5. 요구사항 -시스템은 입력 제출 시 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. 정규화 결과가 비어 있지 않을 때만 사용자 메시지를 세션 상태와 화면에 기록해야 하며, 빈 문자열이나 공백·탭·줄바꿈만 포함한 입력은 응답 선택과 메시지 추가 없이 무시해야 한다. +시스템은 입력 제출 시 입력 양끝의 공백을 제거한 값을 처리 대상으로 사용해야 한다. 정규화 결과가 비어 있지 않을 때만 사용자 메시지를 세션 상태와 화면에 기록해야 하며, 빈 문자열이나 공백·탭·줄바꿈만 포함한 입력은 응답 선택과 메시지 추가 없이 무시해야 한다. 이 동작은 입력 위젯의 제출 이벤트, 대화 표시 흐름 및 관련 경계 테스트에 영향을 준다. -유효한 입력마다 고정된 다섯 개 응답 목록 전체에서 표준 난수 방식으로 응답 하나를 선택해야 한다. 사용자 메시지는 사용자 역할과 사용자 라벨로 표시하고, 선택된 응답은 에이전트 역할과 에이전트 라벨로 표시해야 한다. 사용자 메시지는 대응하는 에이전트 응답보다 먼저 표시되어야 하며 두 항목은 인접한 순서를 유지해야 한다. 여러 입력을 제출해도 이전 대화 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적해야 한다. +유효한 입력마다 정본으로 정의된 다섯 개 응답 목록 전체에서 표준 난수 방식으로 응답 하나를 선택해야 한다. 정규화된 사용자 메시지를 사용자 역할로 먼저 추가하고 선택된 응답을 에이전트 역할로 바로 뒤에 추가해야 하며, 여러 입력을 제출해도 기존 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적해야 한다. 이 동작은 세션 대화 상태, 대화 영역의 표시 순서, 응답 선택 기록 및 회귀 테스트에 영향을 준다. -유효하거나 무효인 입력 제출이 발생하면 입력창은 빈 문자열로 초기화되어야 한다. 역할별 라벨과 구조적 스타일은 메시지 역할에서 일관되게 파생해야 하며 스타일만으로 역할을 판단해서는 안 된다. Escape와 Ctrl+Q 입력은 동일한 애플리케이션 종료 동작을 요청해야 하고, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. +유효하거나 무효인 제출이 발생하면 입력창을 빈 문자열로 초기화해야 한다. 입력창 초기화는 메시지 처리의 성공 여부와 독립적으로 수행되어야 하며, 초기화 뒤 다음 입력을 받을 수 있어야 한다. 이미 기록된 메시지와 응답은 입력창 초기화로 삭제되거나 변경되지 않아야 한다. -대화 처리는 외부 API, LLM, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 프로젝트 스캐폴드와 실행 진입점의 의미를 변경하지 않고 REQ-001이 제공하는 실행 환경에서 동작해야 하며, 이 문서의 상세 대화 규칙과 수용 기준은 프로젝트 스캐폴드 요구사항에서 중복 정의하지 않는다. +각 대화 메시지는 사용자 또는 에이전트 역할을 명시적으로 보유해야 한다. 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로, 고정 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시해야 한다. 라벨과 스타일은 본문 문자열이나 색상만으로 결정하지 않고 메시지 역할에서 일관되게 파생해야 한다. + +사용자가 Escape 또는 Ctrl+Q를 입력하면 현재 Textual 애플리케이션의 동일한 종료 동작을 요청해야 한다. 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 되며, 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. + +대화 처리는 선행 프로젝트 스캐폴드 요구사항이 제공하는 설치 및 실행 환경에서 동작해야 한다. 프로젝트 구조, 패키징 메타데이터와 실행 진입점은 선행 요구사항에서만 관리하고, 입력 정규화와 대화 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화 및 종료 동작은 이 문서에서만 정본으로 관리하여 두 문서 사이의 기능 규칙과 인수 기준 중복을 방지해야 한다. ### REQ-002.01 — 입력 정규화와 유효 입력 판정 -사용자가 입력창에서 문자열을 제출하면 시스템은 문자열 양끝의 공백을 제거한 값을 정규화된 입력으로 사용해야 한다. 정규화 결과가 하나 이상의 문자를 포함하면 유효한 사용자 메시지로 처리하고, 결과가 빈 문자열이면 유효한 메시지로 처리하지 않아야 한다. 공백, 탭 또는 줄바꿈만 포함한 입력은 응답 선택이나 대화 항목 추가 없이 무시해야 한다. +시스템은 입력창에 제출된 문자열의 양끝 공백을 제거한 값을 정규화된 입력으로 사용해야 한다. 정규화 결과가 비어 있지 않으면 이를 유효한 사용자 메시지로 처리하고, 빈 문자열이나 공백·탭·줄바꿈만 포함한 입력은 유효한 메시지로 처리하지 않아야 한다. 무효 입력에서는 응답을 선택하거나 대화 항목을 추가하지 않아야 하며, 문자열 내부의 공백은 변경하지 않아야 한다. **영향 범위** -인터페이스: 입력 위젯의 제출 이벤트와 대화 표시 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 대화 상태를 검증하는 테스트. 마이그레이션: 필요 없음. 호환성: 기존의 양끝 공백 제거와 빈 입력 무시 동작을 유지한다. 배포 전제 조건: 선행 프로젝트 스캐폴드가 제공하는 Textual 실행 환경이 필요하다. +입력 위젯의 제출 이벤트, 대화 상태와 화면 표시 흐름에 영향을 준다. 영속성은 없으며 메시지는 실행 중인 세션 메모리에만 유지한다. 후속 사용 주체는 TUI 사용자와 대화 상태를 검증하는 자동 테스트다. 마이그레이션은 필요하지 않으며, REQ-001이 제공하는 Textual 실행 환경을 전제로 한다. -### REQ-002.02 — 유효 메시지와 고정 응답을 순서대로 누적한다 +### REQ-002.02 — 유효 메시지와 고정 응답을 제출 순서대로 누적한다 -유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 사용자 역할로 먼저 대화 상태와 대화 영역에 추가해야 한다. 이어서 고정된 다섯 개 응답 목록 전체를 표준 난수 선택 기능에 전달하여 응답 하나를 선택하고, 선택된 응답을 에이전트 역할로 사용자 메시지 바로 뒤에 추가해야 한다. 고정 응답 목록은 안녕하세요! 무엇을 도와드릴까요?, 그것은 제가 처리하기 불가능합니다., 맡겨만 주세요., 지금 처리 중입니다., 작업을 완료하였습니다.로 구성한다. 여러 입력을 제출하면 각 사용자 메시지와 응답 쌍을 기존 순서 뒤에 누적해야 한다. +유효한 입력이 제출되면 시스템은 정규화된 사용자 메시지를 사용자 역할로 먼저 대화 상태와 화면에 추가해야 한다. 이어서 다음 다섯 개의 고정 응답 목록 전체를 대상으로 표준 난수 선택을 한 번 수행하고, 선택된 응답을 에이전트 역할로 사용자 메시지 바로 뒤에 추가해야 한다: 안녕하세요! 무엇을 도와드릴까요?, 그것은 제가 처리하기 불가능합니다., 맡겨만 주세요., 지금 처리 중입니다., 작업을 완료하였습니다. 여러 입력을 제출하면 기존 항목을 삭제하거나 재배열하지 않고 각 메시지 쌍을 제출 순서대로 누적해야 한다. **영향 범위** -인터페이스: 대화 영역의 메시지 순서, 본문 및 작성자 역할 표시 계약에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, TUI 렌더링 계층 및 회귀 테스트. 마이그레이션: 필요 없음. 호환성: 기존 고정 응답 문구와 표준 난수 선택 방식을 유지한다. 배포 전제 조건: Textual 대화 영역과 Python 표준 난수 기능을 사용할 수 있어야 한다. +세션 대화 상태, 대화 영역의 메시지 본문·역할·순서와 고정 응답 선택 흐름에 영향을 준다. 영속성은 없으며 사용자, Textual 렌더링 계층과 회귀 테스트가 후속 사용 주체다. 마이그레이션은 필요하지 않고 기존 고정 응답 문구와 표준 난수 선택 방식을 유지한다. ### REQ-002.03 — 제출 후 입력창을 초기화한다 -입력 제출 이벤트가 발생하면 시스템은 제출된 값이 유효한지와 관계없이 입력 위젯의 값을 빈 문자열로 초기화해야 한다. 입력창 초기화는 유효한 메시지 처리와 독립적으로 수행되어야 하며, 초기화 이후 사용자가 다음 입력을 제출할 수 있어야 한다. +입력 제출 이벤트가 발생하면 시스템은 제출된 값의 유효성이나 처리 결과와 관계없이 입력 위젯의 값을 빈 문자열로 초기화해야 한다. 입력창 초기화는 유효한 메시지 처리와 독립적으로 수행되어야 하며, 초기화가 끝난 뒤 사용자가 다음 입력을 제출할 수 있어야 한다. **영향 범위** -인터페이스: 입력 위젯의 값과 연속 입력 흐름에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: TUI 사용자와 입력 이벤트 테스트. 마이그레이션: 필요 없음. 호환성: 유효 입력과 무효 입력 제출 후 입력창을 비우는 기존 동작을 유지한다. 배포 전제 조건: Textual 입력 위젯을 제출 이벤트에서 갱신할 수 있어야 한다. +Textual 입력 위젯의 값과 연속 입력 흐름에 영향을 준다. 영속성은 없으며 TUI 사용자와 입력 이벤트 테스트가 후속 사용 주체다. 마이그레이션은 필요하지 않고 유효·무효 입력 제출 후 입력창을 비우는 기존 동작을 유지한다. -### REQ-002.04 — 역할 기반 메시지 표시를 유지한다 +### REQ-002.04 — 메시지 역할에 따라 라벨과 구조적 스타일을 표시한다 -시스템은 각 대화 메시지에 사용자 또는 에이전트의 작성자 역할을 명시적으로 보유해야 한다. 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로 표시하고, 고정 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시해야 한다. 라벨과 스타일은 임의의 본문 문자열이나 색상만으로 결정하지 않고 메시지 역할에서 일관되게 파생해야 한다. +시스템은 각 대화 메시지에 사용자 또는 에이전트의 명시적인 역할을 보유하게 해야 한다. 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로 표시하고, 고정 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시해야 한다. 라벨과 스타일은 본문 문자열이나 색상만으로 결정하지 않고 메시지 역할에서 일관되게 파생해야 한다. **영향 범위** -인터페이스: 대화 영역의 라벨, 스타일 식별자와 시각적 역할 구분에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 화면 검수자 및 렌더링 테스트. 마이그레이션: 필요 없음. 호환성: 기존 사용자와 에이전트 역할 구분 및 표시 순서를 유지한다. 배포 전제 조건: Textual Label과 CSS 스타일 처리를 사용할 수 있어야 한다. +대화 영역의 메시지 모델, 표시 문자열, 역할별 식별자와 구조적 스타일에 영향을 준다. 영속성은 없으며 사용자, 화면 검수자와 렌더링 테스트가 후속 사용 주체다. 마이그레이션은 필요하지 않고 기존 사용자·에이전트 표시 순서와 역할 구분 의미를 유지한다. -### REQ-002.05 — 종료 단축키로 애플리케이션 종료를 요청한다 +### REQ-002.05 — 종료 단축키로 동일한 애플리케이션 종료를 요청한다 -사용자가 Escape 또는 Ctrl+Q를 입력하면 시스템은 현재 Textual 애플리케이션의 종료 동작을 요청해야 한다. 두 단축키는 동일한 종료 경로를 사용해야 하며, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. 이 요구사항은 원본 Gitea 이슈 8의 대화 상호작용 재작업 범위를 추적한다. +사용자가 Escape 또는 Ctrl+Q를 입력하면 시스템은 현재 Textual 애플리케이션의 종료 동작을 요청해야 한다. 두 단축키는 동일한 종료 경로를 사용해야 하며, 종료 입력은 메시지 제출이나 응답 선택으로 해석되어서는 안 된다. 종료 과정에서 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 호출하지 않아야 한다. **영향 범위** -인터페이스: TUI 키 바인딩과 애플리케이션 생명 주기에 영향을 준다. 영속성: 영향 없음. 후속 사용 주체: 사용자, 운영자 및 종료 회귀 테스트. 마이그레이션: 필요 없음. 호환성: Escape와 Ctrl+Q 종료 방식을 유지한다. 배포 전제 조건: 선행 프로젝트 스캐폴드의 Textual 애플리케이션 실행 계약이 충족되어야 한다. +Textual 키 바인딩과 애플리케이션 생명 주기에 영향을 준다. 영속성은 없으며 사용자, 운영자와 종료 회귀 테스트가 후속 사용 주체다. 마이그레이션은 필요하지 않고 기존 Escape 및 Ctrl+Q 종료 방식을 유지한다. REQ-001의 선행 실행 계약이 충족되어야 한다. ## 6. 제약과 불변조건 -- 입력은 제출 시 문자열 양끝의 공백을 제거한 값으로 정규화한다. -- 정규화 결과가 빈 문자열이면 응답 선택, 메시지 목록 변경 및 새 화면 항목 추가를 수행하지 않는다. -- 유효한 입력은 사용자 메시지를 먼저 추가하고, 고정 응답 목록에서 선택한 에이전트 응답을 바로 뒤에 추가한다. -- 고정 응답은 정본으로 정의된 다섯 문장 중 표준 난수 선택으로 하나를 결정한다. -- 여러 제출의 메시지와 응답은 기존 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적한다. -- 사용자와 에이전트의 역할, 라벨 및 구조적 스타일은 메시지 역할에서 일관되게 파생한다. -- 유효 입력과 무효 입력 모두 제출 후 입력창을 빈 문자열로 초기화한다. -- 무효 입력을 처리해도 기존 대화 상태와 응답 선택 상태는 변경하지 않는다. -- Escape와 Ctrl+Q는 동일한 애플리케이션 종료 요청 경로를 사용하며, 종료 입력으로 새 메시지나 응답을 추가하지 않는다. -- 메시지와 응답은 현재 실행 세션의 메모리에만 보관하며 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 사용하지 않는다. -- 프로젝트 설치, 패키징 및 실행 진입점 계약은 REQ-001을 따르며 이 문서에서 변경하거나 중복 정의하지 않는다. -- 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 도입하지 않는다. +- 입력은 제출 시 문자열의 양끝 공백을 제거한 값으로 정규화하며, 문자열 내부의 공백은 변경하지 않는다. +- 정규화 결과가 빈 문자열이면 사용자 메시지와 에이전트 응답을 추가하지 않고 고정 응답 선택도 수행하지 않는다. +- 유효한 입력 하나는 정규화된 사용자 메시지와 고정 응답 하나로 구성되며, 사용자 메시지가 먼저 기록되고 응답이 바로 뒤따라야 한다. +- 여러 입력의 메시지 쌍은 기존 항목을 삭제하거나 재배열하지 않고 제출 순서대로 누적한다. +- 고정 응답은 정본으로 정의된 다섯 문구 중 표준 난수 선택으로 하나를 결정한다. +- 유효 입력과 무효 입력 모두 제출이 끝나면 입력창을 빈 문자열로 초기화한다. +- 메시지의 역할, 라벨 및 구조적 스타일은 명시적인 역할 값에서 파생하며 본문 내용이나 색상만으로 역할을 판정하지 않는다. +- 사용자 메시지와 에이전트 응답은 각각 사용자 또는 에이전트 역할과 비어 있지 않은 본문을 함께 보유한다. +- Escape와 Ctrl+Q는 동일한 종료 요청 경로를 사용하며, 종료 입력은 메시지 제출이나 응답 선택으로 처리하지 않는다. +- 메시지와 응답은 현재 실행 세션의 메모리에만 보관하고 외부 API, 네트워크 서비스, 데이터베이스 또는 영속 저장소를 사용하지 않는다. +- 프로젝트의 설치, 패키징 및 실행 기반은 선행 프로젝트 스캐폴드 요구사항을 따르며 이 문서에서 그 계약을 재정의하지 않는다. +- 새로운 외부 연동, 의존성, 배포 방식 또는 실행 환경을 추가하지 않는다. ## 7. 인수 기준 -- 양끝에 공백이 포함된 유효한 입력을 제출하면 공백이 제거된 본문만 사용자 메시지로 대화 상태와 화면에 기록되어야 한다. -- 유효한 입력마다 사용자 메시지 하나와 고정 응답 하나가 생성되어야 하며, 사용자 메시지가 응답보다 먼저 인접한 순서로 표시되어야 한다. -- 선택된 응답은 정본으로 정의된 다섯 개의 고정 응답 중 하나여야 하며 표준 난수 선택 절차가 사용되어야 한다. -- 여러 입력을 연속 제출하면 각 사용자 메시지와 응답 쌍이 제출 순서대로 누적되어야 한다. -- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로, 에이전트 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시되어야 한다. -- 유효한 입력을 제출한 뒤 입력창 값은 빈 문자열이어야 하며, 이미 기록된 메시지는 변경되지 않아야 한다. -- 빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 입력을 제출하면 메시지 목록, 제출 입력 기록, 응답 선택 기록 및 화면 항목이 변경되지 않아야 한다. -- 무효 입력을 제출한 뒤에도 입력창은 빈 문자열이어야 한다. -- Escape를 누르면 애플리케이션 종료 요청이 발생해야 하며 메시지 제출이나 응답 선택이 발생하지 않아야 한다. -- Ctrl+Q를 누르면 Escape와 동일한 종료 동작이 발생해야 한다. -- 종료 단축키 처리 후에는 새 대화 메시지나 입력 처리 기록이 생성되지 않아야 한다. -- 대화 기능은 REQ-001의 설치 및 실행 기반에서 동작해야 하며, 패키징과 실행 진입점의 상세 기준을 중복 판정하지 않는다. +- 양끝에 공백이 포함된 유효한 문자열을 제출하면 대화 상태와 화면에는 공백이 제거된 본문만 사용자 메시지로 기록되어야 한다. 검증은 Textual 테스트 앱에서 입력값과 저장된 메시지 및 표시값을 비교하는 방식으로 수행하며, 원본 양끝 공백이 후속 처리에 사용되지 않는지 확인한다. +- 빈 문자열과 공백, 탭, 줄바꿈만 포함한 값을 제출하면 메시지 목록, 응답 선택 기록 및 대화 영역 항목 수가 변하지 않아야 한다. 각 경계 입력을 제출하고 선택 함수가 호출되지 않았는지와 부분 메시지가 남지 않았는지를 확인한다. +- 유효한 입력마다 사용자 메시지 하나와 고정 응답 하나가 생성되고 두 항목이 인접한 순서로 표시되어야 한다. 선택 결과를 고정한 뒤 세션 메시지 목록과 화면의 전체 순서를 비교하여 사용자 역할과 에이전트 역할이 뒤바뀌지 않았는지 검증한다. +- 고정 응답 선택은 정본으로 정의된 다섯 문구 전체를 대상으로 유효 입력마다 한 번 수행되어야 한다. 선택 함수의 호출 인자와 호출 횟수를 감시하고, 반환된 값이 상태와 화면에 동일하게 반영되는지 확인한다. +- 두 개 이상의 유효 입력을 순서대로 제출하면 각 사용자 메시지와 응답 쌍이 기존 대화 뒤에 누적되어야 한다. 이전 항목의 삭제, 재배열, 중복 추가가 없는지 제출 기록과 메시지 목록을 함께 비교한다. +- 유효한 입력을 제출한 뒤 입력창 값은 빈 문자열이어야 하며 이미 기록된 메시지와 응답은 변경되지 않아야 한다. 양끝 공백을 포함한 입력을 사용하여 입력 위젯과 세션 상태를 함께 확인한다. +- 무효 입력을 제출한 뒤에도 입력창은 빈 문자열이어야 하며 기존 대화 상태와 화면은 그대로 유지되어야 한다. 빈 입력과 공백 입력을 각각 제출하여 입력창 초기화와 변경 없음 조건을 함께 검증한다. +- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일을, 에이전트 응답은 에이전트 라벨과 에이전트용 구조적 스타일을 사용해야 한다. 렌더링 문자열, 역할 값, 스타일 식별자 및 역할별 구조 규칙을 서로 대조한다. +- Escape와 Ctrl+Q는 각각 애플리케이션 종료를 정확히 한 번 요청하고 메시지 제출이나 응답 선택을 발생시키지 않아야 한다. 두 키를 별도로 입력하여 동일한 종료 경로와 상태 불변조건을 확인한다. +- 대화 기능은 선행 프로젝트 스캐폴드의 설치 및 실행 환경에서 동작해야 하며, 패키징과 실행 진입점의 상세 기준을 중복 판정하지 않는다. 설치 환경을 준비한 뒤 대화 회귀 검증을 수행한다. +- 실행하지 않은 검증은 성공 결과나 특정 커밋의 실행 증거로 기록하지 않으며, 테스트 정의와 실제 실행 결과를 별도로 관리한다. -### REQ-002.01-AC01 — 양끝 공백을 제거하여 유효 입력을 처리한다 +### REQ-002.01-AC01 — 양끝 공백이 제거된 입력을 처리한다 **판정 기준** -양끝에 공백이 포함된 유효 입력을 제출했을 때 대화 상태와 화면에 공백이 제거된 본문만 사용자 메시지로 기록되면 통과로 판정한다. +양끝에 공백이 포함된 유효한 입력을 제출했을 때 대화 상태와 화면에 공백이 제거된 본문만 사용자 메시지로 기록되면 통과로 판정한다. **검증** -Textual 테스트에서 양끝 공백이 포함된 입력을 제출하고 제출된 입력, 메시지 본문 및 화면 표시값을 비교한다. +Textual 테스트 앱에서 양끝 공백이 포함된 입력을 제출하고 제출 기록, 메시지 본문과 화면 표시값을 비교한다. 문자열 내부 공백은 그대로 유지되는지도 확인한다. **검증 분류** -수준: integration; 백엔드: Textual 입력 이벤트와 대화 상태; 케이스: positive +integration **상태 불변조건** -성공 시 정규화된 본문만 사용자 메시지로 기록되어야 하며 원본의 양끝 공백은 표시되거나 후속 처리에 사용되지 않아야 한다. +성공 후 사용자 메시지에는 정규화된 본문만 존재해야 하며 원본 양끝 공백은 화면이나 후속 응답 처리에 사용되지 않아야 한다. ### REQ-002.01-AC02 — 빈 입력과 공백 입력을 무시한다 **판정 기준** -빈 문자열 또는 공백, 탭, 줄바꿈만 포함한 값을 제출해도 응답 선택과 메시지 추가 및 새 화면 항목 생성이 발생하지 않으면 통과로 판정한다. +빈 문자열 또는 공백·탭·줄바꿈만 포함한 입력을 제출해도 응답 선택, 메시지 추가와 새 화면 항목 생성이 발생하지 않으면 통과로 판정한다. **검증** -각 경계 입력을 제출하고 메시지 목록, 응답 선택 기록 및 대화 영역 항목 수를 확인하며 응답 선택 함수가 호출되지 않았는지 검증한다. +경계 입력을 각각 제출하고 메시지 목록, 응답 선택 기록과 대화 영역 항목 수를 비교한다. 응답 선택 함수가 호출되지 않았는지도 확인한다. **검증 분류** -수준: integration; 백엔드: Textual 입력 이벤트와 응답 선택 경계; 케이스: boundary +integration **상태 불변조건** -무효 입력 처리 후 기존 대화 상태와 화면은 변경되지 않아야 하며 부분 사용자 메시지나 응답이 남아서는 안 된다. +무효 입력 처리 후 기존 대화 상태와 화면은 변경되지 않아야 하며 부분적인 사용자 메시지나 응답이 남아서는 안 된다. ### REQ-002.02-AC01 — 사용자 메시지 뒤에 고정 응답을 표시한다 **판정 기준** -유효 입력 하나를 제출했을 때 정규화된 사용자 메시지와 고정 목록에서 선택된 응답이 인접한 순서로 표시되고 각각 사용자와 에이전트 역할로 구분되면 통과로 판정한다. +유효한 입력 하나를 제출했을 때 정규화된 사용자 메시지와 고정 목록에서 선택된 응답이 인접한 순서로 표시되고 각각 사용자와 에이전트 역할을 가지면 통과로 판정한다. **검증** -응답 선택 결과를 고정한 상태에서 입력을 제출하고 내부 메시지 목록과 대화 영역의 전체 순서를 확인한다. +응답 선택 결과를 고정한 Textual 테스트에서 입력을 제출하고 내부 메시지 목록과 대화 영역의 순서를 확인한다. 두 항목의 본문과 역할이 서로 바뀌거나 합쳐지지 않았는지도 검증한다. **검증 분류** -수준: integration; 백엔드: Textual 렌더링과 대화 상태; 케이스: positive +integration **상태 불변조건** -사용자 메시지는 응답보다 먼저 존재해야 하며 두 메시지의 역할과 본문은 서로 바뀌거나 합쳐지지 않아야 한다. +사용자 메시지는 대응하는 응답보다 먼저 존재해야 하며 각 메시지의 역할과 본문은 독립적으로 보존되어야 한다. -### REQ-002.02-AC02 — 고정 목록에서 표준 방식으로 응답을 선택한다 +### REQ-002.02-AC02 — 고정 목록에서 한 번 응답을 선택한다 **판정 기준** -유효 입력마다 선언된 다섯 개 응답 목록 전체를 대상으로 표준 난수 선택이 한 번 수행되고 그 결과가 상태와 화면에 동일하게 반영되면 통과로 판정한다. +유효한 입력마다 선언된 다섯 개 응답 전체를 대상으로 표준 난수 선택이 한 번 수행되고 선택 결과가 상태와 화면에 동일하게 반영되면 통과로 판정한다. **검증** -난수 선택 함수를 감시하거나 결과를 고정하여 유효 입력을 제출하고 호출 인자와 표시된 응답을 비교한다. +난수 선택 함수를 감시하거나 결과를 고정하여 유효 입력을 제출하고 호출 인자와 표시된 응답을 비교한다. 무효 입력에서 선택이 발생하지 않는지도 확인한다. **검증 분류** -수준: unit; 백엔드: Python 표준 난수 선택과 응답 상수; 케이스: positive +unit **상태 불변조건** -응답은 고정 목록 밖의 값이 될 수 없으며 무효 입력에서는 선택이 발생하지 않아야 한다. +응답은 정본 고정 목록 밖의 값이 될 수 없으며, 무효 입력에서는 선택 상태가 변경되지 않아야 한다. ### REQ-002.02-AC03 — 여러 제출을 기존 순서 뒤에 누적한다 **판정 기준** -서로 다른 유효 입력을 두 번 이상 제출했을 때 각 입력과 응답 쌍이 제출 순서와 동일하게 상태와 화면에 누적되면 통과로 판정한다. +서로 다른 유효 입력을 두 번 이상 제출했을 때 각 입력과 대응 응답 쌍이 제출 순서와 동일하게 상태와 화면에 누적되면 통과로 판정한다. **검증** -두 개 이상의 입력을 순서대로 제출하고 제출 입력, 선택 응답, 메시지 목록 및 렌더링 순서를 확인한다. +두 개 이상의 입력을 순서대로 제출하고 제출 기록, 선택 응답, 메시지 목록과 렌더링 순서를 비교한다. **검증 분류** -수준: integration; 백엔드: 세션 대화 상태와 Textual 위젯 트리; 케이스: positive +integration **상태 불변조건** -새 제출은 기존 메시지를 삭제하거나 재정렬하지 않아야 하며 각 유효 입력은 사용자 메시지 하나와 응답 하나를 추가해야 한다. +새 제출은 기존 메시지를 삭제하거나 재정렬하지 않아야 하며 유효한 입력마다 사용자 메시지 하나와 응답 하나만 추가되어야 한다. ### REQ-002.03-AC01 — 유효 입력 제출 후 입력창을 비운다 **판정 기준** -유효한 입력을 제출한 직후 입력 위젯의 값이 빈 문자열이면 통과로 판정한다. +양끝 공백을 포함한 유효한 입력을 제출한 직후 입력 위젯의 값이 빈 문자열이고 정규화된 메시지와 응답은 정상적으로 보존되면 통과로 판정한다. **검증** -입력 위젯에 양끝 공백을 포함한 유효값을 설정하고 Enter를 누른 뒤 위젯 값과 대화 메시지를 확인한다. +입력 위젯에 유효값을 설정하고 Enter를 누른 뒤 위젯 값, 메시지 목록과 대화 영역을 확인한다. **검증 분류** -수준: integration; 백엔드: Textual Input 위젯; 케이스: positive +integration **상태 불변조건** @@ -256,51 +277,69 @@ Textual 테스트에서 양끝 공백이 포함된 입력을 제출하고 제출 **판정 기준** -빈 값 또는 공백만 포함한 값을 제출한 뒤 입력 위젯의 값이 빈 문자열이고 대화 상태가 변경되지 않으면 통과로 판정한다. +빈 값 또는 공백만 포함한 값을 제출한 뒤 입력 위젯의 값이 빈 문자열이고 대화 상태와 응답 선택 상태가 변경되지 않으면 통과로 판정한다. **검증** -빈 입력과 공백 입력을 각각 제출하고 제출 후 입력 위젯 값, 메시지 목록 및 응답 선택 기록을 확인한다. +빈 입력과 공백 입력을 각각 제출하고 제출 후 입력 위젯 값, 메시지 목록, 응답 선택 기록과 화면 항목 수를 비교한다. **검증 분류** -수준: integration; 백엔드: Textual Input 위젯과 입력 검증; 케이스: unchanged-state +integration **상태 불변조건** -입력창은 비워져야 하지만 기존 대화 상태, 응답 선택 상태와 표시 영역은 그대로 유지되어야 한다. +입력창은 비워져야 하지만 기존 대화 상태와 표시 영역은 그대로 유지되어야 하며 새 항목이 추가되어서는 안 된다. -### REQ-002.04-AC01 — 역할에 따라 라벨과 스타일을 구분한다 +### REQ-002.04-AC01 — 역할에 맞는 라벨을 표시한다 **판정 기준** -사용자 메시지가 사용자 라벨과 사용자 스타일을 갖고 에이전트 응답이 에이전트 라벨과 에이전트 스타일을 가지면 통과로 판정한다. +사용자 메시지가 사용자 라벨을 사용하고 에이전트 응답이 에이전트 라벨을 사용하며 각 라벨이 해당 메시지 역할과 일치하면 통과로 판정한다. **검증** -각 역할의 메시지를 대화 영역에 표시한 뒤 렌더링 텍스트와 구조적 스타일 식별자를 확인하고 역할과의 대응을 비교한다. +유효한 입력을 제출한 뒤 대화 영역의 두 표시 항목을 조회하여 렌더링 문자열과 내부 역할을 비교한다. **검증 분류** -수준: integration; 백엔드: 메시지 모델과 Textual 렌더링; 케이스: positive +integration **상태 불변조건** -메시지 역할과 표시 라벨 및 스타일은 서로 불일치해서는 안 되며 한 역할의 스타일이 다른 역할에 적용되어서는 안 된다. +메시지 역할과 표시 라벨은 항상 일치해야 하며 한 역할의 라벨이 다른 역할에 적용되어서는 안 된다. + +### REQ-002.04-AC02 — 역할별 구조적 스타일을 유지한다 + +**판정 기준** + +사용자와 에이전트 표시 항목이 서로 구별되는 구조적 식별자와 스타일을 사용하고 역할 구분이 색상에만 의존하지 않으면 통과로 판정한다. + +**검증** + +대화 영역의 표시 항목과 애플리케이션 스타일 규칙을 확인하여 역할별 식별자와 테두리 또는 정렬 차이가 존재하고 각 역할에 올바르게 적용되는지 검증한다. + +**검증 분류** + +integration + +**상태 불변조건** + +메시지 역할과 구조적 스타일은 서로 불일치해서는 안 되며 본문 내용만으로 스타일이 임의 변경되어서는 안 된다. ### REQ-002.05-AC01 — Escape 입력으로 종료를 요청한다 **판정 기준** -실행 중인 애플리케이션에서 Escape를 입력했을 때 애플리케이션 종료 동작이 정확히 한 번 요청되면 통과로 판정한다. +실행 중인 애플리케이션에서 Escape를 입력했을 때 종료 동작이 한 번 요청되고 메시지 제출이나 응답 선택이 발생하지 않으면 통과로 판정한다. **검증** -종료 동작을 감시하는 Textual 테스트에서 Escape를 입력하고 종료 요청 횟수와 대화 상태 변경 여부를 확인한다. +종료 동작을 감시하는 Textual 테스트에서 Escape를 입력하고 종료 요청 횟수와 메시지·응답 상태의 변경 여부를 확인한다. **검증 분류** -수준: end-to-end; 백엔드: Textual 키 바인딩과 애플리케이션 생명 주기; 케이스: positive +end-to-end **상태 불변조건** @@ -310,71 +349,74 @@ Escape 입력은 새 메시지나 응답을 생성하거나 입력 제출로 처 **판정 기준** -실행 중인 애플리케이션에서 Ctrl+Q를 입력했을 때 Escape와 동일한 종료 동작이 정확히 한 번 요청되면 통과로 판정한다. +실행 중인 애플리케이션에서 Ctrl+Q를 입력했을 때 Escape와 동일한 종료 경로가 한 번 요청되면 통과로 판정한다. **검증** -종료 동작을 감시한 상태에서 Ctrl+Q를 입력하고 Escape 테스트와 동일한 종료 경로, 호출 횟수 및 상태 불변조건을 확인한다. +Ctrl+Q를 입력하고 Escape 검증과 동일한 종료 요청 횟수, 호출 경로와 상태 불변조건을 비교한다. **검증 분류** -수준: end-to-end; 백엔드: Textual 키 바인딩과 애플리케이션 생명 주기; 케이스: positive +end-to-end **상태 불변조건** -Ctrl+Q는 Escape와 다른 메시지 처리 경로를 사용해서는 안 되며 종료 시 대화 순서와 기존 세션 상태를 변경해서는 안 된다. +Ctrl+Q는 Escape와 다른 메시지 처리 경로를 사용해서는 안 되며 종료 시 대화 상태와 입력 처리 기록을 변경해서는 안 된다. ## 8. 오류 및 충돌 계약 -- 입력 제출 이벤트나 입력 위젯을 사용할 수 없는 초기화 실패가 발생하면 정상적인 메시지 처리로 판정하지 않으며 부분 대화 상태를 성공 결과로 남기지 않는다. -- 빈 문자열 또는 공백만 포함한 입력은 오류가 아니라 무시 가능한 입력으로 처리하고 응답 선택과 메시지 추가를 수행하지 않는다. -- 응답 선택에 실패하면 해당 입력의 사용자 메시지와 에이전트 응답을 부분적으로 기록하지 않아야 하며, 앞서 성공한 세션 메시지는 변경하지 않는다. -- 고정 응답 목록이 비어 있거나 정본과 다르면 응답을 생성하지 않고 처리 실패로 식별해야 한다. -- 메시지 렌더링에 실패하면 일부 화면 항목만 남은 상태를 완전한 처리 성공으로 간주하지 않아야 한다. -- 입력창 초기화에 실패하면 처리 결과를 완전한 성공으로 판정하지 않아야 하며, 이전 입력이 다음 처리에 재사용되지 않도록 실패 원인을 확인할 수 있어야 한다. -- 종료 요청은 이미 종료된 애플리케이션에서 중복 메시지나 응답을 추가하지 않아야 한다. -- 외부 API, 네트워크, 파일 저장소 또는 데이터베이스 오류를 대화 처리의 대체 경로로 사용하지 않는다. -- 지원되지 않는 실행 환경이나 REQ-001의 선행 실행 조건을 충족하지 못한 상태에서는 대화 동작을 정상 제공된 것으로 판정하지 않는다. -- REQ-001의 패키징 및 실행 기반과 이 문서의 대화 동작 사이에 충돌이 발생하면 프로젝트 실행 기반은 REQ-001이, 대화 상호작용의 의미와 검증 기준은 REQ-002가 정본이다. -- 어느 문서도 다른 문서의 범위를 임의로 확장하거나 동일한 기능 규칙과 인수 기준을 중복 정의하지 않는다. +- 입력 위젯이나 제출 이벤트를 사용할 수 없는 초기화 실패는 정상적인 대화 처리로 판정하지 않으며, 부분적으로 생성된 메시지를 성공 결과로 남기지 않는다. +- 빈 문자열 또는 공백만 포함한 입력은 오류가 아니라 무시 가능한 입력으로 처리하고, 응답 선택과 메시지 추가를 수행하지 않는다. +- 응답 선택에 실패하면 해당 제출의 사용자 메시지와 에이전트 응답을 모두 완전한 쌍으로 기록하지 않으며, 앞서 성공한 세션 메시지는 변경하지 않는다. +- 고정 응답 목록이 비어 있거나 정본과 다르면 응답을 생성하지 않고 처리 실패로 식별한다. +- 메시지 렌더링에 실패하면 화면에 일부 항목만 남은 상태를 완전한 처리 성공으로 간주하지 않는다. +- 입력창 초기화에 실패하면 제출을 완전한 성공으로 판정하지 않으며, 이전 입력이 다음 제출에 재사용되지 않도록 실패 원인을 확인할 수 있어야 한다. +- 동일한 제출 이벤트를 자동으로 중복 처리하지 않으며, 단일 Textual 이벤트 루프의 처리 순서에 따라 한 번만 반영한다. +- 이미 종료된 애플리케이션에 대한 종료 요청은 새 메시지나 응답을 추가하거나 오류 상태를 정상 처리로 바꾸지 않는다. +- 외부 API, 네트워크, 파일 저장소 또는 데이터베이스 오류를 대화 처리를 위한 대체 경로로 사용하지 않는다. +- 선행 프로젝트 스캐폴드의 설치 또는 실행 조건을 충족하지 못한 상태에서는 대화 기능이 정상 제공된 것으로 판정하지 않는다. +- 프로젝트 구조와 실행 기반에 관한 충돌은 선행 스캐폴드 요구사항을 따르고, 입력·응답·표시·입력창·종료 동작에 관한 충돌은 이 문서의 대화 상호작용 계약을 따른다. +- 두 요구사항 문서는 서로의 범위를 임의로 확장하지 않으며 동일한 기능 규칙과 인수 조건을 중복 정의하지 않는다. ## 9. 데이터 및 인터페이스 계약 -- 입력 인터페이스는 대화 입력 위젯에서 Enter로 제출되는 문자열 값이다. -- 입력값은 제출 시 양끝 공백을 제거하며 문자열 내부의 공백은 변경하지 않는다. -- 정규화된 입력이 비어 있지 않으면 사용자 메시지의 본문으로 저장하고 화면에 표시한다. -- 고정 응답 목록은 다음 다섯 문장을 정본으로 사용한다: "안녕하세요! 무엇을 도와드릴까요?", "그것은 제가 처리하기 불가능합니다.", "맡겨만 주세요.", "지금 처리 중입니다.", "작업을 완료하였습니다.". -- 응답 선택은 정본 고정 응답 목록 전체를 표준 난수 선택 기능에 전달하여 수행한다. -- 세션 대화 상태의 각 메시지는 사용자 또는 에이전트 작성자 역할과 비어 있지 않은 본문을 함께 보유한다. -- 사용자 메시지는 "사용자: 본문" 형식으로, 에이전트 응답은 "에이전트: 본문" 형식으로 표시한다. -- 사용자 메시지와 에이전트 응답은 서로 다른 구조적 스타일을 사용하며, 스타일은 본문 문자열이 아니라 작성자 역할에서 파생한다. -- 유효한 제출 하나는 사용자 메시지와 대응하는 에이전트 응답의 두 항목으로 구성하고 두 항목의 인접 순서를 유지한다. -- 빈 입력 제출은 입력창을 빈 값으로 만들 수 있지만 대화 메시지, 응답 선택 및 화면 항목을 생성하지 않는다. -- 입력창은 초기 화면에서 입력을 받을 수 있어야 하며 유효하거나 무효인 제출 처리 후 다시 입력 가능한 상태여야 한다. -- Escape와 Ctrl+Q는 별도 데이터 값을 생성하지 않고 동일한 애플리케이션 종료 동작을 요청하는 키 입력이다. -- 메시지와 선택 응답은 현재 프로세스의 세션 메모리에만 보관하며 애플리케이션 종료 후 재조회하거나 복구하는 인터페이스는 제공하지 않는다. -- 프로젝트 패키지 위치, 패키징 메타데이터 및 실행 진입점 계약은 REQ-001을 참조하며 이 문서에서 재정의하지 않는다. +- 입력 인터페이스는 대화 입력 위젯에서 Enter로 제출되는 문자열 값이며, 제출 시 양끝 공백을 제거한다. 문자열 내부의 공백은 보존한다. +- 정규화된 입력이 비어 있지 않으면 사용자 메시지의 본문으로 사용하고, 비어 있으면 메시지 본문으로 저장하지 않는다. +- 고정 응답 목록은 다음 다섯 문구를 정본으로 사용한다: "안녕하세요! 무엇을 도와드릴까요?", "그것은 제가 처리하기 불가능합니다.", "맡겨만 주세요.", "지금 처리 중입니다.", "작업을 완료하였습니다.". +- 응답 선택은 정본 고정 응답 목록 전체를 표준 난수 선택 기능에 전달하여 수행하며, 유효한 입력마다 한 번만 실행한다. +- 세션 메시지는 사용자 또는 에이전트 역할과 비어 있지 않은 본문을 함께 보유한다. 유효한 제출 하나는 사용자 메시지와 대응하는 에이전트 응답의 두 항목으로 구성된다. +- 사용자 메시지는 사용자 라벨과 사용자용 구조적 스타일로, 에이전트 응답은 에이전트 라벨과 에이전트용 구조적 스타일로 표시한다. 표시 정보는 메시지 역할에서 파생한다. +- 메시지 쌍은 사용자 메시지 다음에 에이전트 응답이 오는 인접 순서를 가지며, 여러 제출의 쌍은 세션 메모리에서 제출 순서대로 유지한다. +- 무효 입력은 입력창을 빈 값으로 만들지만 메시지, 응답 선택 기록 및 대화 영역 항목을 생성하지 않는다. +- 유효하거나 무효인 제출 이후 입력창은 다시 입력 가능한 빈 상태가 된다. +- Escape와 Ctrl+Q는 별도의 데이터 값을 만들지 않고 동일한 애플리케이션 종료 동작을 요청하는 키 입력이다. +- 메시지와 선택된 응답은 현재 프로세스의 세션 메모리에만 보관하며 종료 후 재조회하거나 복구하는 인터페이스는 제공하지 않는다. +- 외부 API, LLM, 네트워크 서비스, 데이터베이스 및 영속 저장소 인터페이스는 제공하지 않는다. +- 프로젝트 패키지 위치, 패키징 메타데이터 및 실행 진입점은 선행 프로젝트 스캐폴드 요구사항을 참조하며 이 문서에서 상세 계약을 재정의하지 않는다. ## 10. 하위 호환성 -- REQ-001에 정의된 `chat-tui` 콘솔 실행 방식과 `python -m chat_tui` 모듈 실행 방식은 유지되어야 한다. -- 대화 기능 분리로 프로젝트 설치 방법, Python 지원 버전, 패키지 이름, Textual 의존성 및 실행 진입점 계약을 변경하지 않는다. -- 기존 Textual 화면 진입과 입력 위젯의 역할을 유지해야 한다. -- 기존의 입력 양끝 공백 제거, 유효 입력 판정, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 의미를 변경하지 않는다. -- 공백이 포함된 유효한 입력은 정규화된 값만 대화에 기록하고, 공백만 포함한 입력은 대화 항목을 추가하지 않아야 한다. -- 고정 응답 문구와 사용자 및 에이전트 표시 라벨은 기존 동작과 호환되도록 유지해야 한다. -- Escape와 Ctrl+Q 종료 방식은 별도 변환 없이 계속 사용할 수 있어야 하며 두 키는 동일한 종료 동작을 요청해야 한다. -- 세션 내 메시지 누적은 유지하되 영속성이나 외부 서비스 연동을 새로 도입하지 않는다. +- 선행 프로젝트 스캐폴드 요구사항에 정의된 설치 방법, Python 지원 조건, 패키지 이름, Textual 런타임 의존성 및 실행 진입점은 변경하지 않는다. +- 기존 Textual 화면 진입과 입력 위젯의 역할을 유지하며, 대화 기능을 분리해도 사용자는 동일한 입력 방식과 키 조작으로 대화를 시작할 수 있어야 한다. +- 입력 양끝 공백 제거, 유효 입력 판정, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작의 의미는 유지한다. +- 공백이 포함된 유효 입력은 정규화된 값만 대화에 기록하고, 공백만 포함한 입력은 대화 항목과 응답을 추가하지 않는다. +- 고정 응답 문구와 사용자 및 에이전트 표시 라벨은 기존 관찰 결과와 호환되도록 유지한다. +- 사용자 메시지와 에이전트 응답의 순서, 세션 내 누적 방식 및 역할 구분을 변경하지 않는다. +- Escape와 Ctrl+Q는 계속 사용할 수 있어야 하며 두 키는 동일한 종료 동작을 요청해야 한다. +- 제출 후 입력창을 비우는 동작은 유효 입력과 무효 입력 모두에서 유지한다. +- 세션 내 메모리 기반 메시지 관리는 유지하되 영속성, 외부 서비스 연동, 인증, 다중 세션 또는 메시지 복원을 새로 도입하지 않는다. - 대화 기능을 사용하는 기존 호출자는 추가 마이그레이션 없이 동일한 입력과 키 조작으로 동일한 관찰 결과를 얻어야 한다. -- 테스트와 문서는 실제 애플리케이션이 제공하는 입력, 응답, 표시, 입력창 및 종료 동작과 일치해야 한다. -- REQ-001의 프로젝트 구조, 패키징 및 실행 진입점은 이 요구사항의 변경 대상이 아니며, REQ-002는 해당 선행 계약을 의존한다. -- 대화 상호작용의 상세 규칙은 REQ-002에서만 정본으로 관리하고 REQ-001에 중복 기록하지 않는다. +- 이 문서는 대화 상호작용의 상세 규칙을 정본으로 관리하고, 선행 프로젝트 스캐폴드 요구사항의 프로젝트 구조·패키징·실행 진입점 계약을 복제하거나 변경하지 않는다. +- 테스트와 문서는 실제 애플리케이션이 제공하는 입력, 응답, 표시, 입력창 및 종료 동작과 일치해야 하며, 실행되지 않은 검증을 성공 결과로 기록하지 않는다. +- 새로운 외부 의존성, 배포 방식, 실행 환경 변경 또는 데이터 마이그레이션은 필요하지 않다. ## 11. 검증 계획 -Python 3.11 이상 환경에서 애플리케이션을 실행하여 대화 입력과 종료 동작을 검증한다. 정상 입력에서는 앞뒤 공백이 제거된 사용자 메시지와 고정 응답이 제출 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 세션 내 메시지가 사용자 메시지와 응답의 인접한 쌍으로 누적되는지 확인한다. 빈 입력이나 공백만 포함한 입력에서는 응답 선택, 메시지 누적 및 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택이 정본으로 정의된 다섯 개 문구 중 하나를 표준 난수 방식으로 결정하는지와 선택 결과가 에이전트 메시지로 표시되는지 확인한다. 사용자와 에이전트 메시지의 라벨과 구조적 스타일이 역할에 맞는지 검증한다. Escape와 Ctrl+Q 입력은 애플리케이션 종료를 요청하고 종료 전에 새 메시지나 응답을 생성하지 않는지 확인한다. 프로젝트 설치 및 두 실행 진입점의 검증을 선행한 뒤 대화 기능 회귀 검증을 수행하며, 외부 API나 영속 저장소 없이 저장소의 자동화 테스트로 결과를 판정한다. +Python 3.11 이상 환경에서 프로젝트 설치와 실행 기반이 선행 조건을 충족하는지 확인한 뒤 대화 상호작용을 검증한다. 정상 입력에서는 양끝 공백이 제거된 사용자 메시지와 고정 응답이 제출 순서대로 대화 영역에 표시되는지 확인한다. 여러 입력을 연속 제출하여 각 사용자 메시지와 에이전트 응답이 인접한 쌍으로 기존 순서 뒤에 누적되는지 검증한다. -테스트 정의와 실행 증거는 별도 테스트 카탈로그 및 증거 산출물에서 관리한다. 대화 입력 정규화, 빈 입력 무시, 메시지와 응답의 순서 및 누적, 고정 응답 선택, 입력창 초기화, 역할별 표시와 종료 단축키에 대한 각 인수 기준의 검증 연결을 빠짐없이 기록한다. 실행 증거에는 요구사항 개정, 검증한 커밋, 실행 환경, 실행 시각과 결과를 포함하며, 아직 실행하지 않은 검증은 성공으로 간주하지 않는다. 현재 문서 작성 시점에는 이 요구사항을 검증한 실행 커밋과 실행 시각을 기록하지 않는다. +빈 문자열과 공백·탭·줄바꿈만 포함한 입력에서는 응답 선택, 메시지 누적 및 새 화면 항목 추가가 발생하지 않고 입력창만 초기화되는지 확인한다. 응답 선택은 정본으로 정의된 고정 응답 목록에서 표준 난수 방식으로 수행되는지 확인하고, 선택된 값이 에이전트 메시지로 표시되는지 검증한다. 사용자와 에이전트의 라벨 및 구조적 스타일이 메시지 역할과 일치하는지도 확인한다. + +Escape와 Ctrl+Q 입력은 동일한 애플리케이션 종료 동작을 요청하며, 종료 입력이 메시지 제출이나 응답 선택으로 처리되지 않는지 검증한다. 검증 정의와 실행 결과는 별도 테스트 카탈로그와 증거 산출물에서 관리한다. 실행되지 않은 검증은 성공으로 기록하지 않으며, 현재 문서 작성 시점에는 실행 커밋과 실행 시각을 미기록 상태로 둔다. ### 테스트 추적성 계약 @@ -391,6 +433,7 @@ Verifies: - REQ-002.03-AC01 - REQ-002.03-AC02 - REQ-002.04-AC01 +- REQ-002.04-AC02 - REQ-002.05-AC01 - REQ-002.05-AC02 Test reference: tests/test_app.py 및 python -m unittest discover -s tests -v @@ -410,19 +453,19 @@ Executed at: 검증 실행 시각 미기록 ## 12. 추적성 -근거는 원본 Gitea 이슈 #8인 「요구사항명세서의 재작업」, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소 README의 사용자 동작 설명, 애플리케이션 구현과 대화 동작 테스트다. 이 문서는 원본 이슈 #8에서 요구한 대화 기능 분리의 결과로 작성되며, 프로젝트 스캐폴드와 패키징 및 실행 진입점을 선행 조건으로 사용하되 그 의미와 실행 계약을 변경하지 않는다. +근거는 원본 Gitea 이슈 #8인 요구사항명세서 재작업 요청, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소의 사용자 동작 설명, 애플리케이션 구현 및 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 그 패키징과 실행 계약을 변경하거나 다시 정의하지 않는다. -사용자 입력 정규화, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서만 추적한다. 패키징 메타데이터와 실행 진입점은 선행 프로젝트 스캐폴드 문서에서 추적하며 이 문서에서는 상세 규칙과 수용 기준을 중복 정의하지 않는다. 구현 파일의 입력 제출 처리, 고정 응답 목록, 역할별 표시 구조, 종료 바인딩과 관련 테스트는 각 동작의 근거 및 검증 지점이다. +입력 양끝 공백 제거, 유효 입력 판정, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 프로젝트 구조, 패키징 메타데이터와 실행 진입점은 선행 요구사항 문서에서 추적하므로 이 문서에서는 상세 규칙과 인수 기준을 중복 정의하지 않는다. -프로젝트 스캐폴드 문서와의 의존 관계는 설치 및 실행 기반에 한정한다. 두 문서는 동일한 기능 규칙이나 인수 기준을 중복 정의하지 않으며, 대화 동작의 검증 결과는 실제 실행된 검증 기록이 있을 때만 별도 증거로 연결한다. +두 요구사항 문서는 설치 및 실행 기반과 대화 동작의 선행 관계를 공유하되 동일한 기능 규칙이나 인수 기준을 중복 기록하지 않는다. 대화 동작의 검증 결과는 실제 실행된 검증 기록이 있을 때만 별도 증거에 연결한다. 기존 프로젝트 스캐폴드 요구사항의 제목, 적용 범위, 승인 상태와 승인 이력은 이 문서의 작성으로 변경하지 않는다. ## 13. 확정된 결정 -원본 이슈 #8의 분리 범위에 따라 기존 구현과 테스트가 정의한 대화 동작을 독립된 요구사항 문서로 기록한다. 입력은 제출 시 앞뒤 공백을 제거하고, 정규화 결과가 비어 있으면 대화 항목을 추가하지 않는다. 유효한 입력마다 사용자 메시지를 먼저 누적하고 정본으로 정의된 다섯 개 응답 중 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. +원본 이슈 #8의 분리 범위에 따라 기존 구현과 테스트가 정의한 대화 동작을 독립된 요구사항 문서에서 관리한다. 입력은 제출 시 양끝 공백을 제거하고, 정규화 결과가 비어 있으면 대화 상태와 응답 선택을 변경하지 않는다. -사용자와 에이전트 메시지는 역할 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청한다. 프로젝트 스캐폴드의 승인 상태와 기존 승인 이력은 선행 문서에서 보존하며, 이 문서는 대화 동작의 의미와 검증 기준만 관리한다. +유효한 입력마다 사용자 메시지를 먼저 누적하고, 정본으로 정의된 고정 응답 목록에서 하나를 표준 난수 방식으로 선택하여 에이전트 메시지로 바로 뒤에 누적한다. 여러 제출은 기존 메시지를 삭제하거나 재배열하지 않고 제출 순서대로 유지한다. -외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. 실행되지 않은 검증은 특정 커밋의 실행 증거 또는 성공 결과로 기록하지 않는다. +사용자와 에이전트 메시지는 명시적인 역할에서 파생되는 라벨과 구조적 스타일로 구분한다. 유효 입력과 무효 입력 모두 제출 후 입력창을 비우며, Escape와 Ctrl+Q는 동일한 애플리케이션 종료 동작을 요청한다. 외부 API, LLM, 데이터베이스, 영속 저장소, 새 의존성 및 사용자 동작 변경은 도입하지 않는다. 실행되지 않은 검증은 특정 커밋의 실행 증거나 성공 결과로 기록하지 않는다. ## 14. 미결 사항 @@ -430,8 +473,6 @@ Executed at: 검증 실행 시각 미기록 ## 15. 승인 기록 -상태: draft -승인 주체: 미승인 -승인 근거: 없음 +상태는 draft이며 아직 최종 승인되지 않았다. 승인 주체와 승인 근거는 확정되지 않았다. -원본 Gitea 이슈 #8의 디스커버리 결과에 따라 구현 대상으로 인계되었으나, 이 요구사항 문서의 최종 승인은 별도 절차에서 수행한다. 승인 전에는 대화 상호작용의 범위, 검증 기준 및 선행 프로젝트 스캐폴드와의 의존 관계를 검토하고, 실제로 실행되지 않은 검증을 승인 근거나 실행 증거로 기록하지 않는다. +이 문서는 원본 이슈 #8의 디스커버리 결과에 따라 대화 상호작용을 독립적으로 추적하기 위해 작성되었다. 최종 승인 전에는 입력 정규화, 메시지 누적, 고정 응답 선택과 표시, 빈 입력 처리, 입력창 초기화, 종료 동작 및 선행 프로젝트 스캐폴드와의 의존 관계를 검토해야 한다. 실제로 실행되지 않은 검증은 승인 근거나 실행 증거로 기록하지 않는다. -- 2.54.0 From 85de08b2c6aee37a1b6ac9fbc8229620c132adc3 Mon Sep 17 00:00:00 2001 From: gitea-agent Date: Sat, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH 5/5] gitea-agent: rework PR #9 Review-ID: 41 Previous-SHA: 15d8c7530837f4ebd94fdf84510ad9b48c972b2d --- docs/requirements/req-001_project-scaffold.md | 254 +++--------------- .../req-002_conversation-interaction.md | 2 +- 2 files changed, 44 insertions(+), 212 deletions(-) diff --git a/docs/requirements/req-001_project-scaffold.md b/docs/requirements/req-001_project-scaffold.md index ae65bfb..b1f4ce4 100644 --- a/docs/requirements/req-001_project-scaffold.md +++ b/docs/requirements/req-001_project-scaffold.md @@ -6,9 +6,7 @@ "revision": "0.1", "status": "approved", "depends_on": [], - "applies_to": [ - "chat-tui-message-rendering" - ], + "applies_to": ["chat-tui-message-rendering"], "language": "ko" } --- @@ -17,234 +15,76 @@ ## 1. 목적 -대화형 Textual TUI에서 사용자가 입력한 메시지와 에이전트의 응답을 작성자 라벨과 구조적 스타일로 명확하게 구분한다. 각 메시지의 작성자 의미를 명시적인 데이터 역할로 관리하여 화면 표시, 실행 흐름 및 자동 테스트에서 일관되게 검증할 수 있게 한다. +대화형 Textual TUI의 프로젝트 스캐폴드와 실행 기반을 보존하고, 메시지 작성자 의미를 명시적인 데이터 역할로 관리한다. 입력 정규화, 응답 선택, 메시지 누적 및 종료와 같은 대화 상호작용의 상세 규칙은 `REQ-002`에서 관리한다. ## 2. 배경 -현재 애플리케이션은 사용자 메시지와 에이전트 응답을 서로 다른 CSS 클래스를 가진 Label로 표시하지만 화면에 작성자 라벨이 없고 작성자 의미가 데이터 개념으로 표현되지 않는다. 따라서 메시지의 작성자를 화면에서 구분하기 어렵고, 테스트도 표시 순서와 내용만 검증할 뿐 작성자 역할과 구조적 구분을 검증하지 못한다. - -이번 요구사항은 외부 API나 LLM 연동 없이 현재 Textual 기반 대화 흐름을 유지하면서 작성자 의미를 명시적으로 모델링하고, 색상에만 의존하지 않는 라벨·테두리·정렬 기반의 구분을 제공하기 위한 것이다. +애플리케이션은 Python 3.11 이상과 Textual 런타임을 사용하는 로컬 TUI다. 기존 메시지 표시의 작성자 의미는 `ChatMessage`와 `MessageRole`로 표현되어야 하며, 화면 라벨과 구조적 스타일은 그 역할에서 파생되어야 한다. 이번 문서는 프로젝트 구조·패키징·실행 진입점과 승인된 작성자 모델을 보존하고, 대화 상호작용 규칙을 별도 요구사항으로 분리한다. ## 3. 범위 -포함 범위는 다음과 같다. +포함 범위는 Python 패키지 구조, 패키징 메타데이터, Textual 실행 기반, `chat_tui.app:main` 콘솔 실행 진입점과 승인된 메시지 작성자 모델이다. 작성자 모델은 `ChatMessage`와 `MessageRole`을 통해 사용자와 에이전트의 의미를 표현하고, 렌더러가 역할에서 라벨과 구조적 스타일을 파생할 수 있도록 한다. -- 사용자 메시지와 에이전트 응답을 각각 별도의 Label 대화 항목으로 표시한다. -- 각 메시지에 사용자 또는 에이전트라는 명시적인 작성자 역할을 부여한다. -- 화면에 사용자와 에이전트 작성자 라벨을 표시한다. -- `user-message`와 `response-message` 식별자를 유지하고, 테두리 또는 정렬 차이 같은 구조적 스타일을 적용한다. -- 유효한 입력의 정규화, 응답 선택, 메시지 표시 순서 및 공백 입력 무시 동작을 유지한다. -- 작성자 역할, 라벨, 구조적 스타일 및 기존 동작을 자동 테스트로 검증한다. -- 관련 요구사항, 데이터 모델, 인터페이스 계약 및 실행 흐름 문서와의 추적성을 유지한다. - -제외 범위는 다음과 같다. - -- LLM 연동 또는 외부 API 호출 -- 대화 저장, 사용자 인증 또는 사용자별 기록 관리 -- 고정 응답 목록과 응답 생성 방식의 변경 -- 대화 영역 전체 레이아웃의 재설계 -- 색상만으로 작성자를 구분하는 방식 -- 별도 영속성 백엔드나 데이터베이스 도입 - -### 포함 - -대화형 Textual TUI에서 사용자 메시지와 에이전트 응답을 명시적인 작성자 역할로 관리하고, 사용자·에이전트 라벨과 구조적 스타일로 구분하여 표시한다. 유효한 입력의 정규화, 고정 응답 선택, 메시지 순서, 공백 입력 무시 및 관련 자동 검증을 포함한다. - -### 제외 - -외부 API 또는 LLM 연동, 대화 저장과 사용자 인증, 고정 응답 목록과 생성 방식의 변경, 대화 영역 전체 레이아웃 재설계, 색상만으로 작성자를 구분하는 방식 및 별도 영속성 백엔드 도입은 포함하지 않는다. +제외 범위는 입력 정규화, 고정 응답 선택, 메시지 누적 순서, 빈 입력 처리, 입력창 초기화와 종료 단축키를 포함한 대화 상호작용의 세부 동작이다. 이러한 규칙과 인수 기준은 `REQ-002`에서 단일 정본으로 관리한다. 외부 API, LLM, 인증, 영속 저장소, 데이터베이스와 새 의존성도 추가하지 않는다. ## 4. 용어와 기준 -사용자 메시지는 입력창에 사용자가 제출한 공백 제거 후의 유효한 문자열이다. 에이전트 응답은 유효한 사용자 입력마다 고정된 응답 목록에서 표준 난수 선택으로 생성되는 문자열이다. 메시지 역할은 메시지를 작성한 주체를 나타내는 명시적인 값이며 `user` 또는 `agent` 중 하나다. - -작성자 라벨은 사용자 역할을 `사용자`, 에이전트 역할을 `에이전트`로 화면에 표시하는 문자열이다. 구조적 스타일은 색상에만 의존하지 않고 CSS 클래스, 테두리 또는 정렬 차이로 작성자를 구분하는 표현이다. - -정본 기준은 `ChatMessage.role`과 `ChatMessage.content`의 조합을 메시지 의미의 단일 기준으로 삼는 것이다. 작성자 라벨과 CSS 클래스는 이 역할에서 파생하며, CSS 클래스만으로 메시지 역할을 판정하지 않는다. +프로젝트 스캐폴드는 Python 패키지 구조, 선언된 런타임 의존성과 콘솔 실행 진입점의 조합을 뜻한다. 메시지 역할은 작성자 의미를 나타내는 `user` 또는 `agent` 값이며, `ChatMessage.role`과 `ChatMessage.content`가 작성자 의미의 정본이다. 사용자·에이전트 라벨과 CSS 클래스는 이 역할에서 파생되는 표시 정보다. ## 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 — 명시적인 메시지 역할 관리 - -시스템은 유효한 사용자 입력과 그에 대응하는 에이전트 응답을 각각 명시적인 작성자 역할을 가진 메시지로 관리해야 한다. 사용자 메시지의 역할은 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 스타일 기능을 사용할 수 있어야 한다. +메시지 모델은 `ChatMessage`와 `MessageRole`을 통해 작성자 역할과 본문을 함께 표현해야 한다. 역할 값은 `user`와 `agent`이며, UI 렌더러는 역할에서 사용자·에이전트 라벨과 기존 `user-message`·`response-message` 식별자를 파생해야 한다. 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다. ## 6. 제약과 불변조건 -- Python 3.11 이상과 현재 Textual 기반 TUI 구조를 유지한다. -- 유효한 입력은 앞뒤 공백을 제거한 뒤 사용자 메시지로 한 번만 기록한다. -- 공백만 있거나 빈 입력은 응답을 선택하지 않고 메시지 목록과 화면을 변경하지 않는다. -- 유효한 입력 하나마다 사용자 메시지가 먼저 표시되고 그 뒤에 에이전트 응답이 표시되어야 한다. -- 에이전트 응답은 기존 고정 응답 목록에서 표준 난수 선택으로 결정한다. -- 모든 메시지는 명시적인 메시지 역할을 통해 작성자 의미를 가져야 하며 CSS 클래스만으로 역할을 판정하지 않는다. -- 사용자와 에이전트는 화면의 텍스트 라벨로 구분되어야 한다. -- 역할 구분은 색상에만 의존하지 않고 역할별 CSS 식별자와 테두리 또는 정렬 차이를 포함해야 한다. -- 메시지 표시와 테스트에서 사용자 및 에이전트 역할의 순서와 의미가 일치해야 한다. -- 외부 API, 인증, 영속 저장소 및 민감정보 처리는 추가하지 않는다. +- Python 3.11 이상과 현재 Textual 기반 TUI 구조 및 선언된 의존성을 유지한다. +- `chat_tui.app:main` 콘솔 실행 진입점과 기존 패키지 위치를 유지한다. +- 메시지의 작성자 의미는 CSS 클래스나 화면 색상에서 추론하지 않고 명시적인 `MessageRole` 값에서 확인한다. +- 사용자와 에이전트의 라벨 및 구조적 스타일은 역할과 일치해야 한다. +- 입력 처리와 응답 동작의 상세 규칙은 이 문서에 복제하지 않고 `REQ-002`를 따른다. +- 외부 API, LLM, 인증, 영속 저장소, 데이터베이스 및 새 의존성은 추가하지 않는다. ## 7. 인수 기준 -인수 기준은 각 소속 요구사항을 포함하는 식별 체계로 관리하며, 판정 조건과 검증 방법 및 상태 불변조건을 함께 기록한다. +### REQ-001.01-AC01 — 패키지와 실행 진입점 보존 -**메시지 역할이 순서대로 보존됨** +프로젝트가 Python 3.11 이상과 선언된 Textual 의존성으로 설치되고 `chat_tui.app:main` 진입점을 계속 제공하면 통과로 판정한다. 이 기준은 프로젝트 구조와 실행 기반만 검증하며 대화 상호작용의 판정은 `REQ-002`에 위임한다. -판정 기준은 유효한 입력의 앞뒤 공백이 제거된 사용자 메시지가 사용자 역할로 기록되고, 같은 제출에서 선택된 응답이 에이전트 역할로 기록되는지 확인하는 것이다. 여러 입력을 제출할 때 메시지 목록은 각 입력에 대해 사용자 메시지 다음에 에이전트 응답이 오는 순서를 유지해야 하며, 역할과 본문은 함께 비교 가능해야 한다. 역할은 CSS 클래스에서 추론하지 않는다. +### REQ-001.02-AC01 — 역할이 작성자 표시의 정본임 -검증은 Textual 테스트 앱에서 두 개의 유효한 입력을 제출하고 제출 입력, 선택 응답 및 메시지의 값과 순서를 비교하는 방식으로 수행한다. 메시지가 사용자와 에이전트 역할을 번갈아 포함하는지 확인하고, 응답 선택을 고정하여 입력 정규화와 역할 보존을 결정적으로 검증한다. 검증 수준은 통합 테스트이며 별도 백엔드는 없고 정상 사례를 대상으로 한다. - -성공하면 입력과 응답이 각각 올바른 역할의 메시지로 세션 목록에 추가되어야 한다. 기존 입력과 응답의 순서 및 내용은 변경되지 않아야 하며, 실패 또는 공백 입력에서는 응답 선택과 메시지 추가가 발생하지 않아야 한다. - -**공백 입력이 역할 없는 메시지를 만들지 않음** - -판정 기준은 빈 문자열 또는 공백, 탭, 개행만 포함한 입력을 제출해도 사용자 메시지와 에이전트 응답이 추가되지 않고 응답 선택 함수가 호출되지 않는지 확인하는 것이다. 제출 후 입력창은 비워져야 한다. - -검증은 공백만 포함한 입력과 빈 입력을 각각 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 - -**상태 불변조건** - -유효 입력 성공 시 기존 응답 선택과 종료 바인딩이 계속 동작해야 한다. 작성자 라벨 추가로 응답 목록, 난수 선택 방식 또는 종료 정책이 변경되어서는 안 된다. 실패 시 부분적인 응답 선택 기록이나 대화 항목이 남아서는 안 된다. +`ChatMessage`가 `MessageRole`과 본문을 함께 보유하고, 사용자와 에이전트 표시의 라벨·식별자·구조적 스타일이 그 역할에서 파생되며 색상만으로 역할을 판정하지 않으면 통과로 판정한다. ## 8. 오류 및 충돌 계약 -- 입력 오류: 빈 입력과 공백 입력은 오류를 표시하지 않고 무시하며, 응답 선택과 메시지 추가를 수행하지 않는다. -- 상태 충돌: 단일 Textual 이벤트 루프에서 제출 이벤트 순서를 처리하며, 동일 입력을 자동으로 중복 제출하지 않는다. -- 저장 실패: 영속 저장소가 없으므로 저장 실패와 롤백 대상이 없다. 렌더링 실패가 발생하더라도 별도의 부분 영속 기록을 만들지 않는다. -- 역할 오류: 사용자 또는 에이전트로 정의되지 않은 역할은 정상 메시지로 렌더링하지 않으며, 역할 값과 표시 라벨의 매핑은 한 곳의 명시적 기준을 따른다. +- 프로젝트 설치 또는 콘솔 진입점이 제공되지 않으면 스캐폴드 요구사항을 충족한 것으로 판정하지 않는다. +- 정의되지 않은 메시지 역할은 정상 표시하지 않으며 역할과 라벨의 매핑은 명시적인 기준을 따른다. +- 프로젝트 구조·패키징·실행 기반에 관한 충돌은 이 문서를 따른다. +- 입력·응답·누적·입력창·종료 동작에 관한 충돌은 `REQ-002`를 따른다. ## 9. 데이터 및 인터페이스 계약 -- 메시지 역할은 문자열 기반 열거형으로 관리하며 사용자 역할의 값은 `user`, 에이전트 역할의 값은 `agent`이다. -- 각 대화 메시지는 필수 역할 값과 필수 본문 문자열을 함께 보유하여 작성자와 내용을 하나의 단위로 표현한다. -- 본문은 앞뒤 공백 제거가 완료된 사용자 입력 또는 선택된 응답을 담는다. -- 역할은 사용자 라벨인 `사용자` 또는 에이전트 라벨인 `에이전트`로 변환할 수 있어야 한다. -- 세션 메시지 목록은 제출 순서를 보유하며 유효한 입력마다 사용자 메시지와 에이전트 응답을 차례로 추가한다. -- 사용자 표시값은 `사용자: 본문` 형식이고 에이전트 표시값은 `에이전트: 본문` 형식이다. -- 사용자 표시 항목은 사용자 메시지 식별자와 사용자 역할 식별자를 포함하고, 에이전트 표시 항목은 응답 메시지 식별자와 에이전트 역할 식별자를 포함한다. -- 제출 입력 기록, 선택 응답 기록 및 기존 고정 응답 목록 계약은 유지한다. -- 식별자는 세션 내 메모리 객체와 CSS 클래스에 한정되며 시간대, 단위 및 정밀도 계약은 없다. +- `MessageRole`은 문자열 기반 열거형이며 값은 `user` 또는 `agent`다. +- `ChatMessage.role`은 필수 역할 값이고 `ChatMessage.content`는 필수 본문 문자열이다. +- 역할에서 사용자 라벨 `사용자` 또는 에이전트 라벨 `에이전트`를 파생할 수 있어야 한다. +- 사용자 표시 항목은 `chat-message user-message user-role` 식별자를, 에이전트 표시 항목은 `chat-message response-message agent-role` 식별자를 사용한다. +- 상세 입력·응답·세션 누적 계약은 `REQ-002`에 정의한다. ## 10. 하위 호환성 -- Python 3.11 이상에서 실행되는 기존 패키지와 콘솔 실행 진입점을 유지한다. -- 대화 영역과 입력 위젯의 기존 식별자를 유지한다. -- 사용자 메시지와 에이전트 응답의 표시 항목 구조 및 표시 순서를 유지하되 표시 문자열과 역할 클래스를 통해 작성자 정보를 추가한다. -- Enter 제출, 앞뒤 공백 제거, 공백 입력 무시, 고정 응답 목록 선택, Escape 및 Ctrl+Q 종료 동작을 유지한다. -- 기존 영속 데이터가 없으므로 데이터 마이그레이션은 필요하지 않다. -- 작성자 라벨과 구조적 스타일은 추가하지만 대화 영역 전체 레이아웃을 재설계하지 않는다. -- 외부 API, LLM 연동, 인증, 영속 저장소 및 별도 데이터베이스를 추가하지 않는다. +- Python 3.11 이상, 현재 Textual 런타임 의존성, 패키지 위치 및 `chat_tui.app:main` 진입점을 유지한다. +- 기존 `#conversation`과 `#user-input` 식별자를 유지한다. +- 작성자 모델과 역할별 표시를 추가해도 대화 영역 전체 레이아웃을 재설계하지 않는다. +- 입력 제출, 응답 선택, 입력창 초기화와 종료 동작은 `REQ-002`의 기존 계약을 따른다. ## 11. 검증 계획 -Textual 테스트 앱에서 정상 입력, 여러 메시지의 순서, 메시지 역할 객체, 작성자 라벨과 구조적 CSS 클래스를 검증한다. 입력값의 앞뒤 공백이 제거되는지, 유효한 입력마다 사용자 메시지와 에이전트 응답이 차례로 추가되는지, 기존 메시지가 삭제되거나 재배열되지 않는지 확인한다. - -빈 문자열과 공백·탭·개행만 포함한 입력을 각각 제출하여 응답 선택이 호출되지 않고 메시지 목록과 대화 영역이 변경되지 않으며 입력창만 비워지는지 검증한다. 응답 선택을 고정하거나 모의 처리하여 정본 응답 목록이 전달되고 선택된 응답이 에이전트 메시지로 표시되는지 확인한다. - -사용자 메시지와 에이전트 응답의 표시 문자열, 역할, 식별자 및 구조적 스타일을 비교하고, 역할별 테두리 또는 정렬 차이가 색상에만 의존하지 않는지 확인한다. Escape와 Ctrl+Q 입력이 동일한 종료 동작을 요청하며 메시지 제출이나 응답 선택을 발생시키지 않는지도 회귀 검증한다. - -실행 가능한 테스트 정의는 별도 테스트 카탈로그에서 관리하고, 요구사항 문서에는 검증 의도와 판정 조건만 기록한다. 실행 결과는 별도 증거 산출물에 기록하며, 실제로 실행하지 않은 검증은 성공으로 기록하지 않는다. 외부 API, 영속성 백엔드 및 데이터베이스를 사용하지 않으므로 저장 후 재조회와 마이그레이션 검증은 해당 없음으로 판정한다. 관련 요구사항과 데이터 모델, 인터페이스 계약 및 실행 흐름 문서의 역할·라벨·스타일·순서 설명이 구현 및 테스트와 일치하는지도 문서 검토로 확인한다. +패키지 메타데이터와 콘솔 진입점이 Python 3.11 이상 및 선언된 Textual 환경에서 제공되는지 확인한다. `ChatMessage`와 `MessageRole`의 역할-본문 모델, 역할별 라벨과 식별자, 테두리 또는 정렬 기반 스타일을 검증한다. 입력 정규화, 응답 선택, 메시지 순서, 빈 입력, 입력창 초기화와 종료 단축키의 실행 검증은 `REQ-002`의 테스트 추적성 계약에서 관리한다. ### 테스트 추적성 계약 @@ -254,11 +94,9 @@ Textual 테스트 앱에서 정상 입력, 여러 메시지의 순서, 메시지 Test ID: TC-001-001 Verifies: - REQ-001.01-AC01 -- REQ-001.01-AC02 - REQ-001.02-AC01 -- REQ-001.02-AC02 -Test reference: tests/test_app.py의 Textual 애플리케이션 테스트 -Automated: Textual 테스트 앱에서 작성자 역할, 라벨, 구조적 스타일, 입력 정규화, 응답 선택, 표시 순서와 공백 입력 무시 동작을 자동 검증한다. +Test reference: 프로젝트 패키징 검사와 Textual 애플리케이션 테스트 +Automated: 패키지 진입점, 메시지 역할 모델, 역할별 라벨·식별자·구조적 스타일을 자동 검증한다. ``` 실행 증거: @@ -267,26 +105,18 @@ Automated: Textual 테스트 앱에서 작성자 역할, 라벨, 구조적 스 Test ID: TC-001-001 Requirement revision: REQ-001@0.1 Commit: 실행 증거 미기록 -Environment: Python 3.11 이상, 현재 Textual 테스트 앱, 영속 백엔드 없음 +Environment: Python 3.11 이상, 선언된 Textual 런타임 의존성 Result: 미실행 Executed at: 검증 실행 시각 미기록 ``` ## 12. 추적성 -근거 이슈는 Gitea 이슈 #6인 메시지 표시창의 메시지 작성자 구분 요청이다. 구현 PR은 아직 없으며, 관련 설계 문서는 데이터 모델, 인터페이스 계약, 런타임 흐름 및 프로젝트 구조 문서다. - -이 문서는 대화 메시지의 역할과 본문을 정본으로 삼고, 사용자와 에이전트의 라벨·식별자·구조적 스타일 및 표시 순서를 구현과 테스트에서 일관되게 추적한다. 입력 정규화, 고정 응답 선택, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 계약으로 보존하며 작성자 구분을 위해 의미를 변경하지 않는다. - -역할은 CSS 클래스나 화면 색상에서 추론하지 않고 명시적인 메시지 데이터에서 확인해야 한다. 테스트는 메시지 역할과 본문, 렌더링 라벨과 클래스, 표시 순서 및 기존 동작의 보존 여부를 함께 비교하며, 실행 결과와 커밋 결합 정보는 별도 증거 산출물에서 관리한다. +근거 이슈는 Gitea 이슈 #6인 메시지 표시창의 메시지 작성자 구분 요청이다. 구현 PR은 아직 없으며, 관련 설계 문서는 데이터 모델, 인터페이스 계약, 런타임 흐름 및 프로젝트 구조 문서다. 이 문서는 프로젝트 스캐폴드와 승인된 작성자 모델의 정체성을 보존하고, 대화 상호작용의 상세 규칙은 `REQ-002`의 원본 Gitea 이슈 #8 추적성으로 분리한다. ## 13. 확정된 결정 -사용자 메시지와 에이전트 응답은 명시적인 작성자 역할과 본문을 함께 가진 대화 메시지로 관리한다. 사용자 역할은 user이고 에이전트 역할은 agent이며, 화면의 라벨과 구조적 스타일은 이 역할에서 파생한다. - -사용자 메시지는 사용자 라벨과 사용자 식별자를 사용하고 에이전트 응답은 에이전트 라벨과 응답 식별자를 사용한다. 역할 구분은 색상에만 의존하지 않으며 역할별 테두리 또는 정렬 차이를 포함한다. - -유효한 입력의 앞뒤 공백 제거, 고정 응답 목록에서의 표준 난수 선택, 사용자 메시지 뒤에 에이전트 응답을 표시하는 순서, 공백 입력 무시, 입력창 초기화 및 종료 동작은 기존 의미를 유지한다. 외부 API, LLM, 인증, 영속 저장소 및 데이터베이스는 추가하지 않는다. +프로젝트의 Python 패키지 구조, Textual 실행 기반과 `chat_tui.app:main` 진입점을 유지한다. 메시지 작성자 의미는 `MessageRole`과 `ChatMessage`에 명시적으로 보존하고 라벨·식별자·구조적 스타일은 역할에서 파생한다. 입력과 응답의 세부 동작은 `REQ-002`에서 관리한다. ## 14. 미결 사항 @@ -294,6 +124,8 @@ Executed at: 검증 실행 시각 미기록 ## 15. 승인 기록 -이 요구사항은 approved 상태로 승인되었다. 승인 주체는 spec-agent이며, 승인 근거는 승인 댓글 923 및 디스커버리 승인 결과다. +- 상태: `approved` +- 승인 주체: `spec-agent` +- 승인 근거: 승인 댓글 923 및 디스커버리 승인 결과 -작성자 구분을 명시적인 메시지 역할과 역할에서 파생되는 라벨 및 구조적 스타일로 관리하는 범위는 승인된 정본의 의미로 보존한다. 문서 정리나 관련 문서와의 정합성 검토만으로 승인 상태, 승인 주체 또는 승인 근거를 변경하지 않는다. +문서 분리와 정리만으로 기존 승인 상태, 승인 주체 또는 승인 근거를 변경하지 않는다. \ No newline at end of file diff --git a/docs/requirements/req-002_conversation-interaction.md b/docs/requirements/req-002_conversation-interaction.md index 92754a5..bbfc655 100644 --- a/docs/requirements/req-002_conversation-interaction.md +++ b/docs/requirements/req-002_conversation-interaction.md @@ -453,7 +453,7 @@ Executed at: 검증 실행 시각 미기록 ## 12. 추적성 -근거는 원본 Gitea 이슈 #8인 요구사항명세서 재작업 요청, 기존 프로젝트 스캐폴드 요구사항 문서, 저장소의 사용자 동작 설명, 애플리케이션 구현 및 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 그 패키징과 실행 계약을 변경하거나 다시 정의하지 않는다. +근거는 원본 Gitea 이슈 #8인 요구사항명세서 재작업 요청([Gitea 이슈 #8](https://gitea.jsfamily.quest/genichin/gitea-agent-testbed/issues/8)), 기존 프로젝트 스캐폴드 요구사항 문서, 저장소의 사용자 동작 설명, 애플리케이션 구현 및 대화 동작 테스트다. 이 문서는 프로젝트 스캐폴드와 실행 진입점을 선행 조건으로 사용하며, 그 패키징과 실행 계약을 변경하거나 다시 정의하지 않는다. 입력 양끝 공백 제거, 유효 입력 판정, 세션 내 메시지 누적, 고정 응답 선택과 표시, 빈 입력 무시, 입력창 초기화 및 종료 동작은 이 문서에서 추적한다. 프로젝트 구조, 패키징 메타데이터와 실행 진입점은 선행 요구사항 문서에서 추적하므로 이 문서에서는 상세 규칙과 인수 기준을 중복 정의하지 않는다. -- 2.54.0