Skip to content
This repository was archived by the owner on Oct 1, 2026. It is now read-only.
yoonhoGoPublic archive

About

Life is a queue of quests.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Queuest

Life is a queue of quests.

게임 요소와 외부 연동의 의미는 퀘스트 시스템에 정의합니다. 퀘스트 편집에서 목표·이유·다음 행동, 메인/서브·반복·도전 분류, 외부 링크와 수행 시간을 저장하고 할 일 화면에서 미완료 퀘스트를 추적할 수 있습니다.

개인 프로젝트를 원정(프로젝트) → 스테이지(마일스톤) → 퀘스트(태스크)로 관리하는 macOS 메뉴바 앱입니다.

현재 레포는 Tauri 2 + React + TypeScript + SQLite 기반의 로컬 MVP입니다. 앱은 SQLite 인박스와 프로젝트 할 일 목록을 먼저 열고, 프로젝트 보드나 전역 캐릭터 탭에서 필요할 때만 전체 워크스페이스·프로젝트·마일스톤·태스크 그래프를 불러옵니다. 워크스페이스와 프로젝트·마일스톤·태스크 CRUD, 보드 상태 이동은 로컬 SQLite에 즉시 저장되고, 태스크 댓글·전역 캐릭터·프로젝트 장비 설정도 재실행 시 복원할 수 있는 저장 경계를 갖습니다. 메뉴바 팝오버는 포커스와 핀 상태를 반영하며 도구 상태를 확인합니다. 외부 연동은 @queuest/plugin-contracts의 버전 있는 프로토콜과 플러그인 아키텍처를 기준으로 확장합니다.

미리보기

macOS 메뉴바에서 Queuest 아이콘을 클릭하면 아이콘 바로 아래에 팝오버가 열립니다. 우클릭 메뉴로 열어도 같은 위치를 사용하며, 화면 좌우 경계를 넘지 않도록 배치합니다.

macOS 27 이상에서는 상태 항목에 native 메뉴를 연결할 때 클릭 이벤트가 잘못 전달되는 tray-icon 이슈 #355를 우회합니다. 이 환경에서는 좌·우 클릭 모두 Queuest 팝오버를 열고, macOS 26 이하에서는 기존 우클릭 native 메뉴를 유지합니다.

  • 상단의 할 일 / 프로젝트 / 캐릭터 / 설정 메뉴는 스크롤해도 유지됩니다.
  • 캐릭터 이름과 직업은 캐릭터 탭에서 전역으로 편집합니다. 경험치·레벨·스킬은 모든 프로젝트의 완료 기록을 합산하고, 프로젝트별 장비 설정은 프로젝트 설정에 남습니다.
  • 할 일 탭에서 개인 인박스와 모든 프로젝트의 퀘스트를 함께 확인할 수 있습니다. 프로젝트 퀘스트에서 프로젝트 보드와 외부 원본 링크로 바로 이동합니다.
  • 설정 화면에서 연결과 로컬 도구를 관리합니다. Jira 티켓, GitHub 이슈와 PR 리뷰 요청은 저장된 연결을 통해 주기적으로 확인하고 일반 퀘스트로 표시합니다. 수동 새로고침은 연결 설정에서 제공합니다. Calendar·EventKit 항목 가져오기는 후속 범위입니다.
  • 420px 창에서는 퀘스트 상태 보드를 세로로 표시합니다. 고정 버튼을 누르면 다른 앱으로 이동해도 창이 유지됩니다.

아래 이미지는 초기 디자인 미리보기로, 현재 화면 전환 메뉴와는 차이가 있습니다.

Queuest macOS 메뉴바 팝오버 미리보기

디자인 시스템

새 UI 기능은 디자인 시스템을 기준으로 구현합니다. 승인된 레트로 웹 미리보기, 공용 토큰·컴포넌트, 화면별 패턴과 검수 절차를 담고 있습니다. AGENTS.md에 구현 전 필수 참고 지침을 연결했습니다.

구조

apps/desktop              Tauri 셸과 React UI
packages/domain           순수 도메인 모델과 계산 규칙
packages/ports            저장소·에이전트 포트
packages/plugin-contracts 외부 플러그인 manifest·프로토콜·정규화 타입
packages/plugin-sdk       외부 프로세스 플러그인용 JSON 프로토콜 SDK
packages/plugin-manager  플러그인 발견·검증·수명주기·stdio 전송 런타임
packages/plugin-permissions 권한 정규화·승인 브로커·Credential Store 경계
packages/plugin-github   GitHub API 읽기 전용 process connector
packages/plugin-jira     Jira Cloud API 읽기 전용 process connector
packages/plugin-calendar Google Calendar 읽기 전용 process connector
packages/plugin-eventkit 공통 Swift EventKit native helper와 JSONL 경계
packages/plugin-apple-calendar Apple Calendar EventKit 읽기 전용 process connector
packages/plugin-apple-reminders Apple Reminders EventKit 읽기 전용 process connector
packages/adapter-sqlite   Tauri SQL 기반 로컬 SQLite 어댑터
packages/adapter-claude   claude -p 실행 어댑터
packages/adapter-github   GitHub 이슈 조회·Task 변환·원본 링크 어댑터

시작

npm install
npm run dev

Tauri 앱까지 실행하려면 다음을 사용합니다.

npm run tauri -- dev

검증 명령은 다음과 같습니다.

npm run check

CLI 설치

.app 번들을 /Applications에 복사하지 않고 CLI 진입점을 설치하려면 레포 루트에서 다음 명령을 실행합니다.

sh scripts/install.sh

기본 설치 위치는 $HOME/.local/bin/queuest이며, 다른 위치는 --prefix로 지정할 수 있습니다. 설치 스크립트는 웹 자산과 native helper를 준비한 뒤 Tauri 실행 파일을 $prefix/lib/queuest/queuest에 복사하고 queuest CLI를 $prefix/bin에 설치합니다. queuest를 인자 없이 실행하면 메뉴바 앱을 열고, 설정을 CLI에서 확인하거나 바꾸려면 다음 명령을 사용합니다.

queuest settings
queuest settings auto-update on
queuest settings launch-at-login on

앱의 설정 화면에서도 같은 자동 업데이트와 로그인 시 자동 실행 값을 편집할 수 있습니다. 앱 설정은 $HOME/Library/Application Support/Queuest/settings.json에 저장하며 credential은 저장하지 않습니다.

자동 업데이트는 서명된 Tauri 업데이트만 설치합니다. 업데이트 채널은 GitHub Releases의 latest.json을 사용하고, 릴리스 빌드에서는 apps/desktop/src-tauri/tauri.release.conf.json 과 TAURI_SIGNING_PRIVATE_KEY_PATH를 사용해 updater artifact를 생성해야 합니다. private key는 레포에 저장하지 않습니다.

기능 구현 순서는 ROADMAP.md에 기록되어 있습니다.

범위 메모

  • 엔티티 ID는 UUID 문자열을 사용합니다.

  • 상태는 todo → doing → review → done 네 가지입니다. blocked는 플래그입니다.

  • XP·레벨·스킬은 저장하지 않고 태스크와 마일스톤에서 계산합니다.

  • AI 실행 결과는 review로 돌아오며 done 처리는 사람의 몫입니다.

  • 외부 연동은 플러그인에서 앱으로 가져오는 단방향 흐름부터 둡니다.

  • 플러그인 탭에서 GitHub·Jira·Google Calendar·Apple EventKit 연결 프로필을 저장하고 다시 편집·삭제할 수 있습니다. 연결 메타데이터와 캘린더 ID는 SQLite에, API token과 access token은 com.yoonhogo.queuest.credentials.plugin.<pluginId>.<connectionId> 규칙의 macOS Keychain에 저장하며, 토큰은 웹 화면이나 SQLite로 되돌려 읽지 않습니다. Google Calendar의 OAuth 동의·token refresh와 Apple EventKit TCC 요청 화면은 후속 범위입니다.

  • GitHub connector는 com.queuest.github plugin namespace와 connectionId를 조합한 Credential Store 항목을 읽고, GitHub REST GET만 수행합니다. 앱에서는 프로젝트의 repoPath와 gh 인증을 통해 이슈를 읽어 선택한 스테이지의 로컬 Task로 저장하며, externalRef로 중복을 막고 원본 URL을 보존합니다. GitHub에 쓰는 흐름은 읽기 전용 범위 밖입니다.

  • Jira Cloud connector는 com.queuest.jira plugin namespace와 connectionId로 Credential Store 항목을 읽고, 다음 JSON credential을 사용합니다. siteUrl은 baseUrl로 대체할 수 있으며 둘 다 있으면 같은 값이어야 합니다.

    {"siteUrl":"https://<tenant>.atlassian.net","email":"account@example.com","apiToken":"<token>"}

    기본 macOS Keychain namespace는 service com.yoonhogo.queuest.credentials.plugin.com.queuest.jira, account com.yoonhogo.queuest.credentials.plugin.com.queuest.jira.<connectionId>입니다. HTTPS Atlassian Cloud subdomain(*.atlassian.net) origin만 허용하며 path·port·query·fragment· userinfo나 임의 host는 거부합니다. manifest의 network: ["*.atlassian.net"]와 secrets: ["jira"]를 모두 승인한 뒤에만 credential/API를 사용하고, email과 API token으로 Basic auth를 구성해 /rest/api/3/search/jql(POST)과 /rest/api/3/myself(GET)만 호출합니다. project JQL과 bounded opaque nextPageToken pagination을 사용해 Jira issue를 ExternalWorkItem으로 매핑하며, ADF 또는 문자열 description·labels·updatedAt·status category·browse URL을 보존합니다. health.check는 초기화·권한만 확인하고 credential/API를 읽지 않으며, credential/auth/not-found/rate-limit/HTTP/malformed/network 실패는 token을 노출하지 않는 typed error와 connection state로 전달합니다. 연결 설정은 플러그인 탭에서 저장합니다. 데스크톱 UI 가져오기는 아래의 별도 native Host adapter를 사용합니다. provider write, OAuth/3LO, self-hosted Jira/Data Center는 지원하지 않습니다.

  • Google Calendar connector는 com.queuest.calendar plugin namespace와 connectionId를 조합한 Credential Store 항목을 읽고, 다음 JSON credential의 accessToken만 사용합니다.

    {"accessToken":"<oauth-access-token>"}

    기본 macOS Keychain namespace는 service com.yoonhogo.queuest.credentials.plugin.com.queuest.calendar, account com.yoonhogo.queuest.credentials.plugin.com.queuest.calendar.<connectionId>입니다. manifest는 network: ["www.googleapis.com"]와 secrets: ["calendar"]만 선언하며 filesystem 권한은 없습니다. 두 권한을 모두 승인한 뒤에만 credential/API를 사용하고, 고정된 Google Calendar API에서 기간·캘린더별 일정 목록을 GET으로 조회합니다. timed/all-day event와 confirmed·tentative·cancelled 상태, 원본 URL·수정 시각을 ExternalCalendarEvent로 매핑하며 maxResults=2500과 bounded opaque page cursor를 사용합니다. health.check는 초기화·권한만 확인하고 credential/API를 읽지 않으며, connection.status만 credential을 읽어 primary calendar를 확인합니다. credential/auth/ not-found/rate-limit/HTTP/malformed/network 실패는 token을 노출하지 않는 typed error와 connection state로 전달합니다. OAuth 동의·authorization code 교환·token refresh와 accessToken을 Credential Store에 넣는 provisioning은 Host/UI 경계이며 이 read-only connector에 포함하지 않습니다. 연결 설정은 플러그인 탭에서 access token을 Keychain에 보관할 수 있지만, 일정 쓰기, UI import, CalendarEvent 저장과 Task 변환은 아직 연결하지 않습니다.

  • Apple EventKit connector는 com.queuest.apple-calendar와 com.queuest.apple-reminders 두 개의 process plugin으로 제공됩니다. 각각 source.calendar-events 또는 source.work-items capability와 macos.eventkit.calendar 또는 macos.eventkit.reminders platform permission만 선언하며, network·secret·filesystem 권한과 OAuth credential을 요구하지 않습니다. Host의 Permission Broker 승인이 process spawn보다 먼저 필요하고, 그 다음에도 macOS의 EventKit TCC 사용자 승인이 별도로 필요합니다.

    EventKit은 읽기 전용 권한을 제공하지 않으므로 일정과 미리알림 목록을 읽으려면 macOS 14 이상에서 각각 full access를 허용해야 합니다. Swift helper는 requestFullAccessToEvents/requestFullAccessToReminders를 사용하고, 구버전 macOS에서는 호환용 requestAccess로 폴백합니다. TCC 요청은 tcc.request-access에서만 수행하며, health.check는 권한을 자동으로 요청하지 않습니다. 앱과 helper에는 NSCalendarsFullAccessUsageDescription·NSRemindersFullAccessUsageDescription가 포함되고, 샌드박스/하드닝 배포에는 Calendar entitlement와 사용자 승인이 함께 필요합니다.

    native helper는 packages/plugin-eventkit/native/build.sh가 EventKit 프레임워크와 usage-description Info.plist를 함께 빌드하고 로컬에서는 ad-hoc 서명합니다. Tauri bundle은 Contents/Resources/eventkit/queuest-eventkit으로 helper를 포함합니다. 배포용 서명은 앱과 같은 Team ID의 Developer ID identity를 지정해야 합니다.

    npm run build:native --workspace @queuest/plugin-eventkit
    QUEUEST_EVENTKIT_CODESIGN_IDENTITY="Developer ID Application: <name> (<team-id>)" \
      npm run build:native --workspace @queuest/plugin-eventkit
    npm run tauri -- build

    현재 EventKit plugin은 로컬 EventKit 데이터의 목록 조회와 연결/TCC 상태 확인을 구현합니다. 플러그인 탭에서 비밀 없는 연결 ID와 Calendar ID를 저장할 수 있으며, OAuth 동의·authorization code·refresh token·Keychain provisioning은 필요하지 않습니다. TCC 요청 안내, 일정/미리알림 UI, CalendarEvent·Task 저장과 중복 제거, 외부 데이터 생성·수정·삭제(write)는 아직 Host/UI 범위에 연결하지 않았습니다.

  • 커밋·푸시·클라우드 동기화·팀 공유는 이 초기화 범위에 포함하지 않습니다.

Jira·GitHub 백그라운드 작업 확인

  • 설정 → 연결 설정에 Jira 또는 GitHub 연결을 저장합니다. Jira는 사이트·이메일·API token·프로젝트 키, GitHub는 저장소(owner/repository)·PAT를 사용합니다. 인증 정보는 macOS Keychain에 보관합니다.
  • 앱 시작, 연결 저장 직후, 앱 실행 중 5분마다 새 작업을 읽습니다. 메뉴바 팝오버를 닫아도 앱이 실행 중이면 계속 확인하며 앱 종료·기기 잠자기 중 실행은 보장하지 않습니다. 설정에서 새로고침, 최근 전체 성공 시각과 연결별 오류를 확인합니다.
  • Jira는 설정된 프로젝트 티켓을 페이지별로 조회합니다. 보드 ID가 있으면 백로그를 미수락 퀘스트로 보존합니다. GitHub는 저장소 이슈와 해당 저장소에서 나에게 요청된 열린 PR 리뷰를 조회합니다.
  • 새 작업은 연결별 원정의 퀘스트 스테이지에 저장합니다. 전체 원정에서 externalRef로 중복을 막으며, 이미 저장된 작업은 사용자가 편집한 내용·위치·완료 상태를 유지합니다. 따라서 외부 변경을 기존 퀘스트에 덮어쓰는 양방향 동기화는 아닙니다. 삭제한 외부 퀘스트는 다음 조회에서 다시 나타날 수 있습니다.
  • 외부에서 완료된 Jira·GitHub 이슈도 검토 대기로 저장하고 완료는 사용자가 확인합니다. PR 리뷰 요청은 대기 퀘스트로 저장됩니다.
  • 한 번에 하나의 동기화만 실행합니다. 연결별 최대 100페이지, 페이지당 최대 100개를 조회하며 실패 전 저장된 항목은 재시도해도 중복되지 않습니다.

네이티브 Host는 고정 HTTPS API, 리다이렉트 금지, 요청당 30초 제한과 8 MiB 응답 제한을 사용합니다. API token이나 원격 오류 본문은 화면에 반환하지 않습니다. GitHub 연결 동기화는 작업 폴더나 gh 인증을 사용하지 않습니다.

About

Life is a queue of quests.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages