Skip to Content

알려진 gap (정직 페이지)

문서는 “운영자가 1인 멀티테넌트 플랫폼을 잡고 갈 수 있도록 하는 사실 의 SSOT” 가 목표. 그러나 일부 항목은 미구현 / 단순화 / 향후 작업. 본 페이지는 그 격차를 명시.

시간축 4-페이지 분리 (2026-05-22, D-docs-updates-1):

  • /ops/backlog = 현재 — 실행 큐 (🆕→📋→🔧→✅→⏸️). 다른 세션의 entry point
  • /ops/roadmap = 미래 — M1~M5 마일스톤 큰 그림
  • /ops/updates = 과거 — Ship Log + Highlights + /api/changes JSON feed
  • 본 페이지 = (사실) — “왜 이렇게 됐는지 · 무엇이 함정인지” 의 분석적 사실 기록. entry point 아님

새 함정·미구현을 발견하면: 실행 가능한 항목 = backlog 🆕 / 사실·맥락 기록 = 본 페이지 / ship 됨 = updates.

deploy-SSOT guard = host-local 강제, 서버측 백스톱 없음 (2026-06-05)

D-ops-42 의 pre-push guard (컴포넌트 E) 는 이 Mac mini 의 로컬 git 훅이다. axe guard install 로 frame·hive·blueprint·stream·magnet·index + axe-cli(~/.axe/bin) 에 설치 — git push origin main 직접을 기계적으로 거부하고 axe ship(내부적으로 AXE_SHIP=1 set, axe line ~7606) 만 통과. 강제의 경계가 있다:

우회 벡터사실완화
다른 머신/CI 에서 같은 origin 으로 push로컬 훅이 없어 차단 안 됨모든 개발 세션이 이 Mac mini 에서 돎 → 실 위협은 로컬 훅이 커버
git push --no-verifygit 내재 동작 — 클라이언트에서 pre-push skip, 클라이언트측 차단 불가운영자 단일·악의 아님 전제로 수용
GitHub branch protection (서버측 정답)현 plan 불가 — private repo 의 branch protection 은 Pro/Team 필요 (gh api repos/axelabs-ai/<svc>/branches/main/protection → 403 “Upgrade to GitHub Pro”)plan upgrade 시 require-PR / restrict-push 로 권위 백스톱 추가

범위: guard 는 axe-ship 거버넌스 대상 한정 (위 6 서비스 + CLI). artemis/blurgram/vault/axelabs 등은 자체 배포 경로라 의도적으로 guard 밖 (universal 아님).

설치 함정 — tracked core.hooksPath: index 는 core.hooksPath=.githooks (추적 디렉터리, sqlx pre-commit 보유). guard install 이 거기에 pre-push 를 쓰면 untracked 로 노출 → 세션이 git add -A 하면 운영자-로컬 강제 훅이 공유 repo 에 커밋되어 clone/CI 의 정상 push 까지 잘못 차단한다. 2026-06-05 ~/index/.git/info/exclude 로 차단 (비전파·tree 무변·훅 실행엔 무영향). 나머지 6 repo 는 .git/hooks(git 미추적)라 무관. CLI 일반화 = B-axe-guard-hookspath-exclude.

SSH 세션은 GUI login keychain 에 못 쓴다 — vault 비밀 주입의 keychain 함정 (2026-06-09)

이 Mac mini 의 Claude Code 세션은 SSH(loopback) 위에서 돌고 운영자는 Windows 에서 ssh [email protected] (Tailscale) 로 접속한다. macOS 는 SSH 세션이 GUI login keychain 에 쓰는 것을 거부한다 (“User interaction is not allowed”). 그래서 vault 에 비밀을 넣는 keychain 의존 경로 — axe vault unlock (keychain-cache crash), axe secret push/pull/check (_vault_envsecurity find-generic-password -s axe.vault.session 으로 keychain 세션만 읽음 → “vault session not found”) — 이 전부 SSH 에서 실패한다. 현 워크어라운드 = keychain-free raw-bw (운영자가 자기 셸에서 NODE_EXTRA_CA_CERTS + 단독 줄 bw unlock --raw + raw bw create/edit, D-ops-44 / /architecture/secrets). 더 깊은 격차 = _vault_envkeychain 세션만 읽고 env-session(BW_SESSION/stdin) 폴백이 없다는 것 — 그래서 SSH 컨텍스트가 axe secret * 의 1급 경로가 못 되고 매번 raw-bw 로 우회해야 한다. 이 함정을 없애는 fix 후보 = axe secret put --stdin-session 또는 _vault_env 의 env-session 폴백 (있으면 SSH 에서도 axe secret push 가 그대로 동작). 비밀 주입과 달리 배포(axe ship/secret pull) 는 keychain 세션이 필요 — SSH 에선 security unlock-keychain headless unlock 후 axe vault unlock 으로 채운다. (전조: 이 keychain partition 격리 자체는 realchoice D-day 함정 #5 에서 customer 측으로 먼저 관측됨 — 본 항목은 운영자 macmini 의 SSH 세션 + 비밀 주입 축.)

OIDC 발행자가 자기 토큰을 401 (issuer ≠ resource server)

2026-06-04. D-axe-idp-1 후속. Blueprint 가 플랫폼 토큰을 발행하면서 자기 MCP 는 그 토큰을 거부 했다. axe login 토큰은 frame·hive·index·cortex·matrix 에선 동작하나 https://axe.axelabs.ai/blueprint/mcp 에선 401 (unknown_kid).

근본 원인: trust-migration 작업이 frame·hive·cortex·index·matrix 5개만 대상으로 잡고 Blueprint 자체 MCP 를 빠뜨렸다 — “issuer 가 곧 resource server” 가 자명해 보여 목록에서 누락. Blueprint MCP (blueprint_mcp/auth_oidc.py) 는 Microsoft Entra access_token 만 검증 (verify_microsoft_access_token) → 플랫폼 토큰의 kid (= Blueprint OIDC 서명키) 가 Microsoft JWKS 에 없어 unknown_kid → 401.

진단 단서 (같은 토큰을 두 서비스에 던져 비교):

  • blueprint/mcp401 {"code":"UNAUTHORIZED","message":"unknown_kid: <kid>"} (Microsoft JWKS 에서 못 찾음)
  • frame/mcp401 {"code":"TOKEN_EXPIRED"} (= iss 분기·서명검증을 통과하고 exp 만 걸림 → frame 경로는 정상)
  • unknown_kid vs token_expired 의 차이가 “이 서비스는 Blueprint issuer 분기가 아예 없다” 를 가리킨다.

Fix: frame auth_blueprint.py + http_server.py iss-dispatch 를 Blueprint MCP 에 미러 (mcp/src/blueprint_mcp/auth_blueprint.py 신규 + BLUEPRINT_ISSUER=https://blueprint.axellc.com compose env). forged-iss/bad-sig → 401 검증 (unverified iss-peek 가 auth 우회 안 함). 설계: /architecture/platform-identity.

교훈: OP 를 세울 때 그 OP 자신의 MCP 도 resource-server 목록의 한 행이다. 발행자라는 사실이 자동 신뢰를 주지 않는다 — 토큰 검증은 issuer 든 아니든 동일하게 명시 배선해야 한다.

잔여 (별개): axe-cli 의 blueprint local 엔드포인트 경로가 틀림 — :3151/mcp → 404 (proxy 는 /blueprint/mcp 서빙). public 은 정상. backlog B-axe-cli-blueprint-local-path.

Cloudflare Universal SSL 1-level

2026-05-26, D-ops-39. 무료 plan 의 *.axelabs.ai Universal SSL cert 가 1단 서브도메인만 cover 하는 함정. zone 안에 2단 hostname (e.g. ssh.axe.axelabs.ai) 을 만들면 edge 가 SAN 미일치 → default cert fallback → 클라이언트 TLS handshake 실패.

환경증상
Windows (Schannel)SEC_E_ILLEGAL_MESSAGE (0x80090326)cloudflared access loginfailed to get app info: remote error: tls: handshake failure
macOS (LibreSSL/curl)sslv3 alert handshake failure
브라우저 (Chrome/Edge)ERR_SSL_VERSION_OR_CIPHER_MISMATCH

진단 분기점: cloudflared --version 최신 + 시스템 시간 OK + 브라우저/curl/cloudflared 3개 클라이언트 모두 동일 실패 = 서버측 cert 단정 (90%+ confidence). 동일 zone 안에서 1단 host (e.g. axe.axelabs.ai) 는 정상 동작하는 것도 단서.

컨벤션 (D-ops-39): HTTPS 노출되는 모든 hostname = {name}.axelabs.ai 의 1단. flat-hostname (예: ssh-axe) 또는 path under apex (axe.axelabs.ai/frame). 룰 본문 /architecture/domains#함정—universal-ssl-wildcard-의-1-level-한계-d-ops-39.

구체 사례 — ssh.axe.axelabs.ai (강태훈 Windows, 2026-05-25):

  • 강태훈이 cloudflared access login https://ssh.axe.axelabs.ai 시도 → 위 Windows 증상.
  • axelabs.ai chat 의 MAX agent 가 클라이언트 4단계 (cloudflared version / 시스템 시간 / TLS inspection / hostname 정확성) 진단 후 서버측 단정.
  • 2026-05-26 운영자가 ssh-axe.axelabs.ai 신규 등록 (DNS CNAME → 동일 tunnel d8efecdd, ingress 규칙 clone, Access app b903d8cd self_hosted_domains 추가). 검증: curl -v https://ssh-axe.axelabs.ai/ → 302 to axellc.cloudflareaccess.com.

옛 hostname 완전 삭제 (2026-05-26 같은 날 후속): 강태훈이 신규 hostname 으로 1차 재시도했으나 Microsoft SSO 통과 후 callback 이 옛 ssh.axe.axelabs.ai 로 떨어져 동일 cert 오류 재발. 추가 진단:

  • Access app 의 primary domain 필드가 여전히 ssh.axe.axelabs.ai 였음 → post-auth callback / App Launcher 흐름이 primary 를 우선시. 1차 fix: domainssh-axe.axelabs.ai 로 PUT swap.
  • 2차 fix (확정): 옛 hostname 흔적 3 layer 모두 제거 — (a) DNS CNAME ssh.axe.axelabs.ai + *.axe.axelabs.ai 와일드카드 삭제, (b) axelabs tunnel (d8efecdd) ingress 규칙 제거, (c) Access app self_hosted_domains / destinations 에서 제거. 검증: dig ssh.axe.axelabs.ai → NXDOMAIN. 클라이언트 측 cache (브라우저 쿠키 + %USERPROFILE%\.cloudflared\ token) 정리 후 cloudflared access login https://ssh-axe.axelabs.ai 재시도 안내.

거부된 대안 ($10/cert/월 ACM, zone delegation, Tailscale 우회, 클라이언트 cert bypass): D-ops-39 본문 참조.

운영자가 az CLI 로 /me/sendMail 호출하려고 시도 → 403 ErrorAccessDenied. 명시적 scope (--scope https://graph.microsoft.com/Mail.Send) 요청 시 AADSTS65002: Consent between first party application '04b07795-8ddb-461a-bbee-02f9e1bf7b46' and first party resource '00000003-0000-0000-c000-000000000000' must be configured via preauthorization.

az CLI 의 client app id 04b07795 (Microsoft Azure CLI 자체) 가 Microsoft Graph (00000003) 의 Mail.Send scope 받으려면 Microsoft 가 preauthorization 등록해야 함. 자사 앱 간에도 cross-app consent 안 됨. 개별 tenant 의 admin consent 로 우회 불가.

영향: az CLI 경유 mail/chat send 영구 불가. 우회 = (a) /api/admin/broadcast-dm (Blueprint REST, 본 use case 의 정공법), (b) Outlook 수동, (c) custom Azure app 신설 (Mail.Send delegated/application + admin consent + client_id/secret vault 저장, 30분+ setup — 사용 빈도 높을 시 B-axe-mail-send-cli 진행).

왜 운영자가 함정에 들어갔나: Blueprint 가 sendEmail() 함수 + Mail.Send permission 둘 다 보유 — 자연스레 “외부 connector 에서도 호출 가능” 가정. 실제는 graph_* tool 32+ 중 send 계열은 blueprint-graph 내부 MCP 에만 등록, 외부 7cb41f76 connector 는 read-only 격리 (의도). 외부에서 send 가 필요하면 admin REST (broadcast-dm 등) 별도 경로.

D-bp-mcp-calendar-2 send-as 도입 시 8개 함정 (2026-05-26)

Soohun 의 “ai 계정으로 다른 사용자 캘린더 쓸 수 있냐” 질문 → 1시간 안에 7개 별개 차단점 통과. 각각 다음 calendar/admin write feature 도입 시 동일 패턴.

Blueprint Azure App ID 혼동

Blueprint 가 별개의 Azure App 2개 보유:

  • 2b222356-1c36-48e0-96a3-2c5e0ecbf937 = Blueprint Next.js app (NextAuth Azure AD provider, getMsalApp()getAppOnlyClient() 가 사용). DB AppSetting azure_ad_client_id.
  • 482598f7-540c-462c-9dfd-b957651eb804 = Blueprint MCP custom connector (Claude → MCP OAuth용). CLAUDE.md 의 “Client ID” 항목.

내부 API route 가 app-only token 발급할 때 audience = Next.js app (2b222356). Application permission + admin consent 모두 2b222356 에 적용해야 함. MCP app 482598f7 에 consent 하면 무관 → 403 ErrorAccessDenied 계속 반환. 본 세션 1회 잘못 적용 → MSAL token 디코드해서 aud 확인하고서야 발견.

Blueprint User.id ≠ Microsoft Entra oid

Blueprint User.id = Prisma 가 생성한 cuid (e.g. e1c51fa2-0102-43ed-...). NextAuth Azure AD callback 에서 Entra oid 를 별도 컬럼에 저장하지 않음 → /users/{User.id}/events 호출 시 Graph 가 ErrorInvalidUser 404. Graph /users/{key} 는 oid 또는 UPN/email 받음 — UPN 사용으로 우회. Route 가 target.email 을 path 에 인코딩하도록 fix. 향후 D-bp-mcp-calendar-3 이상에서 직접 oid 필요한 endpoint 도입 시 Useroid 컬럼 추가 검토.

MSAL acquireTokenByClientCredential 토큰 캐시

@azure/msal-node 의 ConfidentialClientApplication 은 client-credentials flow 토큰을 in-memory 캐시 (default TTL ~1시간). admin consent 직후에도 캐시된 옛 토큰 (consent 이전 발급, roles claim 누락) 이 계속 반환됨 → Graph 403 지속. container 재시작 또는 skipCache: true 옵션으로 강제 refresh. MSAL .default scope 가 “현재 consent 된 모든 perm” 의미라 cache 무효화 트리거 없음 (admin consent 가 MSAL instance 에 signal 안 보냄). 본 세션은 docker restart blueprint-app-green 으로 우회.

Global Admin = soohun.kang 단독 ([email protected] 은 admin 아님)

운영자 가정: “[email protected] 으로 az 로그인 되어 있고 관리자 권한이므로 tenant 작업 가능”. 실제: AXE 테넌트의 Microsoft Entra Global Administrator role = [email protected] 단독. [email protected] 은 일반 사용자. Authorization_RequestDenied 에러 시 userObjectId 필드 디코드 (Entra oid lookup) 로 실제 호출 identity 확인.

참고: Blueprint 자체 admin role (User.role === "admin") 과 Azure AD Global Admin 은 별개. [email protected] 은 Blueprint admin (Blueprint MCP send-as 호출 가능), 그러나 Azure AD admin 작업 (Application permission grant 등) 불가.

az login 무구독 테넌트

M365-only 테넌트는 Azure 구독 0개. az login --tenant <id> 만으로는 active context 가 직전 계정에 머무름 (No subscriptions 메시지 후 무시). --allow-no-subscriptions flag 필수. 확인: az account show 로 active upn 검증.

Claude.app /dev/ptmx fd leak

Claude 데스크탑 앱이 새 채팅/대화 열 때마다 /dev/ptmx open, close 안 함. 누적되면 kern.tty.ptmx_max=511 (macOS 하드 한도) 도달 → forkpty: Device not configured (ENXIO) → 신규 터미널·subprocess PTY 할당 불가. userspace 측 zsh 좀비 (Claude Code subprocess 누적 82 → 정리해도 무효) 가 아니라 Claude.app 본체 fd leak. lsof /dev/ptmx 로 holder 확인 가능.

해결: Claude.app 종료 후 재실행 (fd 자동 release). sudo 로 kern.tty.ptmx_max raise = “Invalid argument” (macOS 가 511 이상 거부). Anthropic 리포트 대상 (B-claudeapp-fd-leak-report backlog).

2026-06-04 재발 확인 (lsof /dev/ptmx: Claude.app PID 1개가 510/511 점유, 여유 0). 이때 신규 PTY 차단뿐 아니라 sudo 자체가 막힌다 — sudoers Defaults use_pty 탓에 sudo: unable to allocate pty: Device not configured. 세션을 안 끊고 root 작업하는 우회법 = osascript -e 'do shell script "…" with administrator privileges' (AuthorizationServices GUI 인증 → pty 불요, sudo 미경유). netheal 데몬(D-matrix-4) 설치를 이 방법으로 완료. 단 GUI 세션 필요 (GRD/콘솔 OK, 순수 SSH 불가). 항구적 회수는 여전히 Claude.app 재시작.

FastMCP tool 의 Image | dict union 반환 어노테이션

FastMCP tool registration 이 return type annotation 을 pydantic 으로 schema generate. mcp.server.fastmcp.utilities.types.Image 가 union (Image | dict) 안에 있으면 PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <class 'Image'> → MCP 서버 startup 실패 → blue/green health check 60s timeout → swap 자동 거부. return annotation 생략 또는 Any 로 우회. 본 세션 get_teams_hosted_content 가 1회 발현 후 commit 3c7ae254 로 fix.

Pre-existing axelabs-docs {#anchor} MDX 3 acorn parse fail

별개 함정 (calendar 와 무관) 이지만 본 세션 docs ship 차단했음. ## Heading {#explicit-anchor} 문법이 Nextra (MDX 3) 의 acorn 파서를 깨뜨림 → Could not parse expression with acornnpm run build 실패 → axe ship docs 의 docker rebuild 차단. MDX 3 에서 {#...} 명시 anchor 미지원: 헤딩 텍스트를 슬러그와 일치시키도록 변경 (github-slugger 자동 ID) 하고 inbound 링크 그대로 유지. 운영자 별도 commit 으로 동시 fix 됨 (race condition 으로 commit 941196f).

realchoice D-day 첫 실행 — 6 함정 (2026-05-25 발견)

Truvia 측 RE^6 의 D-day 즉시 시작 피벗 후 운영자가 axe onboard realchoice --apply 실행. step 1-13 ✅ + step 14 차단. 본 섹션은 분석적 기록 (실행 항목은 B-onboard-d-day-traps-2026-05-25).

#함정본질영구 fix 후보
1Tailscale short host alias (realchoice-macmini) macOS resolver 미해석 → ssh failmacOS resolver 는 magicDNS short alias 자동 처리 X. ~/.ssh/config 의 Host alias + HostName FQDN 매핑 필수. axe CLI 가 short alias 로 ssh 호출partner/macmini-prep 함정 표 + axe onboard 가 자동으로 ~/.ssh/config 추가 또는 ssh 명령에 -o "Host alias=FQDN" 사용
2SSH non-login shell PATH 에 /usr/local/bin 누락 → docker not foundmacOS 의 zsh non-login 은 ~/.zshrc 안 봄. ~/.zshenv 만 봄. Docker Desktop 의 symlink (/usr/local/bin/docker) 가 default PATH 밖. Truvia 측 ~/.zshenvexport PATH=/usr/local/bin:/opt/homebrew/bin:$PATH 추가 필요partner/macmini-prep 의 §5 Docker 섹션에 ~/.zshenv 명시 (즉시 갱신 필요)
3TXT + CNAME 같은 name 공존 시 axe onboard step 5 의 _cf_dns_find(zone, name) 가 type filter 없어 거절CloudFlare API 는 type filter 미적용 시 모든 record 반환. axe CLI 코드가 “exists” 로 단정 → conflict 처리. RFC 측면 TXT+CNAME 공존 OKaxe CLI _cf_dns_find(zone, name, record_type) 시그니처 변경 + onboard step 5 가 record_type="CNAME" 명시
4Login keychain locked + SSH non-interactive → security add-generic-password exit 36 (errSecAuthFailed)macOS GUI session 의 keychain unlock 이 SSH non-interactive session 의 securityd partition 으로 propagate 안 됨함정 5 가 본질적 fix (vault SOT 이전)
5macOS keychain partition 격리 — SSH non-interactive 의 securityd 가 GUI session 과 별도 partitionTruvia 측 GUI 로그인 + timeout 10h 연장 했지만 SSH non-interactive session 영향 0. 즉 axe onboard 의 step 12 (secret generation) 가 SSH 으로 호출하면 fundamental 차단. 본 D-day 의 핵심 함정. 즉시 우회 = Truvia 가 본인 SSH session 에서 직접 명령 실행 (operator → customer 권한 위임 패턴)(a) start-frame.sh 를 customer launchd job 으로 등록 → console session 의 keychain access. (b) secret SOT 를 keychain 에서 vault 로 이전 (D-ops-17 manifest pattern 확장). bw CLI 는 SSH session 에서도 작동
6start-frame.sh wrapper 가 SSH non-interactive 에서 security find -w (value fetch) 시도 → ACL 차단 → FATAL: FRAME_JWT_SECRET empty함정 5 의 구체적 발현. wrapper 가 keychain value 꺼내야 frame postgres + frame-mcp-blue 부팅 가능. SSH 으로 호출 시 차단. axe CLI line 2588 의 step 12 fix (-w 제거, metadata-only) 는 step 12 통과시키나 step 14 wrapper 의 fetch 는 동일 차단함정 5 와 동일 영구 fix

즉시 우회 (본 세션 적용):

  • 함정 1: ~/.ssh/config 신설 (Host alias + HostName FQDN)
  • 함정 2: Truvia 측 ~/.zshenv PATH 추가
  • 함정 3: Microsoft verify 완료 후 TXT 제거 + axe CLI 재실행
  • 함정 4-5: Truvia 가 본인 SSH session 에서 security add-generic-password 직접 실행
  • 함정 6: ⏳ Truvia 회신 대기 (옵션 A = 본인 SSH session 에서 start-frame.sh up -d 직접 / 옵션 B = security set-generic-password-partition-list ACL 변경)

영구 fix 적용 (2026-05-26, B-customer-deploy-generalization Phase 1 완료):

  • 함정 4·5·6 → vault SoT 이전. axe CLI 의 _deploy_service_customer + 새 wrapper 3종 (start-{frame,blueprint,hive}.sh) 이 customer 측 bw get password 으로 secret fetch. SSH non-interactive 의 keychain partition ACL 회피 (bw 는 파일 기반 ~/.bw-session 으로 BW_SESSION 획득 → securityd 무관). customer 측 1회 부트스트랩 = brew install bitwarden-cli + bw-bootstrap.sh https://<vault-url> <email> (interactive). 본 변경 후 함정 4·5·6 = 다음 customer 에서 재발 0.
  • 함정 10 (env_file $ literal) → escape_dollar: true flag 자동 처리. INGEST_MANIFEST_TEMPLATE 의 OAuth secrets 에 빌트인.
  • 함정 7 (docker-compose default path hardcode) → image_override 슬롯으로 customers.yaml 에서 override 가능 (R4). compose 본체 변수화는 service repo 측 별도 PR.
  • 함정 8 (axe onboard step 14 non-idempotent) → 이미 axe CLI line 2720+ 에 docker ps 사전 검사 + skip if running 패치 적용 (5/25). 신규 _deploy_service_customer 도 동일 패턴 적용 필요 (TODO).

미해소:

  • 함정 1·2·3 = docs 측 갱신 필요 (partner/macmini-prep 의 함정 표 + axe CLI _cf_dns_find 시그니처 변경).
  • 함정 9 (frame-proxy stale archive) → /Users/axe/.axe/frame-proxy/ 5/24 복원 ✅. axe CLI 가 정상 경로 참조.

1-shot onboard 갭 — realchoice (2026-05-23 분석)

목표: D-day 에 운영자가 vault master password 1 회 입력만으로 신규 customer (realchoice 등) 전체 배포 완료. 현재 6 개 수동 touchpoint 가 남음. /ops/runbook/customer-onboarding#d-day-tldr—운영자-수동-touchpoints 가 SSOT.

⚠️ 갱신 (2026-06-06): realchoice 는 2026-05-25 sovereignty self-deploy 로 LIVE 완료 (customers.yaml 에서 services: 의도 제거). 본 섹션의 realchoice 예시는 역사적 — 잔여 갭은 services: 매니페스트를 선언하는 신규 customer 에만 적용되고, realchoice 자체엔 axe deploy {svc} realchoice 가 미적용된다 (→ /ops/runbook/customer-onboarding sovereignty caveat).

#현재 상태닫는 작업
1axe customers add {customer} = stub (line 560-561)customers.yaml 의 customer 메타블록 + services 슬롯 모두 운영자 수동 편집B-onboard-customers-add
2customer IT 회신 8 개 값 → vault 로 운영자 수동 push × 3 + customers.yaml 수동 paste × 4 (tenant_id + 3 client_id)안전채널 받은 값 운영자 손에서 vault 로 이동B-onboard-azure-packaxe customer ingest {customer} pack.json 으로 (a) yaml fill + (b) vault push 묶음
3services: 섹션이 axe customer 만 등재 (realchoice services 슬롯 부재)axe secret push --customer realchoice 가 manifest lookup 실패B-onboard-customers-add 결과물의 일부
4axe deploy hive {customer} subcommand 부재해소 (2026-06-06)axe deploy choices = frame / blueprint / blueprint-mcp / hive / matrix (cmd_deploy_hive customer-path live, .axe/bin/axe)B-onboard-hive-deploy
5cmd_deploy_blueprint docstring 자기 명시: “SSO (Azure AD) 미설정 — Phase 3 추가 작업 필요”Blueprint 컨테이너는 부트되지만 첫 SSO 로그인 시 secret 부재로 실패. 운영자가 별도로 customer Keychain 또는 vault → .env 채워야 함B-onboard-bp-sso
6Cloudflare API token vault 등재 = first-onboard chicken-and-egg첫 onboard 직전 1 회 axe secret push 필요 (현재 docs 부재)B-onboard-cf-token-doc — secrets.mdx 의 bootstrap 섹션에 명시 1 줄

해소 후 D-day 흐름 (목표):

# 0. vault unlock — master password 1 회 export BW_SESSION="$(bw unlock --raw)" && security add-generic-password ... # 1. customer IT 회신 한 줄 ingest (yaml fill + vault push 묶음) axe customer ingest realchoice ~/Downloads/realchoice-azure-pack.json # 2. 모든 stack 묶음 배포 (frame + blueprint + hive + vault) axe deploy all realchoice --apply

현재 drift 발견 (본 sweep, 2026-05-23):

  • customer-onboarding.mdx 의 D-7 step 3-5 가 /Users/axe/.axe/tunnels/axelabs/config.yml 편집 + docker restart axelabs-tunnel 요구정정 완료. 실제 axe onboard 는 customer 별 독립 tunnel 을 customer macmini 에 생성 (_render_cloudflared_config /Users/{ssh_user}/.cloudflared/config.yml). 중앙 tunnel 편집 의무 사라짐.
  • axelabs-bootstrap.sh + realchoice_entra_id_setup_v3.md 가 별도 안전채널 메시지로 전달되는 의존정정 완료 (B-onboard-bootstrap-publish, 2026-05-23). 스크립트가 https://docs.axelabs.ai/axelabs-bootstrap.sh 의 raw 로 노출. partner/registration §Option A + macmini-prep + domain-prep §A/§B + handoff JSON pack 양식 + index 4-step 흐름으로 docs.axelabs.ai 만으로 customer IT 자력 완료 가능. customer-facing 차단은 0. 잔여 6 갭 (위 표) 은 모두 운영자 측 자동화 (umbrella + ingest + hive deploy + bp sso + cf token) — 운영자의 D-day 명령 수를 5→1 로 줄이는 것이 우선순위. customer 측에는 영향 없음.

CLI 측 미구현 (axe CLI Phase 5 stub)

약속된 CLI실제 상태우회
axe restore --customer X --tier local|ring|cold --target X --table X --applyargparse stub (--tier, --target, --table, --apply flag 없음)restic 직접 호출 (각 runbook 의 갱신된 예시 참조)
axe backup --status / axe backup --local --tag Xaxe backup subcommand 없음 — /Users/axe/.axe/bin/axe-backup shell script 가 매일 03:00 자동restic snapshots 직접
axe onboard --skip-azure--skip-azure flag 없음 (--skip-frame 만 있음)onboard 가 Azure 측 변경 안 함 — flag 없어도 무방
axe health &lt;target&gt; --customer X--customer flag 없음 (positional 만)axe health frame 처럼 사용
axe secret status --customer X--customer flag 없음운영자 콘솔 dashboard 에서 확인
axe ship (release-gate)✅ 구현됨 (D-ops-16)
axe secret check/pull/push/rotate (manifest 기반)✅ 구현됨 (D-ops-17). pull merge-mode (D-ops-18)
axe deploy blueprint-mcp (blue/green swap)✅ 구현됨 (D-bp-mcp-2, 2026-05-21) — frame cmd_deploy(frame) 1:1 미러
axe ship blueprint 안에서 mcp swap 자동 호출✅ 구현됨 (D-bp-mcp-2 후속, 2026-05-21) — cmd_blueprint_upgrade 직후 cmd_deploy_blueprint_mcp wire-up

→ Phase 5 (D) 작업 항목으로 CLI 완성 예정. 그때까지 runbook 의 명령어는 “현재 형식” 으로 사용.

매니페스트 / vault 측 미해결

항목현재 상태후속
매니페스트 non-secret config 흡수 결정 (Option A: 매니페스트 확장 / B: merge-mode 만 / C: customers.yaml 통합)merge-mode pull (D-ops-18) 로 즉시 위험 X. blueprint .env 의 AZURE_AD_CLIENT_ID 등 9개는 hand-maintain운영 안정 후 정책 결정
[email protected] Vaultwarden service account미생성. 현재 모든 bw 호출이 운영자 개인 tokenD-ops-17 Phase 6
cmd_blueprint_upgrade Keychain → vault 통합현재 Keychain inject (line 698) + env_file 동시 사용. 두 출처 sync 책임 운영자vault 단일 출처로 통합
CLAUDE_CODE_OAUTH_TOKEN 회전2026-05-21 transcript 노출. 사용자 보류 (후순위)Anthropic console 새 토큰 발급 → axe secret rotate
hive HIVE_MAILER_* 매니페스트 미등재.env.local 에 hand-maintain 중 (D-hive-23)customers.yaml hive.secrets[] 에 추가
hive postgres HIVE_DB_PASSWORD substitution (compose 변수)volume reset 시점 default hive_dev 로 fall back 위험. 현재 data dir 에 vault 값 이미 initpostgres 에도 env_file 도입 또는 .env 명시
bw CLI [Encrypt service] MAC comparison failed. ... Failed to decrypt user key with stretched master key — 재발성 (5/22 .broken.1779431724 + 5/26 .broken.1779783301). KDF 원인 아님 ([email protected] 이미 Argon2id).Root cause 확정 (5/26 검증): bw CLI 의 local data.json 의 cached cryptoSymmetricKey (wrapped user key) 가 server-side patch deploy 후 bw sync 시점에 stale 상태로 저장됨. bw unlock 은 이 캐시를 invalidate 안 함 → 매 unlock 마다 stale wrapped user key 로 decrypt 시도 → MAC fail. axe Vaultwarden 의 빈번한 fork patch deploy (axe.2, axe.3, …) 가 트리거.즉시 복구 (확정): mv "~/Library/Application Support/Bitwarden CLI" "~/Library/Application Support/Bitwarden CLI.broken.$(date +%s)" && bw config server https://axe.axelabs.ai/vault && bw login [email protected] (fresh login). 약 1분. → B-bw-cache-stale-autoheal 영구 fix

launchd 측 미구현

약속된 launchd실제 상태
com.axe.secret-check (매일 09:00)미구현. Vault item 의 만료 메타 + 운영자 콘솔 dashboard 에서 수동 확인
com.axe.health-check (매분)미구현. com.axe.console.refresh (매시) 가 운영자 콘솔에 health 표시. 매분 알림은 향후 추가
axe-health-monitor 바이너리미구현

대안: 운영자 콘솔 (https://admin.axelabs.ai) 이 매시 rebuild 되며 health 표시. 즉시 알림이 필요하면 osascript 또는 Slack webhook 으로 임시 wrapper 작성 가능.

Docs 측 내부 불일치 (정리 진행 중)

항목현재 상태정리 계획
partner/registration.mdx 신모델 (Web platform + secret + App ID URI + mcp.access)작성됨axe customer 는 이미 신모델로 마이그됨. realchoice 도 6월 onboard 전 신모델로 적용
realchoice_entra_id_setup_v3.md✅ 작성 완료 (2026-05-21)발송 (5/29 마감)
axe_frame_mcp_setup.md (구모델 기록)historical본인 실작업 기록 — 사실 정확성 위해 보존
frame/docs/ops/onboarding-operator.md §0 (구모델 Azure 등록)obsoleteregistration.mdx 로 통합 → 향후 cross-link
customers.yaml.axe.sso.apps.blueprint_mcp✅ 추가됨 (D-bp-mcp-1)
frame ahead commits 의 docs drift (auth_oidc.py, cli.py, alembic, Dockerfile 등)operator hive integration 세션 작업분operator 의 axe ship frame 사이클에 함께

정확한 tool count

서비스docs 표기실제 (코드 기준)비고
frame~44 (수정됨)44 (grep -c '@mcp.tool' src/frame/mcp/server.py)OK
stream28 (수정됨)28 (admin=7, sales=5, inventory=4, settlement=3, health=3, bridge=2, signals=3, meta=1)OK
magnet39+ headline51+ 표 합산, 자기 진단 1 포함 시 ~62 데코레이터표 합산이 실제와 다름 — magnet 측 통합 daemon 의 자체 보고가 39

magnet 의 39 vs 51+ 차이는 magnet 측 mcp/server.py 의 importlib 흡수 시 일부 중복/내부 도구 제외. magnet team 정리 후 docs 갱신.

hive 골든테스트 ↔ 라이브 데이터 결합 (2026-06-04)

tests/payroll/test_golden_axec_2026_04.py 가 라이브 axec DB 의 직원 종료상태에 의존 (자체 시드 없이 compute_period 실행). 골든 픽스처 (golden_axec_2026_04.json) 가 강수훈 (AXEC-001) 을 terminated 2026-04-01 로 인코딩 → CI 통과를 위해 실 직원행을 수동 (out-of-band, audit_log empty-actor) UPDATE 하게 만든 것이 강수훈 axec 종료의 근본원인 (2026-06-04 agent 조사·DB 검증). 같은 압력으로 axev/AXEV-003 강수훈도 수동 종료됐으나 그는 AXEV 파트너 직급 — 정합화는 backlog B-hive-axev-003-terminated. 구조적 해소 (테스트를 트랜잭션 내 자체 시드 또는 전용 test entity 로 분리) 는 backlog B-hive-seed-integrity. 가드: “terminated 인데 active membership/open employment_record” 면 fail 하는 invariant 테스트.

gh pr create ↔ repo redirect 함정 (origin=soohunkang/*axelabs-ai/*) (2026-06-04)

로컬 git remote originsoohunkang/<repo> (구 이름) 인데 GitHub 가 axelabs-ai/<repo>redirect (repo transfer — fork 아님: gh repo view soohunkang/hiveisFork:false, parent:null, nameWithOwner:axelabs-ai/hive). 이 상태에서:

  • gh pr create … --head soohunkang:<branch> (fork 스타일 head) → 존재하지 않는 fork owner 해석 시도 → GraphQL Something went wrong 500 (무한 반복). plain gh pr create 도 redirect/fork-resolution GraphQL 에서 간헐 500.
  • REST + plain same-repo head: gh api --method POST repos/axelabs-ai/<repo>/pulls -f head="<branch>" -f base="main" -f title=… -f body=…. 머지도 gh api --method PUT …/pulls/<n>/merge -f merge_method=squash.
  • git push origin 은 redirect 통과(axelabs-ai 에 정상 반영). 진단 순서: GitHub status green + gh api rate_limit 정상이면 장애 아님 → head 형식/redirect 의심하고 REST 로 우회. 모든 세션이 동일 origin 사용 → 공통 함정 (2026-06-04 hive PR #5 에서 ~6회 헛시도 후 규명).

운영 자동화 미완성

항목현재
분기 restore drill (com.axe.restore-drill)launchd 등록 + plist 존재. 첫 실제 drill 시기 (Jul 15) 까지 검증
Cold SSD rotationtooling ready, SSD 자체 미구매 (operator 작업)
Realchoice ring backup양방향 SSH 검증 완료 (2026-05-15). realchoice onboard (6/1) 후 첫 sync 시작
mysrt-postgres backup 정책 미명시mysrt-postgres 컨테이너 운영 중, axe-backup 범위 밖. mysrt 가 SRT 폴링 (외부 SOT 가 source-of-truth 가능성) 이라 의도적 제외일 수도 / 누락일 수도. architecture/backup.mdx 에 “백업 대상에서 의도적 제외” 명시 또는 추가 결정. 검출 2026-05-21.

Blueprint 측 미완 (2026-05-21 세션 발견)

항목현재 상태후속
Blueprint MCP get_session + list_messages tool9 read-only tool 중 Message 본문 외부 비공개 → agent transcript blind. 5분야 진단 (2026-05-21) 의 최대 빈 곳Stage 1 전 추가. PrismaClient member-scoped pattern
cmd_deploy_blueprint_mcp edge probe URL 부정확200 expected 인데 cloudflared 가 /blueprint/mcp/health path 보존 + JWTAuthMiddleware 가 Bearer 인증 요구 → 실제 응답 401 (정상 도달). axe deploy blueprint-mcp 가 매 swap 에서 ”⚠ edge not 200” 경고 출력URL 을 /blueprint/mcp (auth-required endpoint) 로 + expected 401 + WWW-Authenticate: Bearer 헤더 검증
axe blueprint upgrade active color resolve 오작동_blueprint_active_color() 가 stopped 컨테이너 metadata 를 alias 보유로 인식 → 실제 active 인 컨테이너 rebuild 시도 위험 (2026-05-21 회피: docker compose 직접 호출)docker inspect 결과에 State.Running == true 필터 추가
Trinity scheduled reconcile 부재src/lib/trinity-sync.ts:1-15 가 사용자 클릭 trigger / resolveLocalPath self-heal 만. 6/16 row drift 가 사용자 trigger 까지 잔존cron 또는 launchd 일일 reconcile
/axe/personas UI 부재API src/app/api/personas/route.ts:11-19 만, page 없음persona 자기 큐레이션 UI
/api/health 단순 20014줄, DB/Postgres/Graph upstream probe 없음upstream probe + Cloudflare health-gate 신뢰 회복
IC DATA-FIX modeSKILL.md:140-173 4-mode (INITIAL/APPEND/REVISION/FINALIZE) 만. 숫자 정정 시 강제 v-bumpDATA-FIX mode 추가
PARA dispatch UI (Project 종결 시 Area/Resource 로 artifact 이관)schema 부분 완료 (PR #339 sourceWorkspaceId / sourceArtifactPath / copiedAt 3 필드). D-bp-entity-2 정식 등재. UI 만 잔여 (PR 5 예정). 미결 3종: 분배 단위 (파일 vs 의미) / Area 인스턴스 정의 권한 (org-admin vs free) / 정비 트리거 우선순위Path B Spike (DB 변경 없이 단일 workspace 로 LLM 분배 정확도 검증 3-5일) → Path A 본구현 (Area/Resource UI + dispatch modal + archive search separation)
Settings UI default entity dropdown/api/user/default-entity PATCH endpoint (D-bp-entity-7) 있으나 UI 부재. 사용자가 직접 변경 못 함 — 운영자 SQL 또는 customers.yaml 순서 의존/axe/settings/SettingsClient.tsx 에 dropdown 한 줄 (~30 min)
axe entity register 통합 명령hive register-entity + Blueprint seed-entities.ts 갱신 두 명령 분리. 부분 등록 함정 (한 시스템만 등록되고 다른 시스템 안 됨) 가능axe CLI entity register <slug> --name ... --biz-no ... subcommand. hive subprocess + Blueprint Entity row INSERT atomic
blueprint-mcp + hive-mcp /health anon exposeJWTAuthMiddleware 가 모든 path (/health 포함) Bearer 요구. frame-mcp 는 /health anon. axe CLI edge probe 가 401 expected 로 현재 workaround. frame 패턴 mirror 가 본질 fixFastMCP middleware exclusion list 에 /health 추가 (blueprint-mcp + hive-mcp 각각). axe CLI expected 401 → 200 정정. mcp-server-checklist 에 항구화
Teams attachment unsupported contentType → LLM false-negativesrc/lib/teams/attachments.ts:138 의 unsupported-loop 가 [unsupported contentType: X] stub 만 LLM 에 넘김. LLM 은 stub 만 보고 “X 못 봤다” 그럴듯한 답 confabulate (실제 API 한계와 구분 불가). messageReference 1 종은 PR #372  에서 fix. card / file / 기타 contentType 미점검B-bp-teams-attachment-contenttype-audit. production 관측 contentType enumerate + handler 추가 또는 placeholder 명확화. feedback_bot_capability_gap_self_diagnosis
Knowledge Layer 격차 — typed fact 부재ctx skill 이 markdown PKM 만 제공. Per-field citation / cross-functional query (frame typed × portfolio markdown join) / time-travel / 결정론적 충돌 해소 모두 불가능. 인프라는 dev-co level (per-customer isolation / blue-green / restic backup) 인데 knowledge layer 만 single-operator PKM tool 수준M6 Blueprint artifact + PARA 지식 레이어 가 본 격차 직접 대응. D-bp-artifact-1~5 (2026-05-23 등재). 아키텍처 페이지

Multi-tenant 외부 출시 차단 (Stage 0 → 1)

5분야 진단 (2026-05-21) 결과:

항목현재후속
Org tenancy FK fanoutWorkspace/UsageLog/Agent 에 organizationId FK 부재 (prisma/schema.prisma:688 “별도 PR” 주석). single cross-tenant 쿼리 누락 = 전 고객 노출D-bp-org-fanout 신규 결정 + migration. D-bp-entity-1 의 entityId FK 와 별개 (entity = 회계 단위, org = customer 단위)
Azure AD tenant env-locksrc/lib/auth.ts:101 AZURE_AD_TENANT_ID 단일 env → 외부 IdP 분기 0per-org Organization.azureTenantId + auth.ts multi-tenant Azure AD provider
법무 페이지 / rate-limit / Sentry / axe-health-monitorTOS / Privacy / DPA / PIPA 페이지 0건. edge rate-limit 부재. monitor 미구현 (위 launchd 측 미구현 참조)Stage 1 closed beta 진입 prereq
Backup tier-A✅ blueprint-postgres dump 포함 (2026-05-21 backup.mdx 갱신)restore drill 1회 (Jul 15)

MCP 공통 함정 (D-bp-mcp-3 cross-cutting, 2026-05-22)

D-bp-mcp-3 본질이 frame · hive 에도 부분 적용. 양파껍질 6 layer 의 한 갈래:

서비스SQLite legacy 잔재 riskstartup probe (lifespan)비고
blueprint-mcp✅ 해소 (D-bp-mcp-3 2026-05-22)✅ 적용됨.env line 제거 + config fail-fast + lifespan SELECT 1
frame-mcpN/A (URL self-construct, env string 안 씀)미적용/health/ready 는 request-time only (frame/src/frame/mcp/http_server.py:594)broken DB 로 부팅 가능, swap promote 위험. lifespan probe 1 블록 추가 권장 (blueprint pattern mirror)
hive-mcpN/A (frame 패턴 동일)미적용hive/src/hive/mcp/http_server.py:364동상

복붙 메시지 (운영자가 frame/hive owner 에게 전달): /architecture/mcp-server-checklist#16 startup probe pass 참조. 5-10 분 작업.

claude.ai 멀티-커넥터: 1 커넥터의 나쁜 key 가 전체 tools/list 400 (2026-05-28)

claude.ai 는 활성화된 모든 커넥터의 tool 을 하나의 tools 배열로 합쳐 API 에 보냄. 따라서 어느 한 커넥터 tool 의 inputSchema property key 가 ^[a-zA-Z0-9_.-]{1,64}$ 를 위반하면 → 400 tools.N.custom.input_schema.properties요청 전체 거부 → 그 대화의 모든 커넥터(결백한 것 포함)가 같이 막힘. tools.N 의 N 은 결합 배열 인덱스라 커넥터 on/off 시 바뀜 → 범인 특정이 어려움 (Cortex 함정 #6 의 cross-connector 확장판).

  • 2026-05-28 발견: cortex register_person 이 tools.15/tools.10 으로 막힘. cortex(12)·frame(51)·hive(39) 라이브 tools/list + Claude-in-Chrome 22 스키마 직접 검증 → 전부 clean. 범인 = claude.ai 의 GitHub 연동(Anthropic 제공 통합) — 우리가 소스 못 고침. 사용자가 그 커넥터만 비활성화 → 즉시 해소.
  • 진단법 (사용자에게 커넥터 토글 반복 요청 금지): 각 서비스의 mcp-token CLI(frame/hive) 또는 HS256 수동 mint(cortex)로 로컬 tools/list(blue 컨테이너 직접) 받아 모든 property key 를 정규식 검증. Anthropic 커넥터(GitHub 등)는 소스 접근 불가 → 소거법으로 좁힌 뒤 사용자가 해당 커넥터 비활성화 + 앱 내 피드백 신고.
  • 예방: 우리 서비스는 trap #6(ASCII-only key) 준수. CI/axe mcp publish 에 “served tools/list 의 모든 property key 정규식 lint” 추가 권장 (backlog 가치).

신규 ship 된 MCP tool 이 이미 연결된 Claude 세션·서브에이전트에 안 보임 — tools/list 재동기 지연 (2026-05-29)

Blueprint MCP send_mail (D-bp-mcp-mail-1) ship + self-send Graph 202 검증 직후, 운영자의 active Claude Code 세션에서 호출 → No such tool available. 같은 세션에서 spawn 한 서브에이전트도 동일 (ToolSearch 4회 모두 미발견).

MCP 클라이언트(Claude Code / claude.ai)는 연결 handshake 시점의 tools/list 를 캐시한다. 서버에 tool 을 새로 배포해도 이미 연결된 세션은 재동기 전까지 못 본다. 서브에이전트(Agent tool)는 부모 세션의 MCP 연결을 공유하므로 스폰으로도 해소 안 됨 (stale registry 상속).

  • 결정적 해결 = 새 세션: spawn_task 칩 / 세션 재시작 / 커넥터 reconnect(/mcp). fresh handshake → fresh tools/list.
  • 자가 해소되기도 함: 본 건은 일정 시간 후 클라이언트가 재-list 하여 같은 세션에 send_mail 이 deferred tool 로 떠 호출 성공(재시작 없이). “전파 지연”이지 영구 차단 아님 — 타이밍은 비결정적.
  • 오진 주의: “tool 미발견 = 배포 실패” 단정 금지. 서버 측 검증(self-send 202 / 컨테이너 직접 tools/list)이 통과하면 배포는 정상, 클라이언트 캐시 문제다.
  • 운영 수칙: MCP tool ship 후 같은 세션 즉시 호출 실패는 정상. 급하면 새 세션(칩/재시작), 아니면 잠시 후 재시도.

Cortex production live — 7 함정 (2026-05-28, 신규 Rust MCP 서비스 첫 배포)

cortex (Rust + axum + sqlx, 첫 비-Python MCP 서비스) 를 claude.ai connector 까지 live 시키며 밟은 함정. index (D-index-2) 가 cortex 1:1 미러라 그대로 상속 — 등재 순서대로 회피할 것.

#함정증상회피
1DB password 의 base64 /·+·= 가 connection URL 파싱 깨뜨림error with configuration: invalid port numberpostgres://user:pa/ss@host:port 에서 / 뒤가 port 자리로 오인sqlx PgConnectOptions::new().host().port().username().password() 빌더 사용 (URL string 조립 금지). cortex src/db.rs::connect_options
2docker compose env_file: 가 따옴표를 literal 로 처리axe secret pullKEY="val" 로 쓰면 컨테이너 안 env = "val" (따옴표 포함) → postgres auth 실패 / secret mismatch. compose .env (variable substitution) 은 따옴표 strip 하므로 postgres init 은 unquoted, mcp 컨테이너만 quoted → 불일치env_file 값은 unquote. 임시: sed -i '' -E 's/^([A-Z_]+)="(.+)"$/\1=\2/'. 영구: B-axe-secret-pull-noquote (axe secret pull 이 quote 안 붙이게)
3RFC 9728 resource-level metadata path 누락claude.ai 가 <application_id_uri>/.well-known/oauth-protected-resource (= /cortex/mcp/.well-known/...) fetch 시도 → 404 (server-level /cortex/.well-known/... 만 있으면 부족) → discovery 실패 → origin /authorize fallbackserver-level + resource-level 둘 다 라우트. D-ops-23 frame 학습 — cortex 가 미반영했다 재발
4RFC 8414 path-insertion — authorization_servers 를 자기 (path 있는 issuer) 로 두면 안 됨authorization_servers: ["https://axe.axelabs.ai/cortex"] → claude.ai 가 RFC 8414 §3.1 따라 https://axe.axelabs.ai/.well-known/oauth-authorization-server/cortex (host 와 path 사이 삽입) 에서 metadata 찾음 → 우리가 serve 하는 /cortex/.well-known/... (path append) 와 불일치 → 404 → origin /authorize fallback → blueprint 404authorization_serversMicrosoft 직접 (login.microsoftonline.com/<tenant>/v2.0) 로. claude.ai 가 Microsoft OIDC metadata fetch → Microsoft endpoint 사용. self-hosted AS proxy 불필요 (D-cortex-8, frame “직접-Microsoft” path)
5claude.ai connector 는 client_id + client_secret 입력 필수URL 만 입력 시 confidential client credential 없어 OAuth 미완Advanced field 에 client_id (Entra appId) + client_secret 입력. frame/hive/blueprint 와 동일 (D-vault-mcp-catalog, axe mcp publish 로 Bitwarden 확장 auto-suggest)
6MCP tool inputSchema property key 는 ASCII only한글 key ("메모") → Anthropic API 400 tools.N.custom.input_schema.properties: Property keys should match pattern '^[a-zA-Z0-9_.-]{1,64}$'해당 connector 의 tools/list 전체 거부 (1개 나쁜 key 가 12 tools 모두 막음). claude.ai 에서 silent failproperty key 는 ASCII (memo). 한글 값은 additionalProperties: true 로 런타임 전달 가능 (key 만 제약). cortex commit dfa9330
7Cloudflare 터널이 Dashboard remote-managed로컬 ~/.axe/tunnels/axelabs/config.yml 편집 + 컨테이너 재시동해도 ingress 안 바뀜 (cloudflared log 의 Updated to new configuration version=N 이 remote 적재 증거). axe-tunnelaxelabs-tunnel 이 다른 컨테이너 (전자 = axellc.com zone, 후자 = axelabs.ai zone) — 잘못된 것 재시동하기 쉬움Cloudflare Dashboard 또는 API (PUT /accounts/<acct>/cfd_tunnel/<uuid>/configurations, token = vault Cloudflare API - axelabs) 로 ingress 변경. axe_cf_request helper 가 이미 있음 → B-axe-tunnel-add-ingress CLI 화 권장

부수: (a) Docker image 는 cargo build (호스트) 와 별개 — 코드 변경 후 docker compose up -d --build 필수 (안 그러면 옛 binary). (b) shred 는 macOS 미존재 (Linux 전용) — rm -P 또는 APFS+SSD 에선 rm 으로 충분. (c) Google OAuth consent 2026-05-29 Testing → production 전환 (client 135512942819-l18ra7gkf1ac93ai8t4hf2h4jl6mi0a2.apps.googleusercontent.com, project no. 135512942819). Testing 시절 함정(Test users 목록의 Gmail 만 허용·100명 한도·미등록=403 access_denied, + refresh_token 7일 만료로 sync 주기적 단절 위험)은 production 전환으로 해소. 잔존 함정: 스코프 auth/contacts 는 Google sensitive 인데 앱이 unverified → 동의 화면에 “확인되지 않은 앱” 경고 + unverified 사용자 100명 상한. 사용자는 고급 → “<앱>(으)로 이동(안전하지 않음)” 으로 통과(동작엔 지장 없음). 경고 제거 = Google 정식 검증 → B-cortex-google-oauth-verify (금전비용 0contacts 는 sensitive 라 CASA 제3자 보안평가 불필요; restricted 였으면 수천 $/yr). Internal user type 은 Workspace 조직원 한정이라 개인 Gmail 연동엔 부적합.

Cortex — attended relationship 방향 불일치 (2026-05-29 PM12, 미해결): interaction↔person 의 attended 엣지가 두 생성 경로에서 반대 방향. log_interaction MCP = from=interaction → to=person, xlsx_hpe/backfill = from=person → to=interaction. 따라서 “interaction 의 참석자” 를 한 방향만 가정해 쿼리하면 절반 누락. 현재 대응: web fetch_attended_participants$iid IN (from,to) 후 반대쪽 endpoint=person 으로 양방향 흡수 (display 레벨 해소, 36 interaction 전부 resolve). 미해결: 데이터 정규화(36건 방향 통일) migration 미실시 — 새 코드가 “interaction 의 attended” 를 짤 때 반드시 양방향. 우회 invariant 는 cortex CLAUDE.md 운영 함정에도 기록.

index 측 — proceeds 산정 정밀도 (2026-05-29, D-index-22 audit)

EV→EqV(net debt) bridge + 투자 후 dilution 이 7-deal 에 비일관 적용된 사실 (사용자 audit 발견). D-index-22 가 schema/validate 로 강제 (proceeds_basis enum + Check 7 stake×(EV−net debt) ±2% reconcile, broken bridge hard-reject) 하고 Sendy 는 ev_bridge 로 정정 (net debt 0, IRR 불변 6.47%). 잔여 분석적 사실:

항목현재 상태후속
Iippo·Canopy legacy_evEV-based 이나 per-leaf 에 exit_ev/net_debt/stake 미itemize → validate Check 7 = legacy_ev WARN 2건. Canopy 는 net debt 300억 을 model-level exit_assumptions 에 명시(EqV 498억)했으나 per-leaf 분해 안 됨; Iippo 는 asset-light net debt~0B-index-proceeds-bridge-retrofit — per-leaf ev_bridge 전환 (40+/30+ leaf)
Iippo·Sentry entry-F/D-flat dilutionexit proceeds 가 entry fully-diluted stake (Iippo 2.065% / Sentry 4.46%) 를 exit 까지 flat 적용 — Pre-A→exit(57y) 사이 Series A/B 신주 희석 미반영 → proceeds·IRR 수 pp 과대 낙관. RCPS anti-dilution/pro-rata 부분 상쇄Closed deal 이라 사후 정정 실익 낮음 — retrofit 시 exit_stake 를 round-별 희석 반영값으로. pre-IPO 3 + Sendy 는 이미 exit-date 희석 stake 명시라 해당 없음
net debt = screening 가정 (BS 부재)Sendy net debt 0 은 dataroom 에 BS 없어 asset-light + 자금니즈 equity 충족 근거의 보수적 screening 가정DD 단계 실 BS 확보 시 exit_net_debt_krw 한 줄 수정 → proceeds·IRR 자동 재산출 (deterministic)

frame 측 미완 (회계 도메인 확장)

항목현재 상태후속
AXEV 창업기획자 펀드 회계Migration #1 + #3 일부 완료 (2026-05-22, D-ops-22). shared.entityentity_kind/fund_meta/closed_at ADD + shared.entity_relationship 확장 (numerator/denominator/unit + gp_managed_fund/lp_invested_fund) + shared.cross_journal_link 신설 + register-entity CLI --kind/--fund-meta flag + alembic 0008_shared 적용 + frame-mcp blue/green rebuild + tests/test_shared_fund_domain.py 16 PASS. axec/axev/axtest 자동 entity_kind=‘corporate’. 강태훈 대표 2026-05-23 자료 ingest 예정 (Evidence + entity meta + 통장내역 raw_transaction). 잔여: 펀드 전용 계정과목 (출자금·미출자약정·평가손익·분배금) + capital call / waterfall + AXEV↔조합 cross-entity mirror 분개 (GP commitment·운용보수·성과보수) 모두 미구현Architecture (2026-05-21 채택 + 2026-05-22 drift 정정 + 2026-05-22 Migration #1 적용):
기존 shared 확장 ✅완료 (frame_meta schema 신설 폐기 — 코드 탐색 결과 기존 객체와 명명 충돌 + cross-entity 메타 layer 가 이미 shared 에 존재): ① shared.entityentity_kind (corporate/kip/kvf) + fund_meta JSONB + closed_at 컬럼 ADD ✅. ② shared.entity_relationship (PR #26) 에 ownership_numerator/denominator/unit 컬럼 ADD (% 폐기, 반올림 오차 회피) + kind ENUM 확장 (gp_managed_fund/lp_invested_fund 추가) ✅. 의미 매핑: entity_a=holder, entity_b=target. ③ shared.cross_journal_link 신설 (mirror 분개 pair, schema 격리 환경 무결성) ✅.
• fund schema 내부 (미구현): commitment_ledger (LP 약정/call/미출자 off-BS) + lp_master (조합원 + optional external_entity_id) + (optional) fund_waterfall_state.
• fund 계정 seed (미구현): 기존 shared.account_template 에 새 standard 'fund_ksme' 추가 + 펀드 계정 row.
• Blueprint = workspace↔entity scalar 1:N (Workspace.entityId 단일). 사용자 결정 (2026-05-22, PR #339 ): OneDrive /Ventures/ /Corporation/ 폴더 분리가 SOT, fund 회계의 cross-entity 는 User.entityScopes 로 처리. N:M WorkspaceEntity join 권고는 reject (over-engineering).
• 권한 enforcement = Blueprint middleware (gatekeeper). frame 은 entity_id 동등 처리. 기존 entity_session search_path 패턴 (entity_id == schema_name) 유지.
• 회계 원칙: AXEV↔fund = parent-child 아닌 운용 관계 (K-IFRS 1110 통제 미달). relation_kind 가 회계 처리 갈래 (지분법/공정가치/운용보수) 결정.
Migration 순서: (1) ✅완료 shared 확장 + cross_journal_link 신설 (alembic 0008_shared) [D-ops-22], (2) fund_ksme standard + seed [D-frame-N2], (3) ✅일부완료 (CLI --kind/--fund-meta) — 잔여: MCP register_entity tool (CLI 의존 제거) + list_sub_entities tool [D-frame-N3], (4) Blueprint WorkspaceEntity migration [D-bp-entity-1 수정], (5) 결성 조합 schema bootstrap + shared.entity row [조합 detail 대기], (6) fund schema 의 commitment_ledger/lp_master + 과거 결산 적재, (7) cross_journal_link 활용한 mirror 분개 tool [D-frame-N4]

frame shared.entity 의도 불명 row (axep)

2026-05-26 audit 발견. shared.entityaxep (legal_name “액스파트너스 유한책임회사”, entity_kind=corporate, accounting_standard=ksme, 2026-05-22 08:56 등록) 의 등록 의도가 확인되지 않음. audit_logaccount 한 table 의 chart seed 만 (운영 데이터 0). actor null, biz_no 없음, git 검색 결과 코드에도 언급 0.

후속: 강수훈 의도 확인 → (a) 실제 액스파트너스 유한책임회사 설립 의도면 보존 + biz_no/fund_meta 보강, (b) 단순 placeholder/test 면 DROP SCHEMA axep CASCADE + DELETE shared.entity. 본 row 는 D-frame-register-entity-atomic 2026-05-26 cleanup 사이클에서 보존 결정 (low-risk to leave, 강수훈 confirm 대기).

디자인 시스템 배포 (@axe/ui · axelabs.ai)

항목현재 상태후속
@axe/ui 패키지 발행 채널git+ssh 직접 임포트 (pnpm add 'git+ssh://...axelabs#tag'). dist 빌드 없이 raw TS export — 소비자는 transpilePackages: ["@axe/ui"] 명시 필요. npm registry / Verdaccio / GitHub Packages 모두 미사용v0.1 stable 후 GitHub Packages 검토. 현재 React 소비자 ≤3개라 git+ssh 로 충분
axelabs.ai 도메인 라이브✅ LIVE — apex + www + docs + design 모두 tunnel 경유 200 (2026-05-29 검증). 컨테이너 axelabs (127.0.0.1:3900), axelabs-docs (3140).(완료)
design.axelabs.ai 디자인 시스템 도메인 (D-ui-3) LIVE✅ 2026-05-29 — ui.axelabs.aidesign.axelabs.ai 완전 교체. DNS proxied CNAME (axelabs.ai zone, CF API) + tunnel remote config v21→v22 (ui→design 1-rule swap) + axelabs rebuild (proxy.ts host 분기). 검증: design 200(@axe/ui 페이지)·sub-path 308·ui 404·axelabs.ai/www/docs 무영향함정 4: ① tunnel ingress = remote-managed (config.yml 무효 — 본 페이지 “Cortex production live 7함정” #7) → PUT /accounts/<acct>/cfd_tunnel/<uuid>/configurations (token=vault Cloudflare API - axelabs). ② axelabs.ai zone DNS 는 반드시 CF API 토큰cloudflared tunnel route dns 는 cert-scoped(axellc.com) 라 <host>.axellc.com 오생성 (이번에 design.axelabs.ai.axellc.com 생겨 삭제함). ③ host 분기 = proxy.ts (next.config rewrites 아님 — 정적 prerender / 우회). ④ 신규 1-level host 직후 로컬 resolver AAAA-only → IPv6 무라우팅 머신 curl HTTP 000 (production 무관, curl -4/--resolve 검증)
Clash Display @import drop 함정Fontshare URL 의 f[]= 대괄호가 Next.js CSS @import 빌더에서 떨궈진다 (현 16.2.6 확인). 해결: <link rel="stylesheet"> 를 layout 의 <head> 에 직접 추가. Pretendard·D2Coding @import 는 정상다른 서비스 마이그레이션 시 같은 함정 안 빠지게 README + /ui#consume 에 명시. 향후 Next.js 픽스 시 재검토
nextra 테이블 셀 코드스팬 안 escape 안 된 파이프 → build 깨짐2026-05-29 발견 (decisions.mdx D-cortex-google-drift). 마크다운 테이블 셀의 inline code 안에 escape 안 된 파이프 문자(예: JSON-ish payload 의 union 타입 표기)가 있으면 GFM 이 그 파이프를 셀 구분자로 먼저 분리 → 백틱 스팬이 깨지고 그 안 중괄호가 미닫힌 JSX expression 으로 노출 → nextra 가 “Unexpected end of file in expression” 로 전체 build 실패. axe ship docs 의 docker build 단계에서야 늦게 잡힘. 해결: 셀 안 파이프는 항상 백슬래시 escape, 중괄호·꺾쇠도 코드스팬 의존 말고 escape (꺾쇠는 HTML entity). 예방: ship 전 로컬 npx next build 로 컴파일 확인 (docker 왕복보다 빠름).여러 세션이 같은 mdx 편집 시 file 단위 git add 가 병행 세션 WIP 까지 휩쓸 수 있음 (이번 cortex D-cortex-google-drift 가 index 커밋에 혼입) → ship 전 staged diff 확인. docs ritual 에 “ship 전 npx next build” 추가 검토
Button asChild 미지원현재 Button 컴포넌트는 raw <button> 만 — anchor 가 필요하면 <a className="axe-btn axe-btn--primary"> 패턴 직접 사용. axelabs.ai 메인 페이지가 이 패턴으로 작성됨v0.2 에서 Radix Slot 패턴 도입 검토
dist 빌드 부재package.json exports 가 ./src/lib/index.ts (raw TS) 를 가리킴. tsup/unbuild dist 빌드 없음 — 소비자 측 트랜스파일러에 의존Next.js / Vite 둘 다 transpilePackages 로 가능. dist 도입은 외부 OSS 공개 시점에
standalone build 의 output: "standalone" 의존Dockerfile 의 .next/standalone copy 가 next.config.mjs 의 standalone output 설정에 의존. 누락 시 빌드 failnext.config 주석으로 표시. config 변경 시 Dockerfile 같이 확인
문서 템플릿 @page 전역 누수 (D-ui-3 Phase 2).axe-doc 인쇄용 A4 @page 를 전역 bare @page (size A4) 로 선언하면 design 사이트 전 페이지 인쇄가 A4 로 강제됨 (@page 는 문서 전역 스코프). 해결: named @page axe-doc-portrait/axe-doc-landscape + .axe-docpage: 속성으로 스코프 — document.css 적용 완료다른 인쇄 surface 추가 시 동일 패턴. jinja 템플릿 로컬 렌더·검증엔 jinja2 필요 (system python3 미포함 → python3 -m venvpip install jinja2)

docs verify:box 오탐 — orphan next dev 의 IPv6 :3140 port-shadow (2026-05-29)

axe ship docs 의 post-deploy verify:box (playwright page.goto(localhost:3140, networkidle)) 가 TimeoutError: page.goto: Timeout 30000ms exceeded 로 실패 → ”❌ POST-DEPLOY VERIFY FAILED — production 박스 정렬 깨짐 (exit 3)” 출력. 그러나 배포는 성공했고 production 은 정상 — 전형적 오탐. ship 자체를 의심해 롤백/재빌드 하면 멀쩡한 배포를 헛돌린다.

근본 원인: host 에 떠 있던 orphan next dev --port 3140 (parent=launchd, 4h+ 방치된 로컬 docs dev 잔여) 가 IPv6 *:3140 을 점유. localhost::1 을 먼저 resolve 하는 macOS 특성상 host 의 모든 localhost:3140 접근 (playwright + curl) 이 죽은 dev 서버로 빨려감. production docker container 는 IPv4 127.0.0.1:3140 으로만 노출되고, 외부 docs.axelabs.ai 도 tunnel 이 host.docker.internal (IPv4) 로 origin 을 잡으므로 — 둘 다 멀쩡한데 host loopback 경유 검증만 깨진다.

검증 경로결과
curl localhost:3140 (host, ::1 우선)hang / timeout (orphan dev)
curl -4 127.0.0.1:3140200 / ~10ms (production container)
docker inspect in-container healthcheckFailingStreak: 0 (정상)
외부 https://docs.axelabs.ai신규 본문 정상 서빙

진단 분기점: lsof -nP -iTCP:3140 -sTCP:LISTEN → listener 가 두 개 (IPv6 node vs IPv4 com.docker). IPv6 쪽 PID 의 parent 가 launchd 이고 그 PID 가 production 트래픽 0 이면 orphan 확정. verify:box 만 깨지고 curl -4 + in-container healthcheck + 외부 도메인이 모두 통과하면 = 배포 OK · 검증 경로 오염.

조치: orphan 을 kill -TERM <pid> (graceful, SIGKILL 불필요 — production PGID 와 무관). 이후 localhost:3140 이 IPv4 로 fallback → verify:box 재실행 PASS. 예방: 로컬 docs dev 는 끝나면 반드시 종료할 것. :3140 은 production container 점유 포트이므로 로컬 dev 는 다른 포트 권장 (npx next dev --port 3142 등).

Blueprint Postgres — prisma migrate deploy 가 P3005 로 신규 마이그레이션 자동 적용 안 함 (2026-05-30)

blueprint-postgres 는 D-config-17 cutover 때 db push 로 부트스트랩돼서 _prisma_migrations 베이스라인 테이블이 없다. 그래서 컨테이너 기동 시 start.shprisma migrate deployP3005 (“The database schema is not empty”) 로 거부하고 [start] prisma migrate deploy failed (non-fatal) 만 찍고 넘어간다. 결과: prisma/migrations/ 에 새 마이그레이션 파일을 추가해도 배포 시 자동 적용되지 않는다 (테이블이 생성되지 않음).

증상: route·코드는 떠 있는데 신규 테이블이 없어 prisma.<model>.create() 가 런타임에 실패. 감사 로그처럼 try/catch 로 감싼 경로면 조용히 실패할 수 있다 (D-bp-mcp-mail-1 의 MailSendLog 가 정확히 이 케이스 — route 정상 배포됐으나 테이블 부재로 audit write 가 silent fail 직전).

해결 (스키마 변경 시마다 1회):

# additive 변경(새 테이블 등)이면 해당 마이그레이션 SQL 만 직접 적용 — 가장 안전, 기존 테이블 무영향 docker exec -i blueprint-postgres psql -U blueprint -d blueprint -v ON_ERROR_STOP=1 \ < prisma/migrations/<ts>_<name>/migration.sql # 적용 확인 docker exec blueprint-postgres psql -U blueprint -d blueprint -tc "SELECT to_regclass('public.\"<Table>\"');"

2026-05-30 기준 같은 함정에 걸린 마이그레이션: 20260529120000_add_mail_send_log (수동 적용 완료), 20260531000000_add_user_entra_oid (다른 세션 작업 — User.entraOid 컬럼, 수동 적용 필요할 수 있음), 20260603100452_add_entity_legal_name (C1 — Entity.legalName 영문 법인명 + axec/axev 백필, 미적용 — 배포 시 위 psql 직접적용 패턴 사용; additive·기존 테이블 무영향).

근본 fix 후보 (backlog): 기존 마이그레이션 전부를 prisma migrate resolve --applied <name> 로 베이스라인 등록 → 이후 migrate deploy 정상화. 또는 deploy hook 에 db-push fallback 추가.

문서 작업 다음 단계

  • CLI Phase 5 완성 후 runbook 의 restic 명령을 axe restore 로 단순화
  • com.axe.secret-check / com.axe.health-check launchd 구현 후 cloudflared.mdx 갱신
  • partner/registration.mdx 와 frame/docs/ops/onboarding-operator.md §0 일관성 점검
  • customers.yaml 에 blueprint app 슬롯 추가 (현재 frame_mcp 와 vaultwarden 만)
  • Blueprint MEMORY.md 33.5KB → 24.4KB pruning (~/.claude/projects/-Users-axe-blueprint/memory/MEMORY.md index 항목 길이 정리, /ctx review 별도 세션)

axelabs 5 표준 (2026-05-26, Truvia 측 요구로 명시화)

운영자 측 분석 (B-customer-deploy-generalization Phase 1 + Truvia D-day 후속 회신 기반) 의 axelabs platform 표준. 각 항목은 decisions.mdx 의 D-config-N 또는 D-ops-N 으로 별도 격상 검토.

#표준본질시행
1macmini 운영 패턴 = 기존 자산 ≡ 신규 발주 (동등 지원)customer 가 가동 중 macmini 에 platform 도입 시 발주·재설치 의무 없음. 14 컨테이너 기존 가동 + Tailscale 합류 + SSH key 기등록 케이스 (realchoice) 1급 지원./partner/macmini-existing (신설 예정 — B-docs-ssot-extension), B-port-conflict-preflight 가 충돌 게이트
2Vault repo (soohunkang/vault.git) 표준 image = timshel/vaultwarden:latestVaultwarden Timshel fork 가 axelabs platform 표준. customer 측이 다른 vault image (e.g. official vaultwarden/server) 사용 시 SSO/sso_nonce/healthcheck/path mount 패턴 모두 다름. Truvia 측 5/26 D-ops-32 검증 = Timshel + collection 구조 정렬./services/vaultwarden (신설 예정), image_override slot 으로 customer-별 version pin 허용
3bw CLI 표준 version = 2025.7.0 (D-ops-28 line)bw 2026.4.x 가 Timshel SSO user 호환성 차단 (“Master password unlock data was not found”, trap #12). 2025.7.0 = 최후 호환 release.bw-bootstrap.sh 가 install hint + warning gate. _svc_step_customer_vault_check 가 version mismatch warning. backlog B-bw-cli-version-pinning.
4Customer-측 self-deploy 일반화 = R1-R5 빌트인 (B-customer-deploy-generalization Phase 1)(R1) ${HOME} 변환 — hardcoded /Users/axe/ 금지. (R2) vault SoT — bw CLI 기반, keychain 의존 폐기. (R3) env_file $$$ escape — escape_dollar flag 자동. (R4) image_override slot — customer-별 service repo image pin. (R5) ${CUSTOMER_PREFIX}- container name 정규화 (Phase 2).axe CLI _deploy_service_customer + wrapper 3종 + customers.yaml schema.
5customers.yaml schema = secret manifest + service_tenant_map + image_override + escape_dollar slotscustomer 메타 + sso.apps[].client_id + services.<svc>.<env_file, secrets[], image_override> + service_tenant_map (D-magnet-tenant-map-1) + ring_backup + entity_meta. ruamel.yaml round-trip 으로 comment 보존. axe customers ingest 가 자동 fill./Users/axe/.axe/customers.yaml (SSOT), INGEST_MANIFEST_TEMPLATE (axe CLI), schema doc = /architecture/customers (신설 검토).

세션 의례 (다음 세션 / 다른 세션 모두)

모든 axelabs.ai 작업 세션은 본 페이지를 의례로 사용:

  1. 세션 시작 시 — READ: 작업 주제와 관련된 known-gap 이 있는지 본 페이지 확인. 이미 등재된 gap 을 모르고 작업하면 다른 사람의 작업과 중복되거나 충돌 가능.

  2. 세션 중 — DISCOVER: 작업 중 새 gap / 미구현 / 약속 vs 실제 불일치 발견 시 즉시 본 페이지에 한 줄 추가 (해당 섹션에 표 row 추가). 메모리에 들고만 있지 말 것.

  3. 세션 종료 시 — WRITE: 본 세션이 해소한 gap 은 즉시 제거. 새로 발견한 gap 은 등재. 다음 세션의 다른 사람이 본 페이지만 보고도 현재 상태 파악할 수 있어야 함.

  4. 페이지가 비어가는 것이 목표. 단 의도된 deferral (예: “Phase 5 에서 통합”) 은 등재 후 phase 표기.

운영자 또는 협업 세션에 본 ritual 이 적용되도록 root CLAUDE.md + per-repo CLAUDE.md 에 명시.

본 페이지의 의도

다음 세션의 본인 (또는 협업자) 이 문서를 보고 작업할 때, 약속된 것실제 작동하는 것 의 격차를 명확히 알도록 함. 격차 자체가 함정이 되지 않게 정리.

Last updated on