Skip to content

feat(orchestrator): implement runnable v1 autonomous mobile loop#1

Open
ert93333-ops wants to merge 43 commits into
mainfrom
codex/task-title
Open

feat(orchestrator): implement runnable v1 autonomous mobile loop#1
ert93333-ops wants to merge 43 commits into
mainfrom
codex/task-title

Conversation

@ert93333-ops

Copy link
Copy Markdown
Owner

Motivation

  • Provide a runnable Python v1 orchestrator under orchestrator/ that connects OpenAI Planner, Codex CLI, Manus QA and Telegram to enable a 24/7 automated mobile-first development loop.
  • Enforce operational rules in code: mobile-first, one small task per loop, ko/ja i18n checks for UI/text, screenshot-required for UI validation, minimal edits, and automatic rollback after 3 repeated failures.
  • Make the system deployable with only environment/config values to fill, and reduce environment-specific coupling by externalizing CODEX_CMD and using robust config loading.

Description

  • Added an executable entrypoint orchestrator/bot.py implementing the main state machine, loop, Telegram command handlers and rollback logic, including branch-safety checks to forbid running on main/master.
  • Implemented Planner integration in orchestrator/planner.py calling the OpenAI Responses API, extracting and validating planner JSON output, and gating research_request when blockers exist.
  • Implemented Codex runner orchestrator/codex_runner.py as a subprocess wrapper supporting CODEX_CMD with optional {prompt_file} placeholder, logging stdout/stderr, collecting git diff/HEAD SHA, and timeout handling.
  • Implemented Manus QA runner orchestrator/manus_runner.py with task creation/polling, JSON-first parsing and regex/recursive fallback screenshot URL extraction, returning structured QA reports.
  • Added persistent state store orchestrator/state_store.py and utilities orchestrator/utils.py for config loading (UTF-8 then cp949 fallback), safe JSON writes, git helpers and helpers like extract_screenshot_urls and render_template.
  • Added Telegram polling helper orchestrator/telegram_handler.py, prompt templates in orchestrator/prompts/, config.txt.example, state.json.example, logs/.gitkeep, reports/.gitkeep, and an updated orchestrator/README.md documenting setup and usage.
  • Enforced: UI-task success requires Manus screenshot URL, retry counting and automatic rollback after 3 failures, minimal-change principle in Codex prompts, and research-request workflow that only activates when no rollback blockers are present.

Testing

  • Ran syntax checks with python -m py_compile orchestrator/bot.py orchestrator/utils.py orchestrator/state_store.py orchestrator/planner.py orchestrator/codex_runner.py orchestrator/manus_runner.py orchestrator/telegram_handler.py, which completed successfully.
  • Verified repository commit and stats with git show --stat --oneline HEAD to confirm files and changes were recorded successfully.
  • No automated integration tests for external services were run in this pass (Manus/Codex/OpenAI/Telegram require live credentials), so runtime validation requires populating config.txt and running python bot.py --config config.txt --state state.json in a non-main/master branch.

Codex Task

Lito Dev and others added 30 commits April 15, 2026 08:15
- Add ENVIRONMENT_SETUP.md: full guide for env vars, DB, EAS build, and store submission
- Add artifacts/api-server/.gitignore: exclude .env from version control
- Add artifacts/lito/eas.json: EAS Build profiles for iOS/Android (development/preview/production)

DB status:
- PostgreSQL 14 installed and running
- lito_db created with lito_user
- Drizzle schema pushed successfully (12 tables)
  - users, user_profiles, oauth_accounts
  - swipe_likes, swipe_passes, matches
  - conversations, messages, chat_messages, direct_messages
  - user_reports, user_blocks

[checkpoint] pre-launch env + DB setup complete
- fix(ai): gpt-5.2, gpt-4.1-mini → gpt-4o-mini 모델명 일괄 수정 (6개 엔드포인트)
- feat(auth): JWT payload에 plan 필드 추가 (free/plus/premium)
- feat(db): users 테이블에 plan 컬럼 추가 (default: free)
- fix(auth): 모든 signToken 호출에 plan 필드 포함 (auth, oauthCallback, socialAuth)
- feat(security): requireAdmin 미들웨어 추가 (ADMIN_TOKEN 헤더 검증)
- fix(security): /api/admin/* 엔드포인트에 requireAdmin 미들웨어 적용
- docs: 점검 보고서 5종 추가 (AI코치, AI시스템, 매칭, 소셜로그인, 런칭준비)
- feat(api): GET /api/chat/conversations 엔드포인트 추가
  - 로그인 유저의 모든 매칭 대화방 목록 반환
  - 상대방 프로필, 마지막 메시지, 안읽은 메시지 수 포함
  - 대화방 ID 규칙: conv_{min(userId, partnerId)}_{max(userId, partnerId)}
- fix(client): AppContext 대화방 초기값을 Mock 데이터에서 DB API로 교체
  - 앱 시작/로그인 시 fetchConversations() 자동 호출
  - AI 페르소나 대화방은 로컬 유지 (DB 매칭 아님)
  - likeUser 매칭 성사 시 대화방 ID를 서버와 동일한 규칙으로 생성
  - 불필요한 mockMessages, mockMessagesConv3 import 제거
  - mockMatches 초기값 제거 (DB에서 로드)
## 슈퍼 라이크 (Super Like)
- DB: swipe_likes 테이블에 is_super 컬럼 추가
- API: POST /api/users/:id/like에 isSuper 파라미터 지원
- API: GET /api/users/super-like-status 잔여 횟수 조회 엔드포인트
- 플랜별 일일 한도: free=1회, plus=3회, premium=5회
- 한도 초과 시 429 에러 반환
- UI: 스와이프 화면 별 버튼에 잔여 횟수 뱃지 표시
- UI: 한도 초과 시 비활성화 + 햅틱 경고

## 읽음 표시 (Read Receipt)
- DB: chat_messages 테이블에 read_at 컬럼 추가
- API: PUT /api/chat/:conversationId/read 읽음 처리 엔드포인트
- API: GET /api/chat/:conversationId/unread-count 안읽은 수 조회
- API: conversations 목록의 unreadCount를 readAt 기반으로 정확하게 계산
- WebSocket: type=read 이벤트로 실시간 읽음 처리 + read_receipt 브로드캐스트
- UI: 카카오톡 스타일 '1' 표시 (안읽음=금색 1, 읽음=표시 없음)
- 대화방 입장 시 자동 읽음 처리 (WS + REST 이중 보장)
## 개인정보처리방침 (Privacy Policy)
- 한국 개인정보보호법 2025년 지침 기준 전면 보강
  - 수집 항목/방법, 이용 목적, 보유 기간 상세 기재
  - 파기 절차 및 방법 추가
  - 국외 이전 (GCP, OpenAI) 명시
  - 쿠키 자동수집 장치 안내
  - 14세 미만 아동 관련 사항
- 일본어 완전 번역 (個人情報保護法 APPI 기준)
- 한국어/日本語 탭 전환 UI

## 이용약관 (Terms of Service)
- 전 10조 구성 (목적, 자격, 계정보안, 금지행위, 저작권, AI면책, 서비스제한, 면책, 유료서비스, 준거법)
- 로맨스 스캠 등 데이팅앱 특화 금지행위 명시
- 유료 서비스 환불 정책 (앱스토어 정책 준거)
- 일본어 완전 번역
- 한국어/日本語 탭 전환 UI

## 앱 내 연동
- settings.tsx: 개인정보 보호정책 + 이용약관 링크 연결 (Linking.openURL)
- login.tsx: 로그인 화면 약관/개인정보 텍스트에 실제 URL 연결
- AppContext.tsx: mockData.ts import 제거, API 기반 상태관리로 전면 리팩터링
  - fetchDiscover(): GET /api/users/discover → discoverUsers 상태
  - fetchConversations(): GET /api/chat/conversations → conversations/matches 상태
  - loadConversationMessages(): GET /api/chat/:id/messages → messages 상태
  - 로딩/에러 상태 추가 (discoverLoading, discoverError, matchesLoading)
  - profile 초기값을 빈 객체로 변경 → /api/auth/me에서 hydrate
  - AI 페르소나 대화방 데이터를 aiPersonas.ts로 독립 분리

- discover.tsx: discoverError 에러 상태 UI 추가 (네트워크 실패 시 재시도 버튼)
- matches.tsx: matchesLoading 로딩 상태 추가, 화면 포커스 시 fetchConversations 호출
- chat/[id].tsx: CURRENT_USER_ID='me' 하드코딩 제거 → profile.id 기반으로 전환
- prsSignals.ts: MY_ID 상수 제거, 함수 파라미터 기반으로 전환

검증: mockData.ts import 참조 0건, 전체 파일 TypeScript 문법 검증 통과
…e flag 격리 + 증빙 문서

변경 사항:
- AppContext.tsx: WebSocket 지수 백오프 재연결 + AppState 백그라운드 복귀 리스너
- ProfileImage.tsx: onError fallback placeholder + 로딩 상태 + prefetch 유틸
- apiClient.ts (신규): HTTP 401/403/429/5xx 분기 + 자동 재시도 유틸
- photoUpload.ts: 상태코드별 세분화된 에러 메시지 + 재시도 로직
- users.ts: ENABLE_AI_PERSONAS / ENABLE_DEMO_USERS feature flag
- AppContext.tsx: EXPO_PUBLIC_ENABLE_AI_PERSONAS feature flag
- 증빙 파일 3개 + close-out 문서
- objectStorage.ts: Replit 사이드카 의존 완전 제거, GCS Service Account 기반 + 로컬 폴백
- storage.ts: presigned URL + 로컬 업로드 + 삭제 + 서빙 엔드포인트 정비
- profile-edit.tsx: 다중 사진 관리 UI (최대 6장, 삭제, 순서 변경, 업로드 실패 재시도)
- profile-setup.tsx: 업로드 실패 재시도 UX 추가
- photoUpload.ts: 401/403/429 분기 + 자동 재시도 (지수 백오프)
- 전체 프론트엔드: localhost:8080 → localhost:3000 통일
- docs/GCS_BUCKET_SETUP.md: GCS 버킷 설정 가이드
- profile-setup.tsx: 성별 선택 UI 추가 (남성/여성/논바이너리/기타)
- profile-setup.tsx: 관심 대상 선택 UI 추가 (남성/여성/모두)
- userProfiles.ts: genderIdentity -> preferredGender로 변경
- auth.ts: PUT /api/auth/profile에 gender, preferredGender 추가
- users.ts: discover 라우트에 preferredGender 필터링 로직 추가
- Add gender and preferredGender to MyProfile type
- Update AppContext with new fields in ServerProfile interface
- Map gender/preferredGender in serverToMyProfile function
- Update profile-setup.tsx to handle gender selection (남성/여성/모두)
- Disable EAS updates in app.json and eas.json
- Add static build artifacts
- lib/integrations-openai-ai-server: add @types/node devDependency
- FIcon.tsx: add missing icons (mail, wifi-off, arrow-up, copy)
- discover.tsx: fix diagnosisBanner style ref (styles→filterStyles), wrap refetchDiscover in arrow fn
- chat/[id].tsx: fix moreBtn style ref (styles→popup)
- AppContext.tsx: move connectWS before useEffect to fix hoisting error, add readAt/messageIds to WS msg type
- api-server/users.ts: add gender/preferredGender fields to ServerUser interface
- api-server/storage.ts: fix objectId and content-type type errors

All typecheck passes with 0 errors.
- orchestrator.py: 메인 자동화 루프 (GPT 지시 → Codex 코딩 → Manus 테스트 → 반복)
- gpt_browser.py: Playwright 기반 ChatGPT LITOproject & Codex 브라우저 자동 조작
- manus_client.py: Manus API v2 클라이언트 (task.create, task.detail, task.listMessages)
- .env.example: 환경변수 템플릿
- README.md: 설치 및 사용 가이드

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ad52c8ff2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread orchestrator/planner.py Outdated
Comment on lines +85 to +87
output_text = body.get("output_text")
if not output_text:
output_text = json.dumps(body, ensure_ascii=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Parse planner text from output instead of SDK-only field

This code expects output_text in the raw /v1/responses HTTP payload, but that field is SDK-only; when it is missing, the fallback serializes the entire response object and _validate_plan fails because plan keys are not at the top level. As a result, the planner can fail every loop even when the model produced valid JSON text in output, blocking the orchestrator from ever reaching Codex/Manus execution.

Useful? React with 👍 / 👎.

else:
cmd = f"{base_cmd} < {prompt_file}"

result = run_command(cmd, cwd=self.repo_path, timeout=timeout_seconds)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Convert Codex timeouts into retryable failures

This subprocess call can raise TimeoutExpired via run_command(..., timeout=...), but the timeout path is not handled here and bubbles to the top-level exception handler. In that path do_one_iteration never increments retry_count, so repeated Codex hangs do not reach the 3-failure rollback path and the loop can get stuck retrying forever without automatic recovery.

Useful? React with 👍 / 👎.

Comment thread orchestrator/bot.py
Comment on lines +252 to +255
plan = self.state.get("current_task")
if not plan:
plan = self.generate_plan()
if self.state.get("current_state") == "RESEARCH_REQUESTED":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pause task execution while research input is pending

The wait-for-research behavior only runs when current_task is newly created; on the next loop, current_task is already set so the code immediately proceeds to run_codex even though state is RESEARCH_REQUESTED. This skips the intended user-input gate and can execute tasks that were explicitly marked as requiring external research before implementation.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant