From 30a9f6b465e6807002ef6060483ff51b5ac5586d Mon Sep 17 00:00:00 2001 From: Variet Agent Date: Sun, 22 Mar 2026 19:33:05 +0900 Subject: [PATCH] =?UTF-8?q?fix(debate):=20idle-state=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20+=20slug=20=ED=83=90=EC=83=89=20=E2=80=94=20AG=20=EB=8C=80?= =?UTF-8?q?=EA=B8=B0=20=EA=B7=9C=EC=B9=99,=20list-debates=20=EC=BB=A4?= =?UTF-8?q?=EB=A7=A8=EB=93=9C,=20handler=20=EC=8B=9C=EA=B7=B8=EB=84=90=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agent/references/STATUS.md | 5 +-- .../debate-gemini/.agent/workflows/start.md | 23 +++++++++---- debate-agent/debate-gemini/GEMINI.md | 11 +++++- .../debate-gemini/tools/wiki_debate.py | 34 +++++++++++++++++++ .../debate-opus/.agent/workflows/start.md | 23 +++++++++---- debate-agent/debate-opus/GEMINI.md | 11 +++++- debate-agent/debate-opus/tools/wiki_debate.py | 34 +++++++++++++++++++ docs/devlog/2026-03-22.md | 1 + handlers/debate_handler.py | 5 ++- 9 files changed, 130 insertions(+), 17 deletions(-) diff --git a/.agent/references/STATUS.md b/.agent/references/STATUS.md index 214a380..cb22315 100644 --- a/.agent/references/STATUS.md +++ b/.agent/references/STATUS.md @@ -2,7 +2,7 @@ > AI 에이전트는 **세션 시작 시** 이 문서를 읽어 전체 맥락을 파악합니다. > **세션 종료 시** 변경사항을 이 문서에 반영합니다. -> Last updated: 2026-03-20 +> Last updated: 2026-03-22 ## 시스템 개요 @@ -70,10 +70,11 @@ Discord 메시지 | 에이전트 워크플로우 | `.agent/` | ✅ | STATUS.md + 수칙 업데이트 | | Wiki.js | `tools/wiki_client.py` | ✅ | GraphQL CRUD + 대시보드 + singleByPath | | AI Debate Room | `handlers/debate_handler.py` | 🚧 | Wiki.js 기반 분산 토론 (AG 분리) | -| Debate AG 프로젝트 | `debate-agent/` | 🚧 | gemini/opus AG 스캐폴딩 + wiki_debate.py | +| Debate AG 프로젝트 | `debate-agent/` | 🚧 | idle-state 처리 + slug 탐색 + list-debates | ## 최근 마일스톤 +- **2026-03-22**: debate-agent idle-state 처리 — 대기 규칙 + slug 탐색 + list-debates + handler 시그널 개선 - **2026-03-21**: debate-agent 분산 토론 시스템 — Wiki.js 기반 통신, AG 프로젝트 스캐폴딩, handler 리팩토링 - **2026-03-20**: AI Debate Room v2 — 파일 기반 자동 토론 + Flash 합의 판정 + Wiki.js 동기화 - **2026-03-18**: Nextcloud 4모듈 + NC핸들러 + AI Foreman v0.1 + unified 분류→라우팅 구현 diff --git a/debate-agent/debate-gemini/.agent/workflows/start.md b/debate-agent/debate-gemini/.agent/workflows/start.md index fcfced8..1b13476 100644 --- a/debate-agent/debate-gemini/.agent/workflows/start.md +++ b/debate-agent/debate-gemini/.agent/workflows/start.md @@ -1,5 +1,5 @@ --- -description: 토론 세션을 시작합니다. 사회자의 input을 읽고 response를 작성합니다. +description: 토론 세션을 시작합니다. 활성 토론이 없으면 대기합니다. --- # 토론 참여 시작 @@ -12,15 +12,26 @@ description: 토론 세션을 시작합니다. 사회자의 input을 읽고 resp `GEMINI.md`를 읽어 토론 참여자 행동 규칙을 확인합니다. -### 2. 사회자 지시 읽기 +### 2. 활성 토론 탐색 + +```powershell +python tools/wiki_debate.py list-debates +``` + +- 활성 토론이 **없으면** → "진행 중인 토론이 없습니다. 사회자의 시그널을 기다리세요."라고 응답하고 **여기서 종료합니다. 이후 단계를 실행하지 마세요.** +- 활성 토론이 **있으면** → 해당 slug를 사용하여 아래 단계를 진행합니다. +- ⚠️ slug를 추측하거나 임의로 만들지 마세요. 반드시 위 명령의 출력에서 가져오세요. + +### 3. 사회자 지시 읽기 ```powershell python tools/wiki_debate.py read debates/{slug}/input-gemini ``` -> `{slug}`는 현재 진행 중인 토론의 slug입니다. `input-gemini` 페이지가 비어있으면 아직 사회자가 input을 작성하지 않은 것이니 대기하세요. +> `{slug}`는 2단계에서 발견한 실제 토론 slug로 치환합니다. +> 페이지가 비어있거나 `[오류]`가 반환되면 → "사회자의 지시를 기다리는 중입니다"라고 응답하고 **종료합니다.** -### 3. 합의 상태 확인 +### 4. 합의 상태 확인 ```powershell python tools/wiki_debate.py read debates/{slug}/working-document @@ -28,7 +39,7 @@ python tools/wiki_debate.py read debates/{slug}/working-document 사회자가 정리한 현재 합의 상태를 확인합니다. -### 4. 답변 작성 및 업로드 +### 5. 답변 작성 및 업로드 답변을 작성한 후 response 페이지에 업로드: @@ -42,6 +53,6 @@ python tools/wiki_debate.py write debates/{slug}/response-gemini "답변 전문" python tools/wiki_debate.py write-file debates/{slug}/response-gemini response_draft.md ``` -### 5. Discord 완료 시그널 +### 6. Discord 완료 시그널 Discord에 "response 작성 완료"를 게시하여 사회자에게 알립니다. diff --git a/debate-agent/debate-gemini/GEMINI.md b/debate-agent/debate-gemini/GEMINI.md index a79f44e..4c3a592 100644 --- a/debate-agent/debate-gemini/GEMINI.md +++ b/debate-agent/debate-gemini/GEMINI.md @@ -30,13 +30,22 @@ 6. **근거 명시** — 기술적 근거, 사례, 레퍼런스를 포함하세요 7. **합의 가능 시 인정** — 상대 의견이 맞으면 솔직히 인정하고 발전시키세요 +## 대기 상태 (Idle Mode) + +- 진행 중인 토론이 없으면 → **아무것도 하지 마세요.** "진행 중인 토론이 없습니다"라고 답변만 하세요. +- `input-gemini` 페이지가 비어있거나 존재하지 않으면 → **"사회자의 지시를 기다리는 중입니다"라고 답하세요.** +- 사회자가 Discord 시그널을 보내면 그때 `/start`를 다시 실행하여 시작합니다. +- **절대로** 토론 문서가 없다고 해서 자체적으로 해결을 시도하지 마세요. + ## 금지 사항 - ❌ 상대방의 `input-opus` 또는 `response-opus` 페이지 접근 - ❌ `working-document` 수정 (읽기만 — 사회자만 편집) -- ❌ 소스 코드 작성 (문서 수준 논의만) +- ❌ 소스 코드 작성/수정 (문서 수준 논의만) - ❌ 사회자 지시 무시 - ❌ 주제에서 벗어난 발언 - ❌ 근거 없는 주장 - ❌ "이하생략" 또는 답변 축약 - ❌ Discord에 긴 답변 직접 게시 (반드시 Wiki.js response 페이지에) +- ❌ 토론 문서가 없을 때 자체적으로 해결 시도 (소스 수정, 파일 생성, 설정 변경 등) +- ❌ slug를 추측하거나 임의로 생성 diff --git a/debate-agent/debate-gemini/tools/wiki_debate.py b/debate-agent/debate-gemini/tools/wiki_debate.py index 29b9c81..3e4946b 100644 --- a/debate-agent/debate-gemini/tools/wiki_debate.py +++ b/debate-agent/debate-gemini/tools/wiki_debate.py @@ -66,6 +66,28 @@ async def _query(query: str, variables: dict = None) -> dict: return data.get("data", {}) +async def list_debates() -> list[str]: + """Wiki.js에서 debates/ 하위의 활성 토론 slug 목록을 조회.""" + query = """ + query { + pages { list(orderBy: UPDATED, orderByDirection: DESC) { + id, path, updatedAt + }} + } + """ + data = await _query(query) + pages = data.get("pages", {}).get("list", []) + slugs = set() + for p in pages: + path = p.get("path", "") + # debates/{slug}/input-* 형태의 페이지에서 slug 추출 + if path.startswith("debates/") and "/input-" in path: + parts = path.split("/") + if len(parts) >= 3: + slugs.add(parts[1]) + return sorted(slugs) + + async def read_page(path: str) -> str: """경로로 페이지 읽기 (singleByPath).""" query = """ @@ -143,6 +165,18 @@ async def main(): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") args = sys.argv[1:] + + # list-debates 커맨드는 인수 불필요 + if args and args[0] == "list-debates": + slugs = await list_debates() + if slugs: + print("활성 토론 목록:") + for s in slugs: + print(f" - {s}") + else: + print("진행 중인 토론이 없습니다.") + return + if len(args) < 2: print(__doc__) return diff --git a/debate-agent/debate-opus/.agent/workflows/start.md b/debate-agent/debate-opus/.agent/workflows/start.md index 54625f0..9963b7a 100644 --- a/debate-agent/debate-opus/.agent/workflows/start.md +++ b/debate-agent/debate-opus/.agent/workflows/start.md @@ -1,5 +1,5 @@ --- -description: 토론 세션을 시작합니다. 사회자의 input을 읽고 response를 작성합니다. +description: 토론 세션을 시작합니다. 활성 토론이 없으면 대기합니다. --- # 토론 참여 시작 @@ -12,15 +12,26 @@ description: 토론 세션을 시작합니다. 사회자의 input을 읽고 resp `GEMINI.md`를 읽어 토론 참여자 행동 규칙을 확인합니다. -### 2. 사회자 지시 읽기 +### 2. 활성 토론 탐색 + +```powershell +python tools/wiki_debate.py list-debates +``` + +- 활성 토론이 **없으면** → "진행 중인 토론이 없습니다. 사회자의 시그널을 기다리세요."라고 응답하고 **여기서 종료합니다. 이후 단계를 실행하지 마세요.** +- 활성 토론이 **있으면** → 해당 slug를 사용하여 아래 단계를 진행합니다. +- ⚠️ slug를 추측하거나 임의로 만들지 마세요. 반드시 위 명령의 출력에서 가져오세요. + +### 3. 사회자 지시 읽기 ```powershell python tools/wiki_debate.py read debates/{slug}/input-opus ``` -> `{slug}`는 현재 진행 중인 토론의 slug입니다. `input-opus` 페이지가 비어있으면 아직 사회자가 input을 작성하지 않은 것이니 대기하세요. +> `{slug}`는 2단계에서 발견한 실제 토론 slug로 치환합니다. +> 페이지가 비어있거나 `[오류]`가 반환되면 → "사회자의 지시를 기다리는 중입니다"라고 응답하고 **종료합니다.** -### 3. 합의 상태 확인 +### 4. 합의 상태 확인 ```powershell python tools/wiki_debate.py read debates/{slug}/working-document @@ -28,7 +39,7 @@ python tools/wiki_debate.py read debates/{slug}/working-document 사회자가 정리한 현재 합의 상태를 확인합니다. -### 4. 답변 작성 및 업로드 +### 5. 답변 작성 및 업로드 답변을 작성한 후 response 페이지에 업로드: @@ -42,6 +53,6 @@ python tools/wiki_debate.py write debates/{slug}/response-opus "답변 전문" python tools/wiki_debate.py write-file debates/{slug}/response-opus response_draft.md ``` -### 5. Discord 완료 시그널 +### 6. Discord 완료 시그널 Discord에 "response 작성 완료"를 게시하여 사회자에게 알립니다. diff --git a/debate-agent/debate-opus/GEMINI.md b/debate-agent/debate-opus/GEMINI.md index 53891ec..8f84c3c 100644 --- a/debate-agent/debate-opus/GEMINI.md +++ b/debate-agent/debate-opus/GEMINI.md @@ -30,13 +30,22 @@ 6. **근거 명시** — 기술적 근거, 사례, 레퍼런스를 포함하세요 7. **합의 가능 시 인정** — 상대 의견이 맞으면 솔직히 인정하고 발전시키세요 +## 대기 상태 (Idle Mode) + +- 진행 중인 토론이 없으면 → **아무것도 하지 마세요.** "진행 중인 토론이 없습니다"라고 답변만 하세요. +- `input-opus` 페이지가 비어있거나 존재하지 않으면 → **"사회자의 지시를 기다리는 중입니다"라고 답하세요.** +- 사회자가 Discord 시그널을 보내면 그때 `/start`를 다시 실행하여 시작합니다. +- **절대로** 토론 문서가 없다고 해서 자체적으로 해결을 시도하지 마세요. + ## 금지 사항 - ❌ 상대방의 `input-gemini` 또는 `response-gemini` 페이지 접근 - ❌ `working-document` 수정 (읽기만 — 사회자만 편집) -- ❌ 소스 코드 작성 (문서 수준 논의만) +- ❌ 소스 코드 작성/수정 (문서 수준 논의만) - ❌ 사회자 지시 무시 - ❌ 주제에서 벗어난 발언 - ❌ 근거 없는 주장 - ❌ "이하생략" 또는 답변 축약 - ❌ Discord에 긴 답변 직접 게시 (반드시 Wiki.js response 페이지에) +- ❌ 토론 문서가 없을 때 자체적으로 해결 시도 (소스 수정, 파일 생성, 설정 변경 등) +- ❌ slug를 추측하거나 임의로 생성 diff --git a/debate-agent/debate-opus/tools/wiki_debate.py b/debate-agent/debate-opus/tools/wiki_debate.py index 29b9c81..3e4946b 100644 --- a/debate-agent/debate-opus/tools/wiki_debate.py +++ b/debate-agent/debate-opus/tools/wiki_debate.py @@ -66,6 +66,28 @@ async def _query(query: str, variables: dict = None) -> dict: return data.get("data", {}) +async def list_debates() -> list[str]: + """Wiki.js에서 debates/ 하위의 활성 토론 slug 목록을 조회.""" + query = """ + query { + pages { list(orderBy: UPDATED, orderByDirection: DESC) { + id, path, updatedAt + }} + } + """ + data = await _query(query) + pages = data.get("pages", {}).get("list", []) + slugs = set() + for p in pages: + path = p.get("path", "") + # debates/{slug}/input-* 형태의 페이지에서 slug 추출 + if path.startswith("debates/") and "/input-" in path: + parts = path.split("/") + if len(parts) >= 3: + slugs.add(parts[1]) + return sorted(slugs) + + async def read_page(path: str) -> str: """경로로 페이지 읽기 (singleByPath).""" query = """ @@ -143,6 +165,18 @@ async def main(): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") args = sys.argv[1:] + + # list-debates 커맨드는 인수 불필요 + if args and args[0] == "list-debates": + slugs = await list_debates() + if slugs: + print("활성 토론 목록:") + for s in slugs: + print(f" - {s}") + else: + print("진행 중인 토론이 없습니다.") + return + if len(args) < 2: print(__doc__) return diff --git a/docs/devlog/2026-03-22.md b/docs/devlog/2026-03-22.md index b1f510c..0ff07a3 100644 --- a/docs/devlog/2026-03-22.md +++ b/docs/devlog/2026-03-22.md @@ -1,3 +1,4 @@ | # | 시간 | 작업 | 커밋 | 상태 | |----|------|------|------|------| | 001 | 09:05 | debate-agent .env 생성 (gemini/opus Wiki.js API 키) | - | ✅ | +| 002 | 19:15 | debate-agent 대기 상태 처리 — idle-mode 규칙 + slug 탐색 + 금지 사항 강화 (7파일) | - | ✅ | diff --git a/handlers/debate_handler.py b/handlers/debate_handler.py index fd00473..9438db0 100644 --- a/handlers/debate_handler.py +++ b/handlers/debate_handler.py @@ -323,8 +323,11 @@ class DebateHandler: if not ch: return rd = self.session.round + slug = self.session.topic_slug await ch.send( - f"📥 **Round {rd}** — `input.md`를 읽고 `response.md`에 답변을 작성하세요." + f"📥 **Round {rd}** — slug: `{slug}`\n" + f"Wiki.js에서 `debates/{slug}/input-{speaker}`를 읽고 " + f"`debates/{slug}/response-{speaker}`에 답변을 작성하세요." ) async def _wait_for_response(self, speaker: str) -> str: