Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions docs/v0-1-40-backlog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# v0.1.40 작업 목록

> v0.1.39 발행(2026-08-03) 이후 확정. 유건 지시 5건이 머리고, 나머지는 v0.1.39 배치와 QA 조사에서 나온 이월이다.
> 각 항목은 **왜 하는지**와 **어디까지 실측했는지**를 함께 적는다 — 미검증을 검증된 것처럼 물려주지 않기 위해.

## 1. 루틴 생성 — 한 줄만 써도 설계된 루틴이 나오게 (유건 지시 2026-08-05)

**왜**: 지금은 사장이 입력한 문장이 **그대로** 크루에게 전달된다. "Claude Code 루틴"이 그렇듯, 목적을 읽고
필요한 절차·판단 기준·산출물 형식까지 짜 주는 것이 이 기능의 값인데 현재는 전달자에 그친다.

**설계 방향**
- 루틴 저장 시점에 **한 번** 목적 맥락을 확장한다(매 실행마다가 아니라 — 실행마다면 비용이 주기마다 곱해진다).
- 원문은 반드시 보존한다. 확장본은 별도 필드로 두고 화면에서 **둘 다 보이게** 한다 —
사장이 "내가 쓴 게 아닌 지시"를 발견하는 일이 없어야 한다(via 표식 신고 2026-07-28과 같은 계열).
- 확장은 러너 중립이어야 한다. SDK 크루만 좋은 루틴을 얻으면 그 자체가 편파(러너 중립성 원칙).
확장은 서버가 oneshot으로 수행하고 결과를 저장하는 쪽이 자연스럽다.
- 화면에 이미 "말로 쓰면 자동 설정" 입력이 있다(자연어 → 주기·시각 파싱). **그 자리를 확장한다** —
새 UI를 만들지 말고 같은 문에서 주기·시각과 함께 본문까지 짜 준다.

**검증**: 같은 한 줄("매일 아침 인스타 댓글 확인하고 정리해줘")로 만든 루틴이 확장 전/후에 어떤 결과를
내는지 실제 턴으로 비교. 빌드 통과는 증거가 아니다.

## 2. '추천 Top 20' 문구 교체 (유건 지시 2026-08-05)

실제 항목 수가 20개가 아닌데 화면은 `추천 Top 20`이라고 단정한다 — 거짓 표기다.

- 자리: `app/i18n.jsx:1042` `'market.topLabel': ['추천 Top 20 · {source}', 'Top 20 Recommended · {source}']`
- 교체: `추천 스킬` / `추천 플러그인`처럼 개수를 말하지 않는 문구로(ko·en 둘 다).
- 같은 화면에 개수를 단정하는 다른 문구가 더 있는지 함께 훑는다(3번 스윕과 묶어도 된다).

## 3. 영문 사용자 피드백 오류 (유건 지시 2026-08-05)

**제보**: 영문 사용자가 피드백을 보낼 때 오류가 난다는 이야기가 있다. **재현 미확인** — 제보 원문·환경을
아직 특정하지 못했다.

**조사 시작점(코드 실측 2026-08-05)**
- `app/api/feedback/route.js`의 오류 응답 4곳이 **한국어 하드코딩**이다(35·37·40·71행).
다국어 상시 규칙 위반이고, 어딘가 이 문구가 그대로 노출되면 영문 사용자에겐 깨진 화면으로 읽힌다.
- 다만 `FeedbackModal`은 자기 `t('feedback.error')`를 쓰므로(`app/ui.jsx:580`) **모달 안에서는** 서버 문구가
안 보인다 → 위 하드코딩이 신고의 원인이라고 단정할 수 없다. 별개로 고치되, 진짜 원인은 따로 찾는다.
- 다음 확인 순서: 제보 원문 확보 → 영문 로케일에서 실제 전송 재현 → 실패 시 서버 로그(`insert 실패` 코드).

## 4. 모니터링 강화 — 개선 근거를 우리가 먼저 갖기 (유건 지시 2026-08-05)

**왜**: 지금 우리는 **활성 사용자를 제대로 못 센다.** 로컬 우선 제품이라 턴이 서버에 안 남고, 셀 수 있는 건
로그인 이벤트(`last_sign_in_at`)뿐인데 그마저 세션이 유지되면 갱신되지 않는다 — 실측 2026-08-04:
08-04에 제보한 사용자의 마지막 로그인이 07-27로 찍혀 있었다. 즉 현재 수치는 **활성의 하한**이다.

**모을 것**(최소 침습 — 개인정보·본문 금지)
- 접속: 일시, OS·앱 버전, 언어
- 사용: 턴 수(집계값만), 쓰는 러너·모델, 실패 종류(코드 단위)
- **원칙**: 대화 내용·파일 경로·프롬프트는 절대 올리지 않는다. 로컬 우선 제품의 약속이 먼저다.

**DB 부담 최소화**
- 행을 턴마다 만들지 않는다. **기기별 1행을 upsert**하고 카운터를 누적하는 형태(일 단위 롤업)로.
2026-07-26 사고가 정확히 이 반대였다 — `storage.search`가 8초마다 돌아 DB CPU 80%를 찍었다.
- 전송 주기를 상수로 두고 주석에 **"100명이면 분당 몇 회"**를 숫자로 적는다(출하 관문 0.5 규모 질문).
- 실패해도 제품 동작에 영향이 없어야 한다(사본 원칙 — 피드백 이슈 미러링과 같은 계약).

**선행**: 사용자에게 무엇을 모으는지 알리는 표기. 동의 없이 늘리지 않는다.

## 5. 기기 리스 공백 — 리더가 꺼지면 최대 2분 (유건 지시 2026-08-05, 백로그 승격)

**증상**: 텔레그램 봇과 예약 루틴은 **리더 기기 한 대**에서만 돈다(봇 토큰 하나에 폴러 하나 — 텔레그램 규격).
리더가 꺼지면 리스 만료(120초) + 다음 사이클(8초) + 게이트웨이 재점검(10초) ≈ **최대 2분 20초** 동안
어느 기기에서도 안 돈다. 새 기기에 러너 자격이 없으면 양보 로직 때문에 **최대 5분**까지 늘어난다.

- 근거: `src/sync.mjs:35·57·179-181·210-224`, `src/gateway.mjs:806·859-862·926`,
선행 기록 `docs/ux-sweep-backlog-2026-07-17.md:54`
- 메시지 유실은 없다(at-least-once, `src/gateway.mjs:322-324`) — **지연**만 문제다.
- 방향: 정상 종료 시 리스를 **명시적으로 반납**하면 2분이 몇 초로 준다. 비정상 종료(전원 차단)는
여전히 TTL을 기다려야 하므로 TTL 단축과는 별개 트레이드오프(짧게 잡으면 일시적 네트워크 끊김에
리더가 튄다 — 이중 실행 위험). 반납부터 하고 TTL은 건드리지 않는 쪽을 권한다.

## 5-B. 구독 관리 — 서버 창구로 이전 (유건 지시 2026-08-05, **결제 개시 전 필수**)

**정본 설계: `docs/billing-portal-design.md`**

데스크톱 앱은 사용자 기기에서 Next 서버를 돌린다. `LEMONSQUEEZY_API_KEY`를 릴리스 빌드에 넣으면
**전 사용자에게 결제 API 키가 배포되고**, 안 넣으면 구독 관리 링크가 죽는다(실측 2026-08-05:
릴리스 CI에 없음 → 데스크톱에서 `결제 연동이 아직 설정되지 않았습니다`).

**지금 결제를 열면 결제는 되는데 해지·카드 변경을 못 한다.** 환불·분쟁으로 돌아온다.

- 해법: Supabase Edge Function `ls-portal`(웹훅과 같은 인프라) + 키는 Supabase secret으로만
- 상태의 단일 진실을 `entitlements`로 모아 로컬 서버가 LS를 직접 호출하지 않게 한다
- 키가 앱 산출물에 없음을 테스트로 잠근다 — 그 순간이 이 설계가 무너지는 순간이다
- **선행 조건**: 이게 끝나기 전에는 실결제를 열지 않는다

## 5-C. 체험 임박 알림을 설정 밖으로 + 딥링크 (유건 지시 2026-08-05)

지금 체험 임박(D-3) 안내는 **설정 페이지 안에서만** 뜬다(`trialImminent`가 settings에만 존재).
사용자가 설정에 안 들어가면 만료될 때까지 아무 말도 못 듣는다.

- 설정 밖(사이드바 하단 또는 상단 바)에 임박 알림을 노출
- 알림 → `/c/{ws}/settings?billing=1` 딥링크로, **그 카드까지 스크롤 + 잠깐 강조**
(선례: 러너 연결 안내가 `?ai=1`로 들어와 `scrollIntoView` — `settings/page.jsx:37-40`)
- **결제 직행 대신 설정 경유**를 택한 이유: 결제창엔 맥락이 없고, 같은 카드의 '자료 내보내기'
선택지가 감춰지며, 링크에 `user_id`를 붙이는 경로가 하나로 유지된다

## 6. 기억 그래프 — 인터랙션 재작업 (유건 지시 2026-08-04)

지금 것은 **회전하는 그림**이지 그래프 뷰가 아니다. 코드 실측(2026-08-04):

- **이웃 강조·감광이 0건** — hover는 간선만 굵게 그린다. 옵시디언에서 시냅스처럼 느껴지는 감각의 본체가 없다.
- **카메라가 카메라가 아니다** — 초점거리 `f = 460`·깊이 오프셋 `z + 260` 하드코딩, 줌은 화면 스케일 배수라
**카메라 거리를 못 움직인다**(`app/c/[ws]/graphview.jsx:143·149·151`).
- 그래서 노드 반지름이 `Math.min(view.zoom, 1.4)`로 **상한**이라 확대해도 밀도가 안 풀린다(같은 파일 202행).
- **v0.1.39가 자동 맞춤을 이월한 진짜 이유가 이것이다** — 카메라를 못 움직이니 "위치만 축소 / 위치+크기 축소"
같은 편법만 남았고 둘 다 깨졌다. 원인을 잘못 짚고 이월했다(정정).
- 라벨 LOD 없음(타입 고정), 노드 드래그 없음, 검색·필터 없음.

**할 것**
- 카메라 거리를 상태로 올린다 → 투영 `k = f/(f + z + dist)`, 휠 = `dist` 변경.
화면 맞춤은 공식 한 줄이 된다: 바운딩 구 반지름 r에서 `dist = r / tan(fov/2)`. 반지름 상한도 제거.
- hover → 1홉 이웃만 정상 알파, 나머지 감광(인접 리스트는 차수 계산 자리에서 함께 만든다).
- 클릭 → 그 노드로 카메라 이동 + 로컬 모드(주변 1~2홉).
- 줌 레벨별 라벨, 노드 드래그로 집기, 검색어 → 매치 발광 + 카메라 이동.
- 집계(폴더·시기 단위 접기)는 **위가 끝난 뒤 선택지로** 얹는다. 대체재로 내지 않는다.

**검증**: 노드 1,800개(실제 데이터 규모)에서 띄워서 눈으로. 프레임 유지·라벨 가독·클릭 후 이동.

## 7. 안내 문구 전수 스윕 (유건 지시 2026-08-04)

같은 계열 결함이 반복된다 — Grok 크레딧을 "인증 실패"로(2026-08-03 신고), 윈도우 러너 크래시를
"AI 연결 확인"으로(v0.1.39에서 수정), codex 401·Gemini 정책 폐기도 같은 모양이었다.

**대상**: 사용자에게 보이는 실패·거부 문구 전부 — 러너별 벤더 오류(401·402·403·429·5xx·타임아웃·크래시),
자격 저장/검증, 동기화 실패, 요금제·결제, MCP·스킬 미지원, 게이트·결재 거부, 메신저 전달 실패.

**방법(두 방향 교차 — 한쪽만 하면 샌다)**
1. 코드에서 사용자 문구를 만드는 지점을 전수 열거하고, 문구마다 "이게 참이려면 무엇이 사실이어야 하는가"를 적는다
2. 벤더가 실제로 주는 응답을 무자격 프로브로 모아(2026-08-03 xAI에 한 방식) 우리 번역과 대조한다

**판정 게이트 셋**
- **중립성**: 같은 사정인데 러너별로 안내 품질이 다르면 그 자체가 결함
- **정직성**: 확인 안 된 원인을 단정하지 않는다 — 사용자가 엉뚱한 곳을 고치게 된다
- **갈 곳**: "안 됩니다"로 끝나면 미완성. 다음 행동(충전·재연결·다른 엔진)을 준다

## 8. 피드백에 앱 버전 자동 첨부

**왜**: 제보 17건의 버전을 몰라 원인 추적에 하루를 썼다(2026-08-04~05). UA에는 OS만 있고 앱 버전이 없다
(`meta.ua` 실측 — Tauri WebView 표준 UA뿐).

**할 것**: 서버가 이미 아는 버전을 저장 시 `meta`에 함께 넣는다. 한 줄이다. 4번 모니터링의 선행 조각이기도 하다.

## 9. 기억 검색 — FTS5 (P1b, 이월)

설계는 이미 있다(`docs/memory-store-design.md` §5-2·5-3): `node:sqlite`가 FTS5까지 도는 것 실증,
스키마 초안(`docs_fts … tokenize='trigram'`)과 한국어 토크나이저 근거까지 적혀 있다. **미착수**.

지금 크루의 검색 수단은 `Grep` 도구 + `_index.md`뿐이고(`src/chat.mjs:250`), 인덱스는 메타데이터 캐시만
담는다(`src/memindex.mjs` — `docs(rel, kind, title, links, updated)`). 문서가 수천 건이 되면 여기가 병목이다.

**전에 막혀 있던 것**: FTS를 붙여도 크루가 쿼리할 도구가 없었고, 도구를 노출하면 SDK 러너만 쓸 수 있어
편파가 됐다. **이제 해소됐다** — ```` ```argo tool ```` 지시 블록(`src/cli-directives.mjs`)이 CLI 러너에도
도구 통로를 열었다. 커넥터 US-3/US-4와 같은 구조로 두 표면에 같은 코어를 붙일 수 있다.

## 10. 운영 — 제보자 회신 (코드 아님)

v0.1.39 + 신규 설치 Windows에서 쓰기 차단이 **재현되지 않았다**(2026-08-05 실측: codex 샌드박스 정상,
제품 경로로 파일 생성 성공). 제보 17건 중 14건이 v0.1.36(전권 출하) 이전이다.

1. **08-03·08-04 제보자 2명에게 버전 문의** — 최신에서도 나는지가 유일한 미확정
2. **전체 제보자에게 업데이트 안내** — 대부분 막힌 뒤 재로그인 기록이 없다(이탈 신호)

## 11. v0.1.39 이월 (미검증으로 발행한 것들)

- **Grok 모델 id 실턴 스모크** — 카탈로그 규칙("실턴 통과분만 등재")의 예외 상태. xAI 자격 필요
- **깃헙 이슈 미러링 라이브 확인** — `ARGO_GITHUB_ISSUE_TOKEN` 필요. 넣기 전까지 기능은 꺼져 있다
- **대화 큐의 스티어링** — 큐만 출하했다. SDK는 스트리밍 입력 개조 필요, CLI 러너는 주입 지점 없음(정직 표기 전제)
- 러너 3종(Codex·Gemini·Antigravity) 라이브 스모크, Gemini 정책 안내 UI 확인 — v0.1.36부터 이월 중
- 구글 캘린더 커넥터 프로덕션 게시(현재 테스트 모드 = 유건 계정 전용)
- 큰 그래프 자동 맞춤 — 6번에 흡수됨
Loading