<!-- canonical: https://docs.axelabs.ai/ops/updates -->
<!-- source: content/ops/updates.mdx -->

---
title: 업데이트 (Updates)
description: docs.axelabs.ai + 플랫폼의 ship 별 changelog + Highlights + API feed. 시간축 = 과거 (이미 한 일).
---

# 업데이트 (Updates)

> **시간축 4-페이지 분리** ([D-docs-updates-1](/ops/decisions), 2026-05-22):
>
> | 페이지 | 시간 | 용도 |
> |---|---|---|
> | [roadmap](/ops/roadmap) | **미래** | 분기 마일스톤 (M1~M5) |
> | [backlog](/ops/backlog) | **현재** | 1주 안 행동 큐 |
> | **본 페이지** | **과거** | ship 별 changelog + 큐레이션 highlights |
> | [known-gaps](/ops/known-gaps) | (사실) | 함정·미해결 |

본 페이지는 **3 섹션**:

1. **Ship Log** — 매 `axe ship SERVICE` 마다 한 줄 자동 기록 (Phase 2: [`B-axe-ship-update-hook`](/ops/backlog)). Phase 1 (현재) = 수동 append. 정직 채널, 운영 회고용.
2. **Highlights** — 사람 큐레이션. 의미 있는 변경만 narrative (직원·외부 IT 용).
3. **API feed** — [`/api/changes`](/api/changes) JSON endpoint. LLM agent 가 "지난 N일 변경" fetch.

---

## Ship Log

> 매 ship 의 한 줄. `2026-MM-DD HH:MM — SERVICE ship — COMMIT-SUBJECT` (commit hash + service stack).
>
> Phase 1 (수동 append) — 운영자가 `axe ship SERVICE` 후 한 줄 추가.
> Phase 2 (완전 자동) — backlog 의 [`B-axe-ship-update-hook`](/ops/backlog) 항목.

| 일시 (KST) | Service | Commit | 한 줄 |
|---|---|---|---|
| 2026-06-05 | vault (axe org) | (운영자 action + docs) | **vault axe.3 — 4명 KDF rotation 전부 완료 → D-ops-40 전체 종결** ([D-ops-40](/ops/decisions) Progress xiii). ai (5/27) → soohun → taehun (5/29) → jinwoo (6/4) 순서로 SSO→MP unlock 정상화. **본질 발견 = KDF dropdown 변경 불필요** — Master password change + ☑ "Also rotate my account's encryption key" 만으로 user.akey 재wrap 충분 (kdf_type 안 바뀌어도 fix 동작, ai 만 Argon2id 까지). jinwoo last_login 5/23→6/4 점프 = 완료 신호. taehun 실사용 피드백 6건 → [/onboard/vault-setup](/onboard/vault-setup) playbook 반영 (Windows section + Phase 강제도 + TOTP UI 동작 + SSO 사용자 검증 분기 + valid 변형) + [B-vault-revoke-scope-doc](/ops/backlog) (vault trust boundary). [B-vault-axe.2-sso-mp-incomplete](/ops/backlog) ✅. **D-ops-40 전 작업 (build pipeline + 4 patches + GHCR + deploy + 검증 3건 + 정책 layer + 4명 rotation) 종결** — self-host vault 의 Bitwarden client compat + organization 권한 + SSO→MP 영구 fix 완성. |
| 2026-06-04 | docs | `22b1334` | docs(frame): D-frame-2 evidence blob-storage + D-frame-3 CF classification rule _(auto-logged by `axe ship` — curate/expand, then Highlights)_ |
| 2026-06-04 | docs | `ed65f9b` | docs(ops): netheal install complete + Claude.app pty-leak osascript workaround _(auto-logged by `axe ship` — curate/expand, then Highlights)_ |
| 2026-06-04 | hive | `48f38a1` | feat(auth): trust Blueprint platform tokens (D-axe-idp-1 Phase 2) _(auto-logged by `axe ship` — curate/expand, then Highlights)_ |
| 2026-06-03 | frame | `f1b124d` | feat(auth): trust Blueprint platform tokens (D-axe-idp-1 Phase 1) _(auto-logged by `axe ship` — curate/expand, then Highlights)_ |
| 2026-06-04 | index | `b273979` | **evidence-durability v1 — citation sha256 anchor (B-index-evidence-durability)** — 운영자 "workspace unique id" 제안 + 폴더 이동/삭제 분석에서 도출. citation 을 fragile path → stable anchor: `sha256` content-anchor(범용·무의존) + Blueprint-id(`workspace_id`/`driveItemId`/`marker`) 필드 readiness. `CitationAnchor`+`is_durable` · ingest sidecar sha256 + **propose-time fallback hashing**(skill 무변경에도 durable) · `verify_citations` MCP tool · 현황 페이지 durable% 라인. **additive**(기존 357 artifact/545 citation byte-identical) · 80 test · validate-seeds Δ0 · 공개 페이지 누출 0. blue/green deployed. deferred(v2): 545 backfill · Blueprint resolve API · driveItemId 채우기. |
| 2026-06-03 | blueprint | `57ff2ac7` | feat(auth): Blueprint as platform OIDC Provider (D-axe-idp-1 Phase 1) _(auto-logged by `axe ship` — curate/expand, then Highlights)_ |
| 2026-06-03 | blueprint | `#381`+`#382` | **전략 P3 — investment skill vertical-gate (contamination purge, D-index-47)** — 사용자 merge 승인. 8 투자 skill(ic·ingest·due-diligence·vc-deal-sourcing·investor-relations·portfolio-management·legal-compliance + pmc)에 `owner:index` 태그 + blueprint boot(`start.sh`)/webhook(`route.ts`) 양 경로 gate(customer `services.index` → 비-index `rm -rf`+skip purge, index keep). **axe 3중 안전**(services.index + `:-axe` 기본 + fail-safe keep + 운영자 ungated → simul KEEP 16/16) · realchoice/Truvia PURGE 7/KEEP 9 · `customers.ts customerHasService` + test 21/21 · tsc 0. pmc(index-only)도 base 로 mirror(gated→axe 만). PR #381(gate)+#382(pmc) squash-merged origin/main. 운영자 잔여: Truvia env 확인+재기동 purge + R7 DB residue. rollback=revert(axe 무영향). |
| 2026-06-03 | index | `6edf0ff` | **전략 P2 — index→blueprint attest sentinel + mirror mechanism (D-index-47)** — 사용자 "P2 진행". ⭐ 조사 결과 "런타임 fix" 는 **이미 달성**(P0+기존 sync): ic/ingest 가 index SoT↔blueprint origin/main↔런타임 byte-identical(attest IN-SYNC). 그래서 P2 = 위험한 content push 아닌 **메커니즘**: `index-skill-sync.py`→`--attest`(deterministic dir-sha256 drift sentinel) 재범위 + `index-skill-mirror.sh`(미래 미러, sanctioned PR flow, pmc fail-closed) 빌드. **blueprint 무쓰기·무push·무PR**, pmc 보류(P3 contamination gate 전). note-3 worry 해소 — 런타임이 stale 이 아니라 index 가 stale 이었음. |
| 2026-06-03 | index | `11aca12` | **전략 P1 — provenance stamp + schema-drift gate (D-index-47)** — 사용자 "P1만 진행"(P2/P3 명시-go 보존). 모든 propose 경로의 `artifact_event(op=propose).payload_after` 에 `_provenance` 스탬프(frozen_enums_hash 포함) + schema-drift hard gate(불일치→`SCHEMA_CONTRACT_DRIFT`, insert 전 fail-closed). frozen_enums_hash = 전용 SoT fn(D-index-15 enum + SCRUB_KINDS + ARTIFACT_REF_RELATIONS) pinned tripwire + /index/schemas 가 publish(외부 ic-push discover+pin). additive(기존 357 artifact/event byte-identical, append-only 라 retro-stamp 없음) · 66 test(+17) · sqlx clean · validate-seeds Δ0. blue/green redeploy + live 드리프트 probe 검증(무오염). |
| 2026-06-03 | index | `8ec2c10` | **seed = SoT for judgment facts — hardcoded backfill 폐기 (D-index-46, B-index-judgment-in-seeds ✅)** — 사용자 "위생 본질 전략 순" 의 본질 leg. [D-index-45](/ops/decisions) 의 1회성 hardcode backfill(`backfill.rs`+`corpus.rs` 2824 LoC)을 제거 → seed.yaml 이 judgment 단일 SoT. per-seed `judgment:`(assumptions+calibrations) + `seeds/_corpus.yaml` + seed-ingest `--emit-judgment`(natural-name anchor→corpus id 해소, idempotent·confirm-on-create). 23 seed 마이그레이션 후 두 모듈 삭제. **HARD GATE**: 전 23 seed 재ingest +0 new · committed wipe(318→0, relational 무손상)→seed-ingest 단독 +318 byte-identical 재현(42 stale dup citation pruned) · append-only trigger intact · validate-seeds 23 Δ=+0.00 · 51 test. **신규 deal 자동 artifact화** — hardcode transcription 0. |
| 2026-06-03 | index | `1c707e1` | **artifact-first judgment layer — 증거층↔판단층 결합 (D-index-45, Epic 1, 2-wave supervised)** — 사용자 "Epic 1 같이 검토하고, 실제 구현은 서브에이전트로 · 본질에 집중 quick-fix 금지". 휴면 artifact store(39 fact)→relational 23 deal 결합: 모든 투자판단 fact 를 일급 typed+cited+audited artifact 로 승격. migration 0(generic store 재사용), 4 kind(assumption·calibration·comp·base_rate), 링크=일급 citation(index_field+artifact_ref relation, side-bridge table 아님). **23/23 deal → 357 fact**, 0 orphan judgment value. additive-only 3중 증명(event propose/confirm 만·relational updated_at 미전진·validate-seeds Δ=+0.00), 48/48 test, sqlx --check clean. ⭐ adversarial gate 가 wave1 61% 미완 적발 → wave2 5딜 author + 6 rival backfill module → 1 `backfill.rs` 통합. 방향: structured-seed 파생[B-index-judgment-in-seeds]·Epic 2 confidence load-bearing·Epic 3 self-calibrating loop. |
| 2026-06-03 | docs | `3eade41`+`19ffd2c` | **backlog C1–C5 인터랙티브 정비 + axe-cli ship-hook/drill ✅ 반영** — 운영자와 C1(entity legal영문+display한글, frame/hive/blueprint 마이그레이션 준비·미적용)·C2(axe-cli git-track → 비공개 `axelabs-ai/axe-cli`)·C3(`axe drill` freshness+robust-canary · `axe ship` post-deploy Ship Log hook)·C4(설계 DRAFT 5건 보존)·C5(미커밋 코드 전부 보존) 순차 해결. ⭐ **premise 정정**: B-backup-restore-drill = drill 메커니즘 강화일 뿐 postgres 실제 restore drill 은 미완(open 유지). 동반 게시: D-hive-29 payroll UPSERT/adjustment docs · @axe/ui resync. ⭐ 본 row = ship-update-hook 첫 실가동 산출(자동 stub → curate). |
| 2026-05-30 | index+blueprint | `931284b9`+`c8b3746` | **ingest 데이터품질 metric_kind 세분 + lifecycle 회귀 스위트 (D-index-44, 5축 평가 2 unit 병렬)** — 사용자 "지금 가능한 작업, 본질·퀄리티·결과·안전·혁신". **(X)** blueprint PR #380: convert_xlsx metric_kind 세분 — coarse valuation(절대 EV+EV/EBITDA 배수+음수 혼재, reconcile 가 노출한 결함) → `valuation`/`multiple`/`moic` 분리 + curation(음수/absurd helper drop). 52/52 test, irr·moic·cagr 0 regression(XIRR function-path 무영향). webhook sync live. **(Y)** index `c8b3746`: artifact lifecycle 회귀 8 test (idempotency·status 파생·confirm/reject·append-only(grant+trigger 이중)·RLS 격리·reconcile·seed-draft non-ingestability serde-reject), 35 pass 0 residue, offline-safe. ⭐ 발견: append-only trigger 가 ON DELETE CASCADE 차단 → event 보유 artifact 삭제불가 = audit 영속성. **통합**: 정제 classifier 재ingest → store refresh → valuation 12 + multiple 4 split 반영(39 facts). self-correcting 루프(reconcile 가 노출 → source fix). |
| 2026-05-30 | index | `3eece93`+`118568a` (deploy) | **artifact-first lifecycle 완성 — Query API+ctx review+reconcile+seed-draft (D-index-43)** — 사용자 "서브에이전트로 종결 후 보고". D-index-42(propose) 잔여 4개를 2 supervised subagent 순차 구현 + 1 blue/green. **(1) Query API**: `query_artifacts`/`get_artifact` (status=최신 event.op 파생). **(2) ctx review**: `confirm_artifact`/`reject_artifact` (op=confirm/reject, append-only 감사). **(3) reconcile**: `reconcile_artifacts` — metric_kind 별 value spread flag(불일치 전량 surface, silently 택1 금지; Apposter irr 86% flag). **(4) L2 본령 seed-draft**: `draft_seed_from_artifacts` — deal artifacts → 보수적 seed.yaml SCAFFOLD(`index draft-seed`). ⭐ 날조금지 구조강제: surface→audit주석 only, calibration·intake·baseline 전부 `~ TODO`, valuation 후보다수 자동선택 거부, draft non-ingestable(validate-seeds fail). coverage auto_filled 0/needs_human 18/surface 29. RLS 정식경로, build online+offline clean, 27 test, 6 MCP tool live(ext healthz 200). artifact-first 전 lifecycle 가동(propose→query→review→reconcile→draft). 잔여: ctx review UI(Blueprint)·Query API /ic 통합·extractor metric_kind 세분·전 deal artifact화. | — 사용자 "ingest 때 artifact화 한다던 것 구현됐나?" (정직 확인). **gap 발견**: index artifact/citation/artifact_event store([D-index-2](/ops/decisions) cortex mirror)가 Day-1 이후 **0행 미사용** — 23-deal 은 relational 테이블에만, artifact-first 층 dormant. **구현**(subagent + orchestrator QC): `propose-from-ingest` CLI + `propose_artifacts_from_ingest` MCP tool — D-index-41 sidecars(`cells.json`/`figures.json`) → 각 key_output/figure = `artifact`(extracted_metric|extracted_figure) + `citation`(cell/page 증거) + `artifact_event`(op=propose). RLS 정식경로(index_app+index.actor GUC, `db::set_current_user` 첫 실사용자), idempotent. **before/after (Apposter)**: store **0 → 35** (31 metric+4 figure, 1:1:1 artifact:citation:event). Exit IRR 57.2% = typed artifact(`metric_kind=irr`)+citation `Return!Y62`+propose event. append-only+RLS live 검증. build clean(online+offline, sqlx guard), blue/green 재배포 — `propose_artifacts_from_ingest` MCP tool live(both healthy, ext healthz 200). [D-bp-artifact-5](/ops/decisions) "proposed fact" 전반부 실현. 잔여: ctx review + Query API + L2본령(seed-draft) + L3 reconciliation. |
| 2026-05-30 | blueprint | `PR #379` | **ingest 고도화 L1 — 재무모델·IR structured extraction (D-index-41)** — 사용자 "ingest 역량 끝까지 고도화, 서브에이전트로". impl agent(worktree, skill-sot-guard 준수) + orchestrator QC. ingest 가 dataroom xlsx/pdf 를 md photocopy 하던 lossy 문제(수식 40개 truncate → `<!-- formulas: +182 more -->` 매몰, 기계추출 불가) 해소. **convert_xlsx v2**: `{stem}_xlsx.cells.json` (full grid value+formula+number_format+label, named_ranges, **key_outputs[]** XIRR/IRR/NPV/MoM/CAGR/valuation 자동탐지) + md Model Summary/Key Outputs/formula↔value 표. **convert_pdf v2**: `figures.json` 라벨인접 재무 figure sweep. 숫자=mechanical only([D-index-15](/ops/decisions)), citation(cell/page) 자동. **before/after (Apposter 20-sheet model)**: Exit IRR `=XIRR(…)` 가 truncated 주석 매몰 → **31 key outputs 자동 surfacing** (Exit IRR 57.2%/50.4%·MoM 8.60x·Entry EV 270억·9x exit, 값+수식+라벨). test 40/40 PASS·기존 포맷 무변경·의존성 0·datetime fix. QC: broad-recall false-positive(date·mislabel CAGR 25M) numeric+rate 게이트로 34→31 정정(true output 보존). PR #379 merged→main(`3a9966bd`)→launchd webhook sync→`~/.claude/skills/ingest` v2 live. [B-index-ingest-structured-extraction](/ops/backlog) L1 ✅(L2 typed seed-draft / L3 reconciliation / L4 versioned-diff 잔여). |
| 2026-05-30 | index | `de47a2c` | **Render/리얼초이스(23rd) 적재 + par-entry cheap-option = E[CF] 극단 (D-index-40) — 데이터룸 소진, DB 23** — 사용자 "더 추가할 프로젝트?". 데이터룸 전체 스캔 → 적재가능 신규 = Render 1건. **Render = 리얼초이스/트루비아**(데일리퓨어크레아틴, 크레아틴 건기식). best-effort SCREEN, status=passed (미투자 — AXE 플랫폼 고객이나 고객≠투자집행). ⭐ **par-entry**(5,000만@100원=액면=순자산, 트루비아 벤처확인 enabler 신주) → 어떤 성공도 거대 multiple → **E[CF] 35.13%**(랭킹 4위 수준)이나 **E[MoM] 4.53x·P(loss) 68%·median 손실**. exit multiple 은 0.8-1.4x commodity scrub 완료([D-index-26](/ops/decisions) fantasy 아님) — 높은 E[CF]=par 진입 구조적 산물. ⭐ **[D-index-25](/ops/decisions) poster child**: E[CF] 단독 랭킹은 par-entry 딜에서 오해 — Render 35% = top deal 아닌 **68% 손실확률 cheap call option**. SCREEN=PASS, 단 5,000만=트루비아 벤처확인 enabler+고객관계 cheap option 으로 재무 IC 와 분리. deal_id eb83b883. **데이터룸 소진**: 잔여 Whale=위시켓(자료 확보 시)·DHP 3(빈 폴더)·Artemis(AXE 자체 제품)·델리후레쉬(RFP)·thin lead 5 = 비-딜/자료대기. **23-deal 랭킹**: Sentry 43.5 > Iippo 43.3 > Starnex 38.1 > **Render 35.13(⚠par cheap-option)** > Canopy 31.8 > Interstellar 30.5 > … > Open Research −25.85. validate-seeds Δ0 Pass. |
| 2026-05-30 | index | `7d6ccca` | **Archive batch 6-deal 적재 (17~22th, D-index-39) — 전부 correctly-avoided — DB 22** — 사용자 "1_Project (Archive) 6건 모두 best effort 검토". 6 병행 agent + orchestrator 양방향 QC. 전부 archived=미투자 → [D-index-24](/ops/decisions) calibrated canonical. **Medistaff**(의료진, screen) **−0.59%** (founder 형사 jeopardy+두나무 lead) · **Open Research/oo.ai** **−25.85%**(P loss 90%) — ⭐ "deal structure ≠ company quality"(회사 2,000억 라운드 중이나 창업자 개인 distressed 담보 secondary bridge, 도박/사채/팀 9-of-9 이탈) · **JS E&L**(2차전지 부품) **−1.97%**(EV 캐즘·자본잠식 임박, PER 16x→2-8x scrub) · **Catalyst/클래스카드**(교육 PE buyout) **16.99%** — index 2nd buyout + 첫 PEF/GP구조(AXE=GP, committed=consortium 170억, 10x flat exit→5-9x scrub+60% LTV wipeout, first-time-GP 0 commit, "높은 IRR≠Go") · **데이톤/DATON**(DC AI Ops, screen) **16.57%**(흑자 100억 매출·DC tailwind 진성이나 terms-void) · **Apposter/b.ring**(스마트링) **8.34%** — ⭐ "field DD kills thesis"(현장실사 Bic Camera 방문→commodity 입증→Case Drop, Oura 10x PSR→2-3x scrub). ⭐ 교훈: (1) negative-E[CF] 기록 = PASS 결정의 정량 검증, (2) 양방향 QC(instrument floor·fat-tail scrub·wipeout)가 agent 에 briefing 만으로 전파. **22-deal 랭킹**: …EGA 23.3 > (Superman 20.8) > Catalyst 16.99 > 데이톤 16.57 > Infinity 16.5 > Eduon 15.0 > 디벨로퍼그룹 14.76 > 수성별 14.0 > Sendy 11.7 > Nanora 10.1 > Novachips 9.2 > Apposter 8.34 > 유비랩 4.06 > Medistaff −0.59 > JS E&L −1.97 > Open Research −25.85. validate-seeds Δ0 6/6 Pass. |
| 2026-05-30 | index | `c0bf6d5` | **디벨로퍼그룹(15th)+유비랩(16th) 적재 — buyout-class + 양방향 QC (D-index-38) — DB 16** — 사용자 "디벨로퍼그룹·유비랩 검토". 입력 richness 양극. **디벨로퍼그룹 스터디카페 사업부 100% 영업양도** = index **최초 buyout-class**(PE형 캐시카우 M&A, AXE 12억/EBITDA 3.87x, 무차입, 보통주/secondary). full IC v5 surface 공식 34.09% → **메모 자신의 Devils-reweighted 16.5% anchor**([D-index-24](/ops/decisions) 미집행→calibrated + [D-index-26](/ops/decisions) Exit 5.0x→4.0x·조정EBITDA·kakao 9,251M fantasy scrub + [D-index-21](/ops/decisions) genuine wipeout) → **E[CF] 14.76% / E[MoM] 2.02x / P(loss) 15%**. ⭐ buyout 신 insight: cashflow buyout 의 FCF 배당이 실질 하방 floor → downside ~1.1x(원금손실 거의 없음), **P(loss) VC 대비 구조적 저**. deal_id b88e2dcb. **유비랩**(그래핀/그라파이트 방열 시트 deep-tech, OLED foldable+AI 반도체 TIM) SCREEN(병행 agent + orchestrator QC): elite founder(유봉현 삼성D 33년·NeoGraf 美VP)+삼성D/애플 샘플 진성 traction 이나 component multiple cap(직접경쟁사 신화인터텍 EV/Rev 0.2x)+pre-rev hockey-stick(92억@3y 2,500x)+Samsung 단일고객 → **"좋은 회사 ≠ 좋은 딜"**(Interstellar/Novachips 가족). ⭐ **양방향 QC** (D-index-37 보완): agent 가 base 를 as-converted(0.76x)로 계산해 E[CF] 2.9%/P(loss) **80%** 산출 → 본인 가정 RCPS 1x 우선권을 base(EV 143억≫20억)에 미적용한 **내부 불일치 artifact** 교정(우선권 floor 일관적용 base 1.0x) → **E[CF] 4.06% / P(loss) 43%**(peer 정합). QC=올바른 수치 착지(낮은 수치 아님) — fat-tail 도 instrument-floor artifact 도 교정. deal_id c98ba89e, stage=Screening. **16-deal 랭킹**: Sentry 43.5 > … > Eduon 15.0(screen) > **디벨로퍼그룹 14.76(buyout)** > 수성별 14.0 > Sendy 11.7 > Nanora 10.1 > Novachips 9.2 > **유비랩 4.06(최하, screen)** (+ Superman 20.8 별도). validate-seeds Δ0 둘 다 Pass. |
| 2026-05-30 | blueprint | `247b41f8` | **send_mail MCP 도구 — 범용 outbound email (D-bp-mcp-mail-1)** — `create_event` 형제. caller 본인 mailbox 발송(delegated `Mail.Send` 이미 SCOPES → self re-consent 불요) + admin send-as(`as_user_email`, app-only `Mail.Send`+consent 선행). 신규 route `POST /api/internal/mail` + Python tool `mail.py` + append-only `MailSendLog` audit(`sent`/`dry_run`/`failed`) + migration `20260529120000_add_mail_send_log`. params to/subject/body(html\|text)/cc/bcc/attachments(base64)/save_to_sent_items/dry_run. 에러 `send_as_forbidden`/`recipient_invalid`/`mail_send_not_consented`/`graph_error`. Graph `sendMail` 202 no-body → `message_id` null. ⭐ **동시 세션 격리 배포**: 내 커밋만 origin/main 위로 cherry-pick(247b41f8), 다른 세션의 unpushed `579a0fa1`(index-skill-sync) + 미커밋 WIP 는 `wip/index-skill-sync-579a0fa1` + stash 로 보존하고 배포 제외. |
| 2026-05-30 | index | `fc56004`+`7b4a50d` | **EGA·수성별·Nanora 3-deal batch 적재 (12~14th deal, D-index-37) — DB 14** — 사용자 "EGA·Nanora·수성별 모두 진행" + "Nanora full ic". 3 병행 background agent(deal당 1) + orchestrator QC. ⭐ **핵심 교훈 — full-IC 메모를 blind transcribe 하면 안 됨** (메모 rigor 가 deal 마다 극과 극): **EGA**(디파이넘버, NMN 뉴트리코스메틱) 메모는 surface-optimistic → agent 가 그대로 옮긴 E[CF] **127%**(매출 16억→550억 34x + EV/Rev 7× + 18x MoM@2y, wipeout 無)는 [D-index-26](/ops/decisions) fat-tail 환상(Iippo 74% 재현). status='passed'(미투자)라 [D-index-24](/ops/decisions)상 calibrated 가 canonical → **scrub**(ramp 16→300/120억 + EV/Rev 5×/3.5× K-beauty M&A anchor + **genuine wipeout 0.2x**: 창업자 이력 부재·매출 16억 미검증 red flag) → **calibrated E[CF] 23.3%** (E[MoM] 2.33x, P(loss) 40%); surface 는 헤더 audit trail 보존. 반면 **수성별**(국군복지단 DOOH 광고, 우선협상대상자) 메모는 이미 보수적 — Σp −23.8% → E[CF] **+14.0%**(sign-flip, Interstellar 패턴). 단 **deal 조건 전부 dataroom 부재**(10억/30억/25% 가정) + 팀공백 + CAPEX gap = info-void Conditional(stage Passed, instrument TBD). **Nanora**(US precision-wellness, TCM→구독 supplement+smart ring+AI, SAFE @ $9M post cap, pre-launch)는 사용자 지시로 **SCREEN→FULL IC 승격**: 18-section + multi-scenario + adversarial(proponent/premortem-critic 분리). E[CF] **10.05%**(E[MoM] 1.76x, P(loss) 50%) — Care/of($225M→Bayer→2024 폐업) category-graveyard + Pre-Seed→A 85% fail base-rate 로 회사 plan 하향, 판정 **Conditional**(결정변수 = post-launch 90-day cohort retention, T+9M revisit). **QC 결론**: agent batch 는 효율적이나 transcribe 산출은 반드시 orchestrator 가 fat-tail/wipeout/base-rate QC (EGA 127%를 적재 전 차단). **14-deal canonical E[CF] 랭킹**: Sentry 43.5 > Iippo 43.3 > Starnex 38.1 > Canopy 31.8 > Interstellar 30.5 > Hancom 23.9 > **EGA 23.3** > Infinity 16.5 > Eduon 15.0(screen) > **수성별 14.0** > Sendy 11.7 > **Nanora 10.1** > Novachips 9.2. 엔진 재확인: `validate-seeds seeds/*.yaml` 전 seed status Pass — **EGA E[CF] 23.30% · 수성별 14.02% · Nanora 10.05%** (docs 값 정합), baseline Δ0 regression 은 committed-baseline 3-deal(Iippo/Sentry/Canopy)에만 적용·나머지는 live-computed. |
| 2026-05-30 | index | `eduon seed` | **SCREENING 단계 정규화 (D-index-36) + 에듀온 11th deal (첫 Screening)** — 사용자 "screen 단계 추가 + 정규 프로세스화 + 적재". 1-pager inbound 에 19-agent `/ic` 바로 돌리는 GIGO 방지용 **Screening 게이트** 신설 (deal.stage 'Screening' enum 기존재 — migration 불요). 프로토콜: 외부 리서치 5종 + base-rate calibrated 재무모델 + engine IRR(E[CF]) + premortem 필수, dataroom 불요, "DD 자원 투입 가치" 판단(Go/No-Go 아님). **첫 사례 에듀온**(초등 영어 Writing 프랜차이즈 Seed 보통주 5억@Pre 20억): WebSearch 5 + franchise rollout 재무모델 → **E[CF] 15.0% / E[MoM] 2.0x / P(loss) 45%**. ⭐ 교훈: 회사 IRR 58% / Claude ad-hoc 26.5%(upside 10x) → **calibrated 15%** — 가맹 "3년 1,000"(3030영어 21년→1,400) + exit "3x rev/300억"(크레버스 0.59x·웅진 0.20x) 두 낙관이 base-rate·comp 에 깨짐 → upside 6x cap. **Screen=PASS(DD 미진행)** + 재screen 조건(RCPS+Pre 10-12억+가맹 traction). 산출물 `ic/{research,finance,memo}/` + index 적재(deal_id 2bb5d585). 향후 ic skill screen-mode = [B-index-ic-screen-mode](/ops/backlog). DB 11 deal. |
| 2026-05-30 | index | `7269286` | **Interstellar (인티그레이션) 적재 — 10th deal (D-index-35)** — 사용자 "추가 적재 프로젝트?" → 데이터룸 스캔, IC 분석 완료·미적재 = Interstellar 1건 (Render IC 미완 / Whale admin docs / 델리후레쉬 RFP / Pipeline 스크리닝 — 미대상). 인티그레이션(한의·치과 5-카테고리, 한의사 가입률 83%) Series D RCPS, AXE follow 검토 20억 **PASS** (알토스+네이버 lead 종결). D-index-24 PASS→calibrated canonical (status='passed'). **E[CF] IRR 30.5% / E[MoM] 3.23x / P(loss) 36.0%** (IC surface Σp 25.3%). ⭐ PASS 사유=거버넌스(R6 자기거래 IPO reject≥30%)+1.6% minority, **IRR 아님** — 9-deal 중 5위(Canopy 31.8 > Interstellar 30.5 > Hancom 23.9)인데도 PASS = "높은 IRR ≠ Go". 부수: seed.rs SERIES_OK 에 Series D/E 추가(누락 보완). validate-seeds 12 Pass / 23 test / DB 10 deal. (live MCP 는 DB 데이터 즉시 반영 — SERIES_OK 는 ingest-only 라 재배포 불요.) |
| 2026-05-29 (eve8) | index | `537c04e` (deploy) | **live index MCP blue/green 재배포 — D-index-25~34 코드 라이브** — 그간 commit/검증만 됐던 index 코드(option/passed status·intake 게이트·Σp 폐기·instrument·E[CF] canonical)가 live MCP 에 미반영(blue/green 컨테이너가 35h+ 구 바이너리 서빙 = 새 데이터에 구 코드 = option/passed 오집계)이던 것 배포. `axe ship index` = `manual_hint`(자동화 미구현, [B-index-azure-app](/ops/backlog) 후 frame_blue_green 승격 예정)라 **수동 compose 재배포**: `docker compose build` (SQLX_OFFLINE + `.sqlx` 최신) → green 재생성·healthy·new-binary 검증(sentry option 수락 + E[CF] 43.5% + 폐기코드 가드) → blue 재생성(alias 유지, Caddy `lb_try_duration 5s` 가 restart blip 흡수)·healthy → 검증. **DB 데이터는 이미 current** (option 1·passed 4 status + intake 필드 11/12, baseline 은 live 계산이라 financial_output 0행 = 정상) → 재적재 불요, 코드만 stale 이었음. 검증: 내부 healthz + 외부 `https://axe.axelabs.ai/index/healthz` 200, 4 컨테이너 healthy, 두 이미지 fresh(14:48). |
| 2026-05-29 (eve7) | index | `537c04e` | **canonical E[CF] 랭킹 확정 (D-index-34) + seed 주석·description E[CF] 재기재** — "정확도 심화" 마무리. **(1) D-index-34**: D-index-19/21/23/24 의 인라인 랭킹이 Σp/surface 기준이던 것 → engine `validate-seeds` 로 9 deal E[CF] 재산출, canonical 랭킹 확정: Sentry 43.5 ≈ Iippo 43.3 > Starnex 38.1 > Canopy 31.8 > Hancom 23.9 > Infinity 16.5 > **Sendy 11.7 > Novachips 9.2** — 구 Σp 대비 **tail flip** (Sendy↑Novachips) + Sentry-Iippo 거의 동률. Infinity executed 특례: v8 모델 불변(D-index-24) + 집계만 E[CF] 16.5%(D-index-32), IC headline 13.8% provenance. D-index-23/24 인라인에 "⚠ pre-E[CF] → D-index-34" 마커. **(2) seed 주석 정합** (index `537c04e`): starnex 36.4→38.1·hancom 22.4→23.9·sendy 6.5→11.7·infinity 13.8→16.5 주석 E[CF] 재기재 (value 불변). **(3) description 정정** (index `21e533d`, 병행 에이전트): 재척도 후 stale "3억 ×"(starnex→20억)·"× 10% = 222.5억"(sendy→2%/44.5억). **(4) #82 driver refactor 이미 완료 확인** (Iippo/Canopy 단일 revenue_growth). proceeds-bridge-retrofit(#81)은 날조위험+D-index-24 충돌로 보류. 11 seed validate Pass, E[CF] 전부 불변. |
| 2026-05-29 (eve6) | index | `74e1eb4` | **irr_instrument_adjusted 폐기 (D-index-33) + Σp output_code 가드** — 사용자 "수익성 정확도 심화" 선택 후 조사. **발견**: exit_matrix leaf recovery 가 instrument 구조를 이미 전역 반영 (RCPS preference floor: Sentry 0.05~0.14·Starnex 회생 1.10x / 보통주 후순위 wipeout: Hancom 0.30·Sendy 0.15·Novachips 0.20·Infinity 0.12) → IRR(E[CF])가 이미 instrument-aware. Novachips 1건의 `irr_instrument_adjusted`(-4.55% = E[CF] +9.2% −12pp)는 leaf wipeout(0.2x) **이중계상** (Σp·IRR 동형 함정). **조치**: (a) novachips baseline 제거 + 헤더 재프레이밍, (b) `seed.rs` DEPRECATED_OUTPUT_CODES load-time hard reject — `irr_instrument_adjusted`(D-index-33) + `irr_loss_included`/`irr_success_only`(Σp, D-index-32 완결), (c) overlay 잔존 Σp 정합 — infinity_recalibrated/superman_fresh 의 `irr_loss_included` → `irr_expected_cashflow` (engine E[CF]: Infinity -4.3% [구 Σp -8.3%] / Superman fresh 20.8% [구 Σp 10.5%]). [B-index-instrument-adjusted-irr](/ops/backlog) won't-do close, [B-index-docs-irr-ecf-restate](/ops/backlog) 신규(docs IRR 다수 pre-E[CF]). 11 seed validate + 23 test + 음성 테스트 Pass. |
| 2026-05-29 (eve5) | index | `3b2f543` | **투자성 intake 게이트 + option/passed status + Σp·IRR 폐기** ([D-index-29](/ops/decisions)/[30](/ops/decisions)/[31](/ops/decisions)/[31b](/ops/decisions)/[32](/ops/decisions)). 사용자 thread: "Series A Option 표현? / pass 도 IRR 관리하되 fund·project 제외 / 최소 intake (entry·valuation EV vs EqV·라운드·규모·Series) / 신주 구주 혼합 / p IRR 폐기 + 남은 것 모두". **D-index-29** `status='option'` (pro-rata 권리 미행사) — committed_total·baseline·fund·per-position IRR 전면 제외, IRR=null (Sentry 후속 5억 option 재분류, commit `9523638`). **D-index-30** `status='passed'` (검토 미투자) — what-if IRR 보존하되 fund/project baseline 제외 + all-passed fallback (`incl()` closure 공통화); 5/29 배치 정정 동반 (Canopy BW = Canopy 내 passed position 4.2% warrant, per-position BW IRR 28.0% &lt; RCPS 31.8% 정합 → 별도 deal CanopyBW 삭제; Sentry 1호·Iippo 1·2호·Starnex 20억/8월말·Hancom 5억/7월말·Sendy 10억 Pre-C·Novachips 6/10; proceeds 비례 재척도로 IRR 보존 Starnex 38.1%/Hancom 23.9%/Sendy 11.7%, commit `f650bec`). **D-index-31** 투자성 분석 최소 intake 게이트 5 필수 필드(series·round_size_krw·committed_krw·entry_date·pre_money_krw) + EV/EqV 영구 차단(entry=항상 EqV·exit=proceeds_basis) + `_TEMPLATE.yaml` (intake_enforced 2-tier: 신규 hard·기존 warn); 9건 backfill (commit `c4c12f4`+`9e86a07`). **D-index-31b** `share_type` 신주(primary→post 반영)/구주(secondary→post 불변) + 혼합 `round_primary_krw` + post≈pre+신주 ±2% invariant (Infinity pre 499.5→400억 정정으로 검증; Hancom·Novachips secondary, commit `98b88c2`). **D-index-32** Σp·IRR(rate 평균, 오집계) 폐기 → IRR(E[CF]) 단일 canonical: query_irr/html/xlsx 에서 `weighted_irr_*` 제거 + `irr.rs` 함수 `#[deprecated]` + 9 baseline·validate output_code 전환; E[MoM]은 linear 집계라 유지 (23 unit test + validate 3 PASS, commit `3b2f543`). 부수: superman_fresh entry_date 보강 → 실 seed `entry_basis=assumed` 0건, [B-index-entry-date-backfill](/ops/backlog) + [B-index-deprecate-sump-irr](/ops/backlog) ✅. |
| 2026-05-29 (eve4) | index | `85c8481` | **IRR 방법론 stack — 기대현금흐름 IRR canonical + per-fund 수익성 + fat-tail scrub + 미집행 timing** ([D-index-25](/ops/decisions)/[26](/ops/decisions)/[27](/ops/decisions)/[28](/ops/decisions)). 사용자 thread: "확률 IRR 폐기 보류 + 추가투자 별도 + 1·2·3호 펀드 수익성 + Iippo 2호 분석 + cashflow IRR 정확한 표현 + 2호 IRR 동일 의문". **D-index-25** 기대현금흐름 IRR = IRR(E[CF]) (확률을 CF 에 먼저 적용 → IRR) 를 canonical 로, Σp·IRR(rate 평균, 오집계)은 병기(폐기 보류) — 반드시 E[MoM]+P(loss MoM&lt;1) 동반 (`irr.rs::expected_cashflow_irr`, commit `2d2066f`). **D-index-27** per-position(`position_ecf_irr`, ratio-split + deal_paid_offset) + per-fund(`fund_performance`, axe_ia_001/002/003 횡단 pool) IRR; Iippo 2호 = 가공 follow-on 제거 → 실제 **AXE Private Fund II 개인투자조합** Pre-A 공동투자 1억 RCPS, 별도 IC Memo (commit `7e313b5`). **D-index-26** fat-tail leg comp-scrub 를 **canonical 에 직접 적용**(이전 overlay-only 라 74% 환상 잔존): Iippo mgmt 1~2.5조→1,000~2,500억(강남언니 8x ceiling) E[CF] 74%→43.3%, Sentry upside 47x→14.7x(마스턴 AUM), Canopy 12x→6x EBITDA(Bird) — IC 원본 주석 보존 (commit `8c5e60e`). **D-index-28** 2호 IRR 이 1호와 동일했던 건 paid_date=null→offset 0 silent fallback (계산식은 정확; 격리 테스트 +1개월 44.24%/+4개월 47.40%, exit=calendar 고정이라 늦은 entry=짧은 hold=높은 IRR); 수정 = 2호 entry 2026-06-15 가안(planned)·paid null 유지 + `entry_basis {paid/planned/assumed}` never-silent flag + `fund_ecf_irr` 의 `.max(0.0)` 클램프 버그(deal_ref&lt;fund_epoch 음수 offset 정상) 제거 → 단일 position 펀드 IRR 가 standalone 과 일치 (commit `85c8481`). 부수: flag 가 Hancom·Novachips·Sendy·Starnex·Superman entry date 누락(`assumed`) 노출 → [B-index-entry-date-backfill](/ops/backlog) 진행. validate-seeds 9-deal Pass, DB 9 deal 정합. |
| 2026-05-29 (PM12) | cortex | (interactions 참석자 표시 + 대시보드 폴리시) | **interactions 참석자 표시 + 대시보드 포맷 폴리시** (운영자 피드백 연속). **(1) 참석자**: /cortex/interactions 에 참석자 정보가 없다는 지적 — 데이터는 `attended` relationship 으로 이미 연결돼 있었으나 화면 미표시(display gap). list 2번째 컬럼을 "참석자 / 일시", detail 에 "참석자 (N)" 섹션 추가 (person 링크). **방향 불일치 흡수**: log_interaction 은 from=interaction→to=person, xlsx_hpe 백필은 from=person→to=interaction 으로 만들어 양방향 모두 resolve (`fetch_attended_participants`, `$iid IN (from,to)` 후 반대쪽 endpoint=person). 36 interaction 전부 참석자 연결 확인. 데이터 정규화 migration 은 미실시 (display 흡수, [known-gaps](/ops/known-gaps) 기록). **(2) 대시보드**: stat 카드 값에 단위(명/건) + 천단위 콤마(fmt_n); "전체 인원"→"전체" + total_orgs("N개 회사") sub 추가. **(3) 404**: 운영자가 본 /cortex/interactions 404 는 직전 blue/green --force-recreate 재시작 윈도우(수초)의 일시적 현상 — 라우트 정상, 재현 안 됨. blue/green --no-cache rebuild (binary 4465506b). |
| 2026-05-29 (PM11) | cortex | (D-cortex-customer + dashboard 사람중심 재편) | **고객 태깅(다대다) + home 대시보드 사람중심 2-row 재편** ([D-cortex-customer](/ops/decisions), [D-cortex-dashboard-redesign](/ops/decisions)). **(1) 고객**: 운영자 "1명이 여러 건(프로젝트 a/b/c)으로 고객 가능, 우선 수동 태깅". 고객 = subject 에 붙은 ≥1 customer_case attribute (다대다). tag_customer(subject_id, case, note?) — (subject,case) 멱등, person 은 network 자동 승급; untag_customer — 해당 case archive (tier 강등 X). MCP 23→25 tools. **(2) 대시보드 재편**: 운영자 "relationship 은 사람에게 안 중요". kind 카드 그리드 제거 → 사람중심 2-row: 구글연동 → Push대기 → 전사 row → 안심주석 → 나의 row. 각 row = 전체 인원 · 네트워크 N명/N개 회사 · 고객 N명/N개 회사 · 1개월 활동 N건/총 N건. NetworkStats 한 구조+쿼리를 per-user(RLS)·전사(superuser) 재사용. 안심 주석 "네트워크 아닌 인원은 조직 내 비공유". 검증 나의 row: 총 3600/네트워크 624/회사 413/고객 0/활동 1·1. blue/green --no-cache rebuild. |
| 2026-05-29 (PM10) | cortex | (D-cortex-org-stats + import-xlsx=network 정정) | **전사(cross-user) 집계 대시보드 + import-xlsx tier=network 정정** ([D-cortex-org-stats](/ops/decisions), [D-cortex-person-tier](/ops/decisions)). **(1) 전사 집계**: 운영자 "대시보드에 조직 전체 통계도". 범위 = 전사 cross-user + 전 직원 visible + 합계만(직원 익명). `fetch_org_wide_counts` 가 set_current_user 미호출 → cortex superuser 연결(bypassrls)로 모든 owner artifact 를 kind별 COUNT + distinct owner 수만 집계 (개별 레코드·owner 분해 X — D-cortex-2 격리 유지, 익명 숫자만 공유). home "조직 전체" 섹션 + 익명 callout + non-link org_metric. 집계 person 3600/relationship 3071/org 1500/deal 17/interaction 1/users 1. **(2) import-xlsx=network 정정**: 운영자 지적 — Network_CRM.xlsx 는 큐레이션 인맥이라 import 가 만지는 person 은 pool 아니라 network. create_person_from_xlsx_row payload tier='network', matched(Google pool) person 도 system:xlsx-migration 이 promote (멱등). ImportStats.tier_promoted. **(3) 등록자 추적 확인**: created_by(artifact) + actor(artifact_event append-only) 가 shared 포함 누가 등록·수정했는지 전부 기록 (현재 per-user 라 actor 는 `본인 또는 system:*` 뿐; cross-employee attribution 은 D-cortex-9 Phase 2). blue/green --no-cache rebuild. |
| 2026-05-29 (PM9) | cortex | (D-cortex-person-tier — pool/network 운영 자동화) | **person tier (pool\|network) 도입 — 자동 sync 연락처 vs 운영자 인맥 분리 + auto-promote** ([D-cortex-person-tier](/ops/decisions)). 운영자 관찰: Google Contacts 3,601 중 대부분이 raw 연락처라 "내 인맥" 뷰 오염. backfill = network 625 / pool 2,976. **기본값**: Google sync 신규 person = pool (sync.rs INSERT; 기존 tier 는 enrichment 키라 overlay 가 안 건드림), register_person = network (운영자 명시 등록 = 인맥; tier='pool' 명시 허용). **auto-promote (pool→network, 멱등)**: classify_person / register_relationship(person endpoint) / log_interaction(participant) 어느 액션이든 대상 person 자동 승급 (tier_source='auto_promoted_from_&lt;action&gt;', audit actor='system:auto-promote'). 한 helper 가 3 handler 의 tx 안에서 호출. **network→pool 강등 없음** — 유일 역방향 = 명시 demote_to_pool(person_id, reason) MCP tool. **노출**: list_persons + web /cortex/people 기본 tier='network', ?tier=pool\|all 확장; home People 카드 = 내 인맥 값 + 풀/전체 sublabel. **D-cortex-3 정합**: tier=enrichment 키 → sync 보존. 회귀: overlay_never_touches_tier_enrichment_key (sync.rs 6 tests). MCP 22→23 tools. blue/green --no-cache rebuild (PM8 leader election + Dockerfile cargo test gate 동반). |
| 2026-05-29 (PM8) | cortex | (D-cortex-leader-election + Dockerfile ship hook) | **D-cortex-3 PM7 의 본질 해결 — leader election (pg_try_advisory_xact_lock) 도입 + Dockerfile 안 cargo test 자동 회귀 차단** ([D-cortex-leader-election](/ops/decisions)). PM7 의 fix 는 "둘 다 --no-cache 재빌드 + binary sha 일치 검증" 운영 invariant 였는데 본질 = blue/green 둘 다 run_loop 를 돈다는 것 자체. binary 동일성은 race 가 일어나도 같은 결정을 내리는 우회 — race 자체 차단이 본질. 5축 평가 (본질 5 · 결과 5 · 혁신 5 · 퀄리티 4 · 안전 4 = 23) 로 가장 강한 옵션 선택. **구현**: `src/google/sync.rs::run_cycle` 시작 시 transaction 열고 `pg_try_advisory_xact_lock(2026052907)` 시도. 성공 시 leader → 본문 실행 → commit (lock auto-release). 실패 시 INFO 로그 후 skip. **Transaction-scoped lock** = COMMIT/ROLLBACK/disconnect 시 auto-release → leader panic·crash 해도 무인 페일오버. **부수효과**: Google API quota 절반 (2× → 1×), DB 부하 절반. **Ship hook (직교 추가, 점수 18)**: Dockerfile RUN 안 `cargo build --release && cargo test --release --bin cortex google::sync::tests` 한 줄 — test 실패 시 image 생성 자체 불가 → 옛 destructive 코드가 production 으로 흘러갈 수 없음. **검증**: (1) psql 두 세션 동시 `pg_try_advisory_xact_lock(2026052907)` → 첫 세션 t, 두번째 f. 첫 세션 commit 후 두번째 t (auto-release). (2) Docker --no-cache 양쪽 rebuild + recreate → 같은 binary sha `0658a1c7...`. cargo test 5/5 통과 (자동 회귀 차단). (3) 첫 sync cycle 후 blue/green 중 한 쪽만 "owner sync ok" + 다른 쪽 "leader lock held, skipping" 관찰 예정. **CLAUDE.md 운영 함정 갱신**: blue/green 동일 binary 가 강제→권장 으로 격하 (leader election 이 본질 차단). 새 함정 = skip 로그가 한 쪽에서 항상 안 보이면 그 쪽이 leader 가 못 됨. |
| 2026-05-29 (PM7) | cortex | (D-cortex-3 PM7 — blue/green 동일 binary invariant + 회귀 테스트) | **D-cortex-3 enrichment wipe 재발 → blue/green Docker layer cache race 발견 + fix + 회귀 테스트 5개 추가** ([D-cortex-3 갱신](/ops/decisions)). PM4·PM6 의 overlay-preserving 코드가 이미 ship 됐는데 동일 증상 재발 — 김승우 (코오롱·한섬·스위티) 3명의 memo/cohort/former_org/former_title 이 또 system:google-sync 의 edit event 로 wipe. **진짜 root cause**: PM6 의 `docker compose build --no-cache` 가 `cortex-mcp-blue` 한 서비스에만 적용되고 `cortex-mcp-green` 은 stale 캐시 이미지 그대로 유지. blue/green 둘 다 run_loop 를 동시에 돌기 때문 (leader election 부재) sync 한 번 돌 때마다 race — 새 코드가 enrichment 보존해도 옛 코드가 같은 초에 destructive UPDATE 로 덮음. 운영자가 본 .236 preserve 와 .337 wipe 가 같은 초에 짝지어 일어난 흔적 = 두 컨테이너의 race 결과. **즉시 안전**: `UPDATE google_oauth_token SET status='paused'` → sync 정지. **fix**: 두 서비스 모두 명시적 `docker compose build --no-cache cortex-mcp-{blue,green}` + `up -d --force-recreate cortex-mcp-{blue,green}` → 안의 `/usr/local/bin/cortex` sha256 일치 검증 (50faa90d...). **복구**: `cortex restore-from-audit --owner soohun.kang@axellc.com --scan --apply` → 183 person enrichment 복원. sync 재개 (status='active') 후 강제 sync_google_now 3,385 → 3 victim 그대로 + missing_memo/cohort/former_org/former_title/HPE 전 owner 합쳐 0. **회귀 차단**: `src/google/sync.rs` 에 `#[cfg(test)] mod tests` 5개 unit test — (1) overlay 가 enrichment 보존 + (2) Google canonical 전부 null 일 때도 enrichment 보존 (edge case) + (3) wholesale replace 차단 + (4) 멱등 + (5) is_meaningful 가드. `cargo test --bin cortex google::sync::tests` 5/5 통과. **운영 invariant 명문화** (CLAUDE.md 운영 함정 섹션): sync.rs 같은 critical path 수정 시 blue·green 둘 다 명시적 `--no-cache` + `docker exec <blue/green> sha256sum /usr/local/bin/cortex` 일치 검증 필수. image-level hash 는 빌드 timestamp 비결정성으로 달라도 OK, binary 자체만 같으면 안전. |
| 2026-05-29 (PM6) | cortex | (Google contact displayName backfill 134/134) | **`cortex backfill-google-names` CLI 일회성 실행 — 134/134 success** ([D-cortex-google-names-backfill](/ops/decisions) + [D-cortex-3 갱신](/ops/decisions)). 옛 register_person 으로 push 된 Google contact 134건의 빈 displayName 정정 (unstructured_name fix 이전 createContact 호출분). per-person flow 는 People API updateContact 호출 + citation.ref 갱신 + dispatch event. rate 1 req/sec, idempotency gate (citation.ref 의 unstructured_name_backfill 마킹 v1). dry-run candidate=134 (Bucket A=2 김승우/정성화 + Bucket B=132). canary 5/5 → full 129/129 (총 134, 약 2.5분). 사후 candidate=0, dispatch event 134, 김승우/정성화 citation 마킹 v1. **선행** restore-from-audit 가 Cortex 측 display_name 을 채워둠. **함정 발견** — Docker layer cache 로 코드 fix 후에도 old binary 가 동작 (docker compose build 만 했을 때 캐시 재사용). docker compose build --no-cache 강제 빌드 + 새 binary 동작 직접 검증 (memo/former_org 보존) 후 134 backfill 실행. **D-cortex-3 본문 갱신**: 단방향 createContact 원칙 안에서 식별 키 정정 한정의 updateContact 도 허용 (enrichment 키는 절대 push 안 함). |
| 2026-05-29 (PM5) | cortex | (MCP tools 17 → 22 + register_deal 재설계) | **Cortex MCP write tools 확장 — 17 → 22 tools, register_deal 재설계 + 5 read tools** ([D-cortex-mcp-write-tools](/ops/decisions)). 운영자 follow-up — claude.ai 안에서 일상 운영 (deal stage 전환, org 조회, person ↔ deal 연결 등) 가능하게. **재설계**: `register_deal` = `title` → `name` 표기 통일 (16/19 기존 deal 이 이미 'name' 쓰는 backfill 패턴 + 3개 'title' archived 됨), stage 자유 string (권장 enum origination/screening/dd/ic/active/closed/killed description 만 — 실제 분포 active/closed/exploring/review 호환), **visibility default 'private'** (deals 민감), `contact_person_ids[]` → 각각 `deal_contact` relationship 자동 (idempotent, deal visibility 상속), `target_org_id` 있으면 `targets` relationship 자동, `source_attribute_id` (HPE → deal 추출 provenance). `register_organization` = case-insensitive idempotency (`lower(payload->>'name')` 매칭 — 'Aruda'/'ARUDA'/'aruda' 모두 동일 id) + `aliases` 명시 필드. `archive_artifact` = `reason` 필드 (payload.archived_reason) + `restore=true` alias (archive=false 와 동등). **신규 5 read tools**: `list_organizations` (name+aliases ILIKE search), `get_organization`, `list_deals` (stage/target_org_id 필터), `get_deal` (recent 20 events 포함), `list_relationships` (person_id 가 from 또는 to + edge_kind 필터). 모두 archived 자동 제외 (get_* 단건만 archived 도 노출). **검증** (7/7 smoke): tools/list=22 / ARUDA case-insensitive 3 variant 동일 id / register_deal default private / contact_person_ids+target_org_id → 자동 2 relationship (deal_contact + targets) / archive_artifact reason+restore alias / register_relationship 멱등 / list_* read OK / archived org list 에서 안 보이고 get 으로는 보임. blue/green Docker recreate. |
| 2026-05-29 (PM4b) | cortex | (D-cortex-3 enrichment 보존 fix + 데이터 복구) | **D-cortex-3 sync overwrite 버그 발견 + 즉시 패치 + 데이터 복구** ([D-cortex-3](/ops/decisions)). 운영자 ("방금 2명 신규 저장했는데 잘 적재된건가") 가 확인 요청 → audit log 점검 결과 김승우 (코오롱인더스트리 전무) + 정성화 (한섬비즈온 대표) 두 person 의 display_name + memo + cohort + former_org/title 이 **모두 sync 백그라운드에 의해 destroy** 됨. **Root cause**: `src/google/sync.rs::upsert_from_person` 의 `UPDATE artifact SET payload = $1` (Google payload 전체 덮기). register_person → Google createContact → 4분 후 sync 실행 → Google 의 빈 응답 (createContact 가 displayName 못 저장한 buggy 상태) 으로 Cortex enrichment 까지 통째로 날아감. **즉시 패치 3종**: (1) `sync.rs` 에 `GOOGLE_CANONICAL_KEYS` 화이트리스트 (display_name·given/family_name·org·title·department·emails·phones·memberships·biographies·userDefined) + `overlay_google_into_cortex(existing, google)` 가 meaningful (non-null + non-empty) 값만 selective overlay → enrichment 키는 자동 보존. (2) `google/people.rs::NameCreate` 에 `unstructured_name` 필드 추가 — People API 의 `Name.displayName` 은 server-computed 이므로 클라이언트가 보내도 무시, `unstructuredName` 으로 보내야 Google 측 displayName 정상 생성. (3) `mcp.rs::try_google_create_contact` + `web/views.rs::push_one` 의 NameCreate 인스턴스화에 unstructured_name=display_name 추가. **데이터 복구**: append-only audit log 보존 덕분에 두 person 의 propose (operator) + operator edit 의 enrichment 합성 → SQL UPDATE artifact + INSERT artifact_event op='restore' (actor='system:enrichment-recovery-D-cortex-3'). 정성화: display_name·org·title·memo·cohort 복원. 김승우: + former_org/title 복원. **검증**: 강제 sync_google_now (3,385 contacts) 후 두 person enrichment 그대로 + sync 가 만든 새 edit 의 payload_after 가 `memberships=["myContacts"]` 만 추가 (Google meaningful 값) — display_name·memo·cohort 보존 확인. blue+green Docker recreate. **D-cortex-3 본문 갱신** — Sync 보존 계약 명문화. **회피 가능했던 운영 함정** (참고): 이번 버그는 register_person → createContact name bug + sync 의 destructive overwrite 두 결함이 결합해서 만들어짐. createContact 만 고쳐도 destructive overwrite 는 잠재 위협으로 남았을 것. overlay 화이트리스트 도입이 더 본질적인 안전망. |
| 2026-05-29 (PM4) | docs | (ssh-access trap fix) | **ssh-access runbook 함정 fix — `install` 은 replace, append 는 `tee -a`** ([/onboard/ssh-access](/onboard/ssh-access)). 운영자 ai 가 taehun.kang SSH key 등록 (직원 onboarding) 중 발견 — Step 3 (a) `sudo /usr/bin/install -m 600 -o axe -g staff <tmp> /Users/axe/.ssh/authorized_keys` 주석은 "append" 인데 명령은 destination replace (cp 와 동일). 운영자가 무심코 따라하면 공용 `axe` 계정의 기존 직원 키 (이번 경우 ring-backup + soohun.kang) 전부 삭제 → 다른 직원 SSH 잠김. **fix**: (a) 를 `echo "<pubkey>" \| sudo /usr/bin/tee -a /Users/axe/.ssh/authorized_keys >/dev/null` 로 교체 (NOPASSWD whitelist `/usr/bin/tee /Users/*` 활용 확인). ⚠️ 코멘트 + (c) personal home 도 "첫 등록 시만 install OK, 두 번째부터 tee -a" 명시. 본 건 (taehun.kang) 은 Edit in-place append 로 진행 → 기존 2 키 보존. SACL `com.apple.access_ssh` 는 이미 등록되어 있어서 dseditgroup 불요. |
| 2026-05-29 (PM3) | cortex | (MCP write tools + archive) | **Cortex MCP write tool 표면 완성 — 16 tools** ([D-cortex-mcp-write-tools](/ops/decisions)). 운영자 "본질 퀄리티 결과 안전 혁신" 으로 진행 위임. 5축 평가 후 본질 gap (claude.ai 가 organization/deal/relationship 등록할 채널 없음) + lifecycle gap (DELETE 가 append-only audit trigger 로 차단) 동시 해결. **신규 4 tool** = `register_organization` ((owner, name) idempotent, visibility default shared) · `register_deal` (NOT idempotent — 같은 title 의 round 가능, target_org_id 가 있으면 owner-scope + kind='organization' 검증) · `register_relationship` ((owner, edge_kind, from, to) idempotent, from/to 양쪽 owner-scope 존재 검증, self-loop 차단) · `archive_artifact` (toggle archive=true|false → payload.archived 갱신 + op='archive'/'restore' event). **혁신** — 별도 archive_person/archive_deal 안 만들고 한 일반 도구 + restore. DELETE 차단 우회의 핵심: payload.archived flag 로 lifecycle 표현하면 audit 보존 + list/count/push 자동 제외. **List 쿼리 일괄 갱신** — web(fetch_kind_counts/recent_events/artifacts_by_kind/pending_push) + MCP(list_persons/search_person via push_person_filters) + backfill(distinct_orgs/person_rows) 모두 `NOT COALESCE((payload->>'archived')::boolean, false)` default 필터. ID 직접 접근 (get_person 등) 은 archived 도 반환. **검증** (11/11): register_organization 신규 + idempotent / register_relationship 신규 + idempotent / register_deal 신규 + 동일 title 새 id / target_org_id=person uuid → kind mismatch error / archive 4 artifact / 재 archive no_op / restore / 이전 세션 SMOKE_TEST_ORG_DELETE_ME_BACKFILL MCP archive 로 정리. UI: /cortex/orgs 가 archived 항목 안 보임, home dashboard 카운트 archived 제외 정합. blue/green Docker recreate 후 edge https://axe.axelabs.ai/cortex/home 200. **남은 우선순위** (다음 세션): backfill-introductions CLI (xlsx '소개' attribute → introducer relationship) · HPE attribute → deal 자동 추출 · 운영자 #1 full backfill-orgs (1,536 org YAML 편집, 수동) · edit-before-push / partial-failure (Google push 마무리 UX). |
| 2026-05-29 (eve3) | index | `c0dcd9a` | **Prj_Infinity(INEX) 축적 — 3-step surface→재수행→비교 (13.8% → −8.3% sign-flip)** ([D-index-23](/ops/decisions)). 사용자 "기존 적재 테스트 → 신규 IC 재수행 → 두개 비교". [D-index-19](/ops/decisions)/[21](/ops/decisions) 을 명시적 3-step 으로 정식화. **대상**: INEX 가상자산 거래소/VASP (보통주 0.5억 bridge, Closed). **Step1 surface**: v8 FINAL(irr_locked) 적재 → index 13.8%/MoM 1.70x 정확 재현. **Step2 재수행**: 외부 research — 실명계좌 base-rate near-zero(2021 특금법 후 원화마켓 신규 0건, P&lt;10%) / 코빗 ceiling 1,000-1,400억(Mirae MOU) / Gopax·Binance license-shell M&A 선례 / 보통주 distress recovery 0~20%. → 모달 exit 를 won-market rerating 아닌 SI shell M&A breakeven 으로 reframe + 보통주 wipeout leg(18% @ 0.12x) 추가. **Step3 비교**: calibrated −8.3%/MoM 0.82x. **~22pp gap + sign-flip**. **핵심**: 성숙·정직한 v8(hurdle 미달 공개·3 reviewer·irr_locked)도 핵심 base-rate(실명계좌)를 mgmt optimism 에 anchor + 보통주 wipeout 누락 → 결론 역전. proceeds 메커니즘은 v8 이 이미 정확(ev_bridge·net debt 0·exit-diluted) → 재계산 0, gap 순수 analytical. **canonical = IC-approved 13.8%** (executed/Closed deal → decision-time 기록 보존; −8.3% 는 retrospective overlay = `infinity_recalibrated.yaml`, [D-index-24](/ops/decisions)). 8-deal canonical 랭킹: Hancom 23.2 > **Infinity 13.8** > Novachips 7.8 > Sendy 6.5. validate-model 0 errors. IC memo v9 = OneDrive. |
| 2026-05-29 (PM2) | cortex | (axe-ui + backfill-orgs) | **Cortex 웹 UI 가 docs.axelabs.ai 와 같은 토큰을 입음 + /cortex/orgs 가 비어있던 문제 풀림** ([D-cortex-design-axe-ui](/ops/decisions) + [D-cortex-backfill-orgs](/ops/decisions)). **Design** — D-cortex-6.1 의 inline CSS (~200 line) 폐기 → `scripts/sync-axe-ui.sh` 가 axelabs SSOT (`/Users/axe/axelabs/src/lib/`) 에서 tokens 4종 + styles 6종 (reset/components base/form/data-display/dashboard/feedback) + Sarasa Fixed K woff2 (533 KB) 를 `static/axe-ui/bundle.css` (83 KB) 로 묶음. components.css 의 `@import` 중 cortex 가 안 쓰는 9 그룹은 strip. fonts.css 의 `/fonts/` 절대경로는 `/cortex/static/fonts/` 로 rewrite. `include_str!`/`include_bytes!` 로 binary stamp + Dockerfile 에 `COPY static ./static` 추가. 라우트 = `GET /cortex/static/axe-ui.css` + `/fonts/SarasaFixedK-Regular.woff2` (public, Cache-Control 1일/30일). HTML 은 `<html data-theme="light">` + `<link rel="stylesheet" href="/cortex/static/axe-ui.css">`. 클래스 매핑 = `.topbar`→`.axe-topnav`, `.brand`→`.axe-logo`, `.card`→`.axe-card`, `.btn`→`.axe-btn--{primary,secondary,ghost}`, `.metric`→`.axe-metric-card`, `<table>`→`.axe-data-table > __scroll > __table > __th/__td`, `.empty`→`.axe-empty-state`, callout box→`.axe-callout--{info,danger}`. cortex-only 개념 (visibility tag, payload pre, kv, flash, filter bar) 은 `.cortex-` prefix 로 분리 inline. **Backfill** — `cortex backfill-orgs` CLI 2단계: Phase 1 (`--owner <email>`) → pg_trgm 활성화 + distinct payload.org 추출 (1,536개) + similarity ≥ 0.6 클러스터 (1,446개) 제안 YAML stdout. 운영자가 파일 저장 → canonical_name/aliases/skip 편집. Phase 2 (`--mapping <yaml>`) dry-run, Phase 3 (`--apply`) 실제 INSERT. Idempotent — (owner, name) 으로 org 중복, (from, to, edge_kind) 로 relationship 중복 안 만듦. artifact `visibility='shared'`, `payload.backfill_source='backfill_orgs_v1'`. D-cortex-6.1 read-only 원칙 유지 — CLI 도구만, 웹 form X. **검증**: axe-ui.css 200 + 엣지 https://axe.axelabs.ai/cortex/static/axe-ui.css 200 · /cortex/home + /cortex/google/pending 모두 axe-* 클래스 + Sarasa 폰트로 렌더 · backfill Phase 1 YAML 1,536 distinct → 1,446 clusters 정상 출력 · 소규모 2-org mapping 으로 dry-run + apply (orgs created=2, rels created=2) + 재apply (existing=2, idempotent) 모두 통과 · /cortex/orgs 가 빈 axe-empty-state 에서 데이터 있는 axe-data-table 로 전환됨 확인 · /cortex/relationships 도 employed_by 2개 표시. **잔여**: 1,536개 org 의 full backfill 은 운영자가 YAML 편집 후 실행 (이번엔 smoke 만), 메모리에 도큐먼트. **남은 우선순위**: #2 backfill-introductions (xlsx '소개' 컬럼 → introducer relationship) · #3 register_organization/_deal/_relationship MCP tool · #4 HPE → deal 자동 추출. |
| 2026-05-29 (eve2) | index | `ca714b7` | **proceeds 산정 강화 — EV→EqV(net debt) bridge + exit-dilution 강제** ([D-index-22](/ops/decisions)). 사용자 audit "모두 EV = EqV + Net Debt + 투자 후 dilution 고려됐나 체크". **발견**: 7-deal proceeds 비일관 — net-debt bridge 는 Canopy 만 명시(EV 797−netdebt 300=EqV 498), Sendy(v2)·Iippo 는 stake×EV 직접(EqV 누락), pre-IPO 3+Sentry 는 equity multiple(N/A); dilution 은 pre-IPO 3+Sendy exit-date 희석 명시 vs Iippo·Sentry entry F/D flat. **결정** ([D-index-20](/ops/decisions) IRR determinism 을 proceeds 로 확장): `proceeds_basis` enum (ev_bridge|equity_value|mom|legacy_ev) + ev_bridge non-writedown leaf 는 `stake×(EV−net debt)` 가 axe_proceeds 와 ±2% 일치해야 — seed load **hard reject** + validate Check 7 Error 2중 강제. negative test 거부 확인 (10%×2,225억=222.5억 ≠ 날조 300억). migration 0005 (proceeds_basis + exit_ev/net_debt/stake 컬럼). **Sendy 정정 v3**: ev_bridge, net debt=0 (asset-light + 자금니즈 equity 충족 + 차입 증거 0 → 보수적, **없는 부채 날조 안 함**), stake 12.5%→10%. **proceeds·IRR 불변 6.47%** 이나 EV≠EqV 누락 class 영구 차단 — "정정=구조적, 숫자 불변" 이 정직한 결과. **7-deal**: Sendy ev_bridge PASS / Sentry equity_value / 3 pre-IPO mom / Iippo·Canopy legacy_ev WARN — 0 errors. 잔여: [B-index-proceeds-bridge-retrofit](/ops/backlog) (Iippo·Canopy per-leaf bridge) + Iippo·Sentry entry-F/D-flat dilution ([known-gaps](/ops/known-gaps)). |
| 2026-05-29 (eve) | index | `b77a236` | **센디(Sendy) IC v2 재작성 — 현 practice 재calibration (92% → 6.5%)** ([D-index-21](/ops/decisions)). 사용자 redirect "그냥 적재 말고 ic memo 를 현 practice 수준으로 새로 써라 (당시 방법론 열위)". [D-index-19](/ops/decisions) (surface→calibrated) 의 종착 = **memo 방법론 자체 재작성**. **3-tier IRR**: (a) v1 md 31%/22.8% (fabricated override), (b) v1 Excel 92.4% (math-correct, 낙관 input), (c) **v2 현 practice 6.5% ⭐ canonical**. **v1 5결함 교정**: IRR override(D-index-20 차단) / **wipeout leg 부재** (Downside 가 +31.6% gain → 손실 시나리오 자체 없음) → genuine 18% wipeout (부릉 1/6 recovery 0.15x) / **sendyX 66x 미검증** (beta 5곳 월375만→2026E 25억) → base-rate haircut(-93%) / **Exit 5x flat → segment-weighted** (freight 1.0~1.5x + TMS SaaS 4~5x, WiseTech-E2open 3.5x anchor) / instrument 분석 부재. **외부 anchor**: Convoy $3.8B→0 + 부릉 ₩5,500억→800억(1/6) → wipeout 15~25%, 한국 Series C→IPO 예외(TMAP 교훈). **결과**: 4-scenario bull(0.12,4.45x)/base(0.40,1.83x)/bear(0.30,0.72x)/wipeout(0.18,0.15x) → E[IRR] 6.5% / E[MoM] 1.51x / Sharpe-like -0.06. PASS 재확인 (v1 구조+타이밍 + fundamentals 30% hurdle -23.5pp 미달). **7-deal 랭킹**: Sentry 40.3 > Iippo 36.5 > Starnex 36.4 > Canopy 26.4 > Hancom 23.2 > Novachips 7.8 > **Sendy 6.5 (최하위로 정정)** — 92% 매력 대부분이 2 낙관 input + 누락 risk leg 산물이었음. 산출물: OneDrive `ic/memo/v2_axe_current_practice_260529.md` (5-tenet·premortem·v1→v2 교정표) + seed v2 (version:2). validate-model 7/7 PASS. |
| 2026-05-29 (PM) | index | `9263179` | **센디(Sendy) 축적 — IRR override 오류 flagship + 첫 declined deal** ([D-index-20](/ops/decisions)). 사용자 "sendy 건도 비슷하게". 출처 = `1_Project/Pipeline/Sendy/`. **index 존재 이유의 결정적 증거**: `exit_matrix/v1.yaml` line 76 `irr_approx_pct: 95 # ... ≈ corrected: 35%` — 계산값 95.7% 를 근거없이 "35%" 로 손수 override (md 전반 Base 35/Downside -8/Expected 31/Devils 22.8 오류 chain; Downside -8% 는 수취 114억 > 투자 50억 → 구조적 불가). index 는 IRR 을 exit proceeds 에서 deterministic 계산 → override 물리적 불가. EV-derived seed → index 자동 교정: Base 95.7% / Downside 31.6% / Upside 146.6% / weighted 92.43% (Excel 실제값 일치). **부수 — deal.stage 'Passed' 추가** (migration 0004): GO/Closed 만이 아닌 PASS 결정 institutional memory 보존. 센디 PASS (2026-02-15) = 구조(10억서 CB 외 equity 제한)+타이밍, quality 아님. **7-deal portfolio**: Closed 3 / IC 3 / Passed 1 (full lifecycle). honesty: 92% 는 math-correct 이나 screening-grade model (sendyX 66x 미검증), PASS 는 IRR 무관 결정. validate-model 7/7 PASS. |
| 2026-05-29 (PM) | cortex | (batch push UI) | **Cortex Google push 큐 — batch + skip + visibility 격리** ([D-cortex-google-push-batch](/ops/decisions)). 운영자 "216 명 하나씩 클릭 비현실적" → batch UI 추가. **신규 모듈** `src/web/google_push.rs` (~400 LoC) — `JobRegistry` (`Arc<Mutex<{jobs, owner_running}>>`) in-memory, owner 동시 1 job 락, 1 req/sec 페이스 (Google quota 90/min/user 안전), MAX_BATCH_SIZE=500, 프로세스 재시작 시 손실 허용 (push idempotent — citation 중복 거절). **3 작업 일괄 ship**: (#3, **D-cortex-9 안전 fix**) `fetch_pending_push` SQL 에 `AND a.visibility='shared'` 추가 — private person 절대 push 후보 안 됨. count 216→215 검증. (#2, skip permanently) `kind='attribute', payload.key='do_not_sync_google'` 별도 artifact 마킹 (classify_person 패턴 일관, payload mutation 회피). `POST /cortex/a/:id/skip-google-push` 라우트 + 행별 `<button form="skipform-:id">` (HTML5 외부-form 참조로 nested form 금지 회피). 신규/idempotent 모두 OK, count 215→214 검증. (#1, batch push) `POST /cortex/google/push/start` (body: Bytes 직접 form-urlencoded 파싱 — axum default Form 이 same-key Vec 안 됨) · `GET /cortex/google/push/status/:job_id` HTML (progress bar + 결과 table + `setInterval(1500ms)` JSON 폴링, 완료 시 stop) · `GET /cortex/google/push/json/:job_id` JSON snapshot (owner mismatch 403). 워커 = `push_one_public` 재사용 → `registry.record` per item → 1s sleep → `registry.finish` (락 해제). **UI 재구성**: pending 페이지 = `<form id="batchpush">` 안에 행별 체크박스 + "전체 선택 토글" / "연락처 있는 행만 선택" (placeholder 자동 제외 hint) / "선택 해제" 보조 버튼 + sticky 액션바 "Push selected (N)". **검증** (fake UUIDs 2 개, Google API 호출 0 회 — NotFound 가 token refresh 이전 단락): empty form 303+err flash · 2 ids → 303 status page · immediate JSON state=running 1/2 · 2nd start during running → same job_id `?already_running=1` · 완료 후 락 해제 → new job_id OK · HTML status 200 (9118B) · edge https://axe.axelabs.ai/cortex/google/pending 200 + blue/green 재기동. **남은 작업** (다음 세션): #4 edit-before-push 인라인 수정, #5 partial-failure 분류 column. |
| 2026-05-29 | cortex | (web UI) | **🚀 cortex 웹 UI LIVE — `https://axe.axelabs.ai/cortex` SSO** ([D-cortex-6.1](/ops/decisions)). 운영자 "axe.axelabs.ai/cortex 웹에서 볼 수 있게" 요청 → cortex binary 안에 read-only 운영자 포털 추가 (axum + maud + 인라인 CSS, 별도 SPA/Next.js 없음). **구성** — `src/web/{session,auth,views,mod}.rs` 신규: (a) **세션** = HS256 JWT cookie `cortex_session` (`tok="web"` discriminator, 8h sliding refresh, HttpOnly+Secure+SameSite=Lax, Path=/cortex), CORTEX_JWT_SECRET 재사용; (b) **로그인** = `/cortex/login/start` → Microsoft Entra ID federation (state cookie CSRF gate, server-to-server token exchange, JWKS id_token verify — oauth_as.rs federation 코드 미러); (c) **페이지** — `/cortex/home` 대시보드 (kind 별 count metric + Google 연결 상태 카드 + 최근 8 audit event) · `/cortex/{people,orgs,deals,interactions,relationships}` 리스트 (visibility 필터 all/shared/private + page 50 페이지네이션 + primary/secondary label kind 별) · `/cortex/a/:id` detail (payload pretty + citations + 최근 20 events) · `/cortex/google/reconnect` (기존 `build_authorize_url` wrapper); (d) **격리** — MCP `auth::middleware` (Bearer) 와 web `require_session` (Cookie) 은 별도 axum layer (cross-token-type leak 차단). **Entra app 갱신** — web.redirectUris 에 `https://axe.axelabs.ai/cortex/login/callback` 추가 (기존 3 URI 유지). **검증**: `/cortex` 303→login · `/cortex/login` 200 (5247B) · `/cortex/login/start` 302→Microsoft + state cookie · 보호 라우터 7개 모두 미인증 시 303→login · 유효 세션 쿠키로 home/people/orgs/deals/interactions/relationships/detail 모두 200 + sliding refresh cookie 부착 · 위조 JWT (`tok="mcp"`) 거절 · wrong-secret JWT 거절 · `POST /cortex/logout` 302+clear cookie · MCP `/cortex/mcp` Bearer 흐름 + RFC 9728/8414 metadata 회귀 정상. Write 는 여전히 MCP. D-cortex-6 의 "UI 는 Blueprint" 부분만 번복 (D-cortex-7 single-binary ergonomics + 같은 DB pool + Microsoft federation 코드 재사용 + cross-service 호출 회피 이유). |
| 2026-05-29 | index | `e130a69` | **3 pre-IPO deal 축적 (스타넥스/한컴인스페이스/노바칩스) — calibrated 검토 본** ([D-index-19](/ops/decisions)). 사용자 "찾아서 축적하되 그대로가 아닌 검토 + 시사점". 출처 = OneDrive `_comparative_20260528_preIPO/` (13-agent 비교 IC 메모 + 5축 평가 + quant IRR). **핵심 — surface IRR ≠ calibrated IRR (최대 36pp gap)**: 스타넥스 19.6%→36.4%, 한컴 58.5%→22.4% (KOSDAQ 재청구 base rate down-cal), 노바칩스 -1.5%→7.45%. xlsx surface cell 그대로 축적했으면 한컴 1위 오기록 → index = reviewed truth 저장 실증. 3 seed = pre-IPO scenario-tree (각 scenario Bull/Base/Bear/Wipeout = 단일 exit outcome, P+MoM+holding). code: `parse_timing_years` 소수 연도 (2.5y/4.5y) + seed.rs validate 위임 + migration 20260528000003 (timing CHECK rigid enum → regex). **검증**: validate-model 3 신규 0 error, query_irr calibrated ±1pp (36.36/23.16/7.80), 6-deal portfolio 랭킹 Sentry 40.3 > Iippo 36.5 > Starnex 36.4 > Canopy 26.4 > Hancom 23.2 > Novachips 7.8 (pre-IPO 내부 랭킹 AXE 메모 일치). **5 시사점**: surface↔calibrated gap / instrument 8-15pp IRR-material (schema gap) / probability base-rate provenance / 동일 schema 가 Pre-A multi-leaf + pre-IPO single-leaf 수용 / **변곡점 IC 완성도 ≠ deal quality** (노바칩스 가장 정교=최약체). |
| 2026-05-28 (PM20) | index | (az + axe mcp) | **index_mcp catalog 등록 — claude.ai connector 4-field one-stop**. 사용자 발견: `axe mcp list` 에 index 누락. 원인: `customers.yaml axe.services.sso.apps` 에 `index_mcp` block 없음 (services.index secrets manifest 만 있고 sso.apps 의 OAuth app 정의 누락). 처리: (1) `sso.apps.index_mcp` block 추가 (client_id 47fe856f… + application_id_uri + redirect_uris claude.ai/claude.com + scopes [openid/profile/email/`mcp.access`] + client_secret_env), cortex_mcp 와 동형. (2) **Entra app gap 2개 정정** — `mcp.access` exposed API scope 가 없어서 (`api: []`) claude.ai 가 resource-scoped token 못 받을 상태였음 → Graph API PATCH `oauth2PermissionScopes` 추가 + `requestedAccessTokenVersion=2` (v2 token aud=client_id, frame/hive/cortex 정합). (3) `axe mcp publish` → vault `MCP Connectors` collection 에 **"Index MCP (axe)"** item created (URL + client_id + secret len=40 + scopes 4-field). 이제 `axe mcp list` 5 app (frame/hive/blueprint/cortex/**index**). 운영자가 claude.ai connector 등록 시 vault 한 곳에서 4 field 복사. **테스트 ready 검증**: cortex (live) 와 Entra app 구조 1:1 동일 (identifierUri + mcp.access scope + v2 token + redirect URIs). |
| 2026-05-28 (PM19) | index | (CF API + launchd) | **🚀 index production LIVE — `https://axe.axelabs.ai/index/mcp`**. 사용자 "끝까지 마무리" — 운영자 manual 영역까지 자동화. (1) **Cloudflare route 자동화** — 그간 "Soohun Global Admin 전용" 으로 분류했던 `/index` tunnel ingress 를 **zone-scoped CF API token** (`Cloudflare API - axelabs` vault item, ai@axellc.com 접근 가능) 으로 self-service 갱신. account id 는 zone 의 `account.id` 에서 derive (token 은 account-list 권한 없지만 zone-read 로 우회). `cfd_tunnel/{id}/configurations` GET (v19) → ingress[4] `/index` 의 `http_status:503` → `http://host.docker.internal:4012` 수정 → PUT (v20). **검증**: `/index/healthz` → 200 `{"service":"index","status":"ok"}`, `/index/.well-known/oauth-protected-resource` → RFC 9728 envelope (real tenant 122fb574…), `/index/mcp` (no auth) → 401. **함정 정정**: cloudflared dashboard-managed config 는 local `config.yml` edit 무효 (PM5 에서 발견) 였으나 — **CF API PUT 으로 dashboard config 직접 갱신 가능** = 운영자 dashboard 클릭 불필요. cortex/matrix/frame 도 동일 패턴 적용 가능 (known-gaps "Cloudflare tunnel Dashboard remote-managed" 가치 갱신). (2) **launchd 등록** — `ai.axe.index-skill-sync.plist` install + load (PID 8377 exit 0), 10분 주기 skill sync 작동 시작 (3 skill / 61 file). **잔여 prereq 1개** (UX only, hard-block 아님): Azure admin consent — Soohun 이 claude.ai 첫 OAuth 시 개인 동의로도 가능 (org-wide 사전 동의는 per-user prompt 회피용). **D-index-10 8/8 + Phase 1 전부 + production endpoint LIVE**. |
| 2026-05-28 (PM18) | index + blueprint | `6aa2680` + `8997e28` + `579a0fa1` + `2a74ef0` | **사용자 "모두 진행" — 4 backlog 일괄 완료**. (1) **B-index-xlsx-roundtrip** ✅ `import_xlsx` 16번째 MCP tool — calamine 0.26 read, Assumptions sheet parse, input drivers 만 비교 (derived는 formula 재계산), effective_db_value (period 0 fallback) semantic, diff (added/changed/removed/unchanged), apply=true → DB UPSERT. **검증**: 무수정 round-trip 49 unchanged, 1 cell 수정 → 정확히 1 changed 감지. (2) **B-index-3fs-bs-cf-completion** ✅ Phase 0 working capital model — BS 12 line (ar=rev×dso/365, inv=cogs×inv_days/365, ap=cogs×dpo/365, ppe_net=cum_capex, debt = max(0, init−cum_repayment), equity = init + Σni, cash = plug) + CF 7 line (indirect method: ni+dep−Δwc−capex−debt_rp). LpWorkbookInput 에 bs_lines + cf_lines 필드 추가, xlsx 4→6 sheets, HTML 7→9 sections. **검증** Iippo Y1: total_assets = L + E = 14.4M + 209.5M = 223.9M ✅ balanced. 4 (deal×scenario) compute_3fs persist 성공 (217 rows × 2 + 155 rows × 2). (3) **B-pmc-skill-skeleton** ✅ Background Agent 가 D-index-12 의 pmc (Post-Money Care) skill scaffold (30 files, 1,906 LoC) — SKILL.md 213 line + 8 agents (~93 line each) + 5 references (kpi-catalog/ir-lifecycle/postmortem-cadence symlink/risk-kind-frozen/trigger-tiers) + 4 Python stub + 11 sub-dir .gitkeep. (4) **B-blueprint-agent-sdk-integration** ✅ Blueprint hook — `scripts/sync-index-skills.sh` (index-skill-sync.py wrapper) + `launchd/ai.axe.index-skill-sync.plist` (10분 주기). 검증: 1차 sync 3 skill / 61 file added (ic+ingest+신규 pmc 자동 발견), 2차 sync 61 unchanged. **누적 16 MCP tools + 16 schemas + pmc skill 추가 + Blueprint sync hook 작동**. 회귀: validate-model 27/27 + IRR 3 deal ±1pp 유지. |
| 2026-05-28 (PM17) | index | `8b6f05d` | **MCP client — `bin/index-skill-sync.py` (B-blueprint-skill-mcp-client Phase 2)**. [D-index-17](/ops/decisions) Phase 2 — Blueprint Claude Agent SDK 의 filesystem `.claude/skills/` 직접 의존 제거 reference impl. Python stdlib only (no deps) ~297 line. **Dual transport**: HTTP (production Entra ID bearer) + CLI fallback (local-dev `target/debug/index mcp-call`). 동작: index MCP 의 `list_skills()` + `get_skill_resource()` 호출 → `/var/cache/blueprint-skills/{skill_name}/...` 로 sync. **sha256 cache invalidation** — server sha256 vs local file sha256 비교. **Conditional recursive traversal** — `has_{references,scripts,tests,agents}` 플래그 기반 fetch (scripts/_oneoff/ nested 도 처리). `--diff` mode (dry-run) + `--skill` 단일 필터 + `.manifest.json` (audit trail). **검증**: 1차 sync 43 files added (ic 39 + ingest 4) + 모든 sha256 verified + 2차 sync 43 unchanged (cache hit) + drift simulation (`echo >> SKILL.md`) → 'updated' 감지 + restore 1 updated. **운영 흐름** (Blueprint 측 도입 후): Agent SDK startup → `subprocess.run(["index-skill-sync"])` → cache dir 을 `.claude/skills/` mount point 로 인식 → 10분 cron 으로 server 변경 자동 fetch. 추가: 3 deal HTML render 일괄 생성 (Iippo base/mgmt/upside/downside + Sentry base + Canopy base, 6 file 모두 macOS open 으로 브라우저 즉시 view 검증). 다음 = Blueprint Agent SDK 측 loader 통합 + cron 등재 → [D-index-17](/ops/decisions) sunset 기준 (b) 충족. |
| 2026-05-28 (PM16) | index | `eb66fab` | **Native HTML LP dashboard (`export_lp_html`, 15번째 MCP tool)** — 사용자 결정 PDF 말고 native HTML 로 LP 에 deliver. md-to-pdf intermediate 없이 Rust 에서 직접 inline-CSS self-contained HTML 생성. 신규 `src/html.rs` (~360 line) — `build_lp_html()` 가 7 section HTML5: 🔒 Reproducibility (inputs_hash + xlsx sha256) / 📊 IRR Summary (primary metric card) / 💼 Fund Investments (status + baseline tag) / 📈 Income Statement (12 line × N period + derivation rules block) / 🎯 Exit Matrix (joint_probability column) / ⚙️ Assumptions (driver_value matrix) / 🔍 Audit Trail. 설계: self-contained (외부 fetch 0), Korean-friendly font stack (Apple SD Gothic Neo / Pretendard / Noto Sans KR), `@media print` 으로 LP 가 브라우저에서 PDF 출력, semantic HTML5 (a11y), color-coded (양수 green / 음수 red / NULL gray), sticky table headers. **bundle v2** = `index.html` + `xlsx` + `README.md` (cover.md 폐기, index.html 가 zip 첫 entry → LP 가 가장 먼저 봄). 검증: Iippo base HTML 20,250 bytes, 2회 export sha 동일 (`70096195...` byte-deterministic), 3 deal × 2 scenario 전부 성공, validate-model 27/27 + IRR 3 deal ±1pp 유지. **LP 흐름 update**: bundle.zip 첨부 → LP 가 풀어서 index.html 더블클릭 → 브라우저 dashboard + xlsx 로 cell audit. 다음 Phase 1 = xlsx round-trip + BS/CF + 선택적 interactive chart.js. |
| 2026-05-28 (PM15) | index | `d33e8de` | **`export_lp_bundle` MCP tool (14번째) — LP 가 1 첨부로 받는 zip + byte-deterministic**. Gap 3 마무리 layer. `export_lp_bundle(deal_code, scenario, out_dir?)` → `{deal}-{scenario}-{sha[:8]}-bundle.zip` (xlsx + cover.md + README.md). `src/xlsx.rs` 확장 (~150 line): `build_cover_markdown` (IRR table + Fund table + reproducibility lock + Phase 0 한계 박제), `build_readme_markdown` (LP 안내문: Excel 사용법 + 변경 요청 경로), `build_bundle_zip` (zip 1980-01-01 epoch deterministic). **Determinism fix 3종** (D-index-4 lock 강화): (a) xlsx `DocProperties.set_creation_datetime(epoch)` + set_author "AXE Labs index", (b) cover.md `Generated: <timestamp>` 제거 → inputs_hash[:16] 로 대체, (c) zip `last_modified_time(epoch)`. **검증**: 2회 export (2초 간격) → xlsx sha 동일 (`ac80f052...`) + bundle sha 동일 (`c940ce5b...`). Iippo base bundle 13,302 bytes (xlsx 11,892 + cover 1,997 + README 1,040). 3 deal × 2 scenario 전부 성공. validate-model 27/27 + IRR ±1pp 유지. 운영 흐름: 전 `export_lp_model` xlsx 첨부 (LP 별도 안내 필요) → 후 `export_lp_bundle` zip 1개 (cover + README + xlsx). Phase 1 = xlsx round-trip + BS/CF + PDF render. |
| 2026-05-28 (PM14) | cortex | `4c7dda0` | **visibility 결정 UX — 민감하면 LLM 이 먼저 묻기 + log_interaction visibility** ([D-cortex-9](/ops/decisions)). 사용자 요청 "private/shared 가 민감할 수 있으면 질문하도록". write tool 4종(register/classify/update_person + log_interaction) description 에 **SENSITIVITY RULE** 추가 — `visibility` 미지정 + 민감 가능 내용(딜 코멘트·협상 의견·사적 메모·비공개 미팅)이면 커넥터 LLM 이 저장 전 'private/shared?' 확인, 일반 공개 정보는 묻지 않고 shared. (MCP 는 요청-응답이라 직접 못 물음 → LLM-guidance 패턴. 기본값 shared 유지.) `log_interaction` 에 visibility + skip_audit_payload 신규 — "비공개 미팅" 답변을 실제 반영, participant relationship artifact 도 interaction 의 visibility 상속. **공유 인물 + 비공개 메모** 패턴 문서화 (person shared + 별도 classify_person private attribute). 검증: build 9.0s, tools/list 12 tool 0 bad key (description 한글=값이라 무관), log_interaction props 노출, interaction+relationship private 쓰기 rolled-back SQL 확인. **앞선 GitHub 연동 tools.15 사건**: cortex/frame/hive 라이브 + Claude-in-Chrome 22 tool 스키마 직접 검증해 전부 clean 확인 → 범인은 claude.ai 의 GitHub 연동(Anthropic 통합) — 커넥터 1개의 non-conforming key 가 전체 tools/list 400 (claude.ai 한계, [known-gaps] 가치). |
| 2026-05-28 (PM13) | index | `425a758` | **Gap 3 — LP-deliverable xlsx export (`export_lp_model` MCP tool, 13번째)**. D-index-18 chain 의 종결 — 사용자 stated 목적 "LP 요청 시 model 주는 것" 의 직접적 구현. `rust_xlsxwriter 0.95` Rust 네이티브 crate 사용 (calamine read counterpart는 Phase 1 round-trip backlog). 신규 `src/xlsx.rs` (~280 line): LpWorkbookInput → 4-sheet 결정론적 xlsx — (1) **Assumptions** driver_value 매트릭스 + cover (deal/scenario/horizon/inputs_hash), (2) **Income Statement** 12 line × 7 period + footer 의 derivation rule 문서화 (audit trail), (3) **Exit Matrix** leaf-level (joint_probability = Excel formula `=E*B`), (4) **IRR Summary** per-fund + weighted metrics + reproducibility footer. **export_lp_model(deal_code, scenario, out_dir?)** → `/tmp/index-lp/{deal}-{scenario}-{sha[:8]}.xlsx` 생성 + sha256 + size_bytes + inputs_hash + sheet_summary 반환. 검증: Iippo base 11,894 bytes, `file` 명령으로 "Microsoft Excel 2007+" 인식, unzip 으로 4 sheet 확인, **byte-equivalent reproducibility** (같은 DB → 같은 sha256), 3 deal × 4 scenario 전부 export 성공. **운영 흐름** (LP 전달): `export_lp_model Iippo base` → /tmp/index-lp/*.xlsx → 운영자가 LP 에 첨부 → LP가 Excel 에서 cell formula audit 가능 → cover sheet 의 inputs_hash 가 1년 후 재현 lock. validate-model 27/27 회귀 유지. Phase 1 잔여 = xlsx round-trip (calamine read → DB diff verify) + BS/CF sheet 완성 + PDF cover bundle. |
| 2026-05-28 (PM12) | index | `9ac0c68` | **Gap 2 — 3FS typed schema + `compute_3fs` MCP tool (12번째)**. LP-deliverable chain 의 다음 layer — driver_value 위 typed Income Statement / Balance Sheet / Cash Flow line items. migration 20260528000002 `financial_statement_line` 신설 (model_id × scenario_id × statement × line_code × period_index UNIQUE). frozen enum: **statement 3종** (income_statement / balance_sheet / cash_flow) + **is_line_code 12종** (revenue / cogs / gross_profit / `opex_{sm,rnd,ga,total}` / ebit / interest_expense / pretax_income / tax_expense / net_income). BS 12 line + CF 7 line 은 Phase 1 backlog (working capital + debt schedule 추가 driver 필요) — placeholder return. `compute_3fs(deal_code, scenario, persist=false)` MCP tool: driver_value lookup (period-0 fallback + base inheritance) → IS line 재구성 (cogs = revenue×(1-gross_margin), opex_total, ebit fallback, tax_expense = max(0, pretax × tax_rate), net_income). **검증** Iippo base: 12 line × 7 period = **84 cells persisted**. Y1 revenue=7.80억 → ni=1.10억, Y5 revenue=75.15억 → ni=10.55억, Y7 revenue=122.12억 → ni=17.15억 (net_income = pretax × 0.78 정확). /index/schemas 15 → 16 (`index.financial_statement_line@1.0` active). 회귀: validate-model 27/27 + IRR 3 deal ±1pp 유지. 다음 = [B-index-lp-deliverable-export](/ops/backlog) (Gap 3) — `rust_xlsxwriter` 로 financial_statement_line → Excel sheet 구조 deterministic export. |
| 2026-05-28 (PM11) | cortex | `2ff4cf4` | **xlsx import private-tagging — `--private-cols`** ([D-cortex-9](/ops/decisions) Phase 0 후속, [B-cortex-xlsx-import-run](/ops/backlog)). `Network_CRM.xlsx` enrichment migration 의 민감 컬럼을 `visibility=private` attribute 로 적재. `cortex import-xlsx --private-cols HPE,메모,소개` (default `HPE` = 민감 딜 코멘트). import.rs: 키별 visibility 결정(`private_cols.contains`→private\|shared) + insert_attribute visibility 컬럼 + 알 수 없는 private-col 경고(ENRICHMENT_KEYS 검증) + dry-run summary 에 private 카운트·컬럼·조정 안내. **혁신 축**: 컬럼 private 여부 hardcode 대신 configurable 플래그 + dry-run 가시화. 검증: build 9.1s + CLI `--help` 플래그 노출. **잔여**: 실 dry-run/apply 은 xlsx 파일 macmini 복사 + Google sync 선행 (운영자). |
| 2026-05-28 (PM10) | index | `9df7f71` | **`compute_full_model` MCP tool — DSL evaluator DB 통합 (Gap 1 closure)** + [D-index-18](/ops/decisions) 결정 박음 (single-driver + period-indexed). 사용자 질문 "Excel model → DB화 + 수식 + 계산 + 검증 best practice" 의 첫 gap closure: DSL evaluator 는 이미 구현돼 있었으나 DB 와 연결 안 됨 → 본 commit 이 마지막 1마일. 신규 11번째 MCP tool: `compute_full_model(deal_code, scenario, persist?)` — DB load → scenario inheritance (base 폴백) → base_revenue_period0 → revenue[-1] sentinel → `dsl::evaluator::evaluate(horizon)` → derived 결과 매트릭스 + inputs_hash + (persist 시 financial_driver_value UPSERT). evaluator 개선 2건: (1) topo_order self-edge skip (revenue[y-1] lag, A7 와 동일 정책), (2) lookup_value input period 0 fallback (Excel "constant input row"). **검증**: Iippo base 8 period × 2 derived = 16 cells persist → validate-model scenario_coverage **46% → 77%**, IRR ±1pp 회귀 유지. Iippo mgmt 시나리오 inheritance: base 13 + mgmt 11 override = 14 effective inputs, hash 분리. **발견된 modeling 안티패턴 → D-index-18 결정**: Y-suffix multi-driver (`revenue_growth_y1..y7`) + 단일 formula 결합 시 period 7 에서 revenue 1.2 quadrillion 원 비현실 compounding. Fix path = 단일 driver `revenue_growth` + period 0..6 별 값 (Excel "input row" 동형). Iippo seed refactor 잔여 = [B-index-driver-period-indexed-refactor](/ops/backlog). |
| 2026-05-28 (PM9) | cortex | `f8cad8c` | **artifact visibility tier — private partition Phase 0** ([D-cortex-9](/ops/decisions) · [B-cortex-private-partition-phase0](/ops/backlog) ✅). soohun.kang "Private Partition" 요청. **핵심 재구성**: 현재 모든 artifact 는 이미 RLS 로 owner-only (타인·관리자 볼 경로 없음) → `visibility` 는 owner RLS 섬 밖(**Blueprint M6 mirror**, [D-bp-artifact-1](/ops/decisions))으로 무엇이 나가는가를 막는 propagation gate. M6 이 아직 📐 설계(Q4)라 mirror 생기기 전 지금 박음. migration 0003 `artifact.visibility` (shared\|private, DEFAULT shared, 기존 3,250행 shared) + register_person `visibility`(**private→Google push skip**)·classify_person·update_person(re-tag)에 `visibility`+`skip_audit_payload` + list_persons `visibility`/`exclude_classification_key`/`_value` 필터(QueryBuilder, share-safe export §6) + get_person 노출. 기본값 정책 = base=shared / 민감분류·HPE import=private (backfill 불필요 — 민감 데이터 미유입). 신규 schema key 전부 ASCII (함정 #6). 검증: host build 8.8s + migration(3250 shared/0 private) + blue+green healthy + 필터 5-assertion **rolled-back** SQL(zero residue) + 외부 200/401. **잔여(auth)**: claude.ai tools/list 12 + register_person(private) 실 round-trip 스모크. Phase 1(Google 라벨 sync 필터)·2(M6 mirror 계약+field-level)·3(E2E) backlog 등재. |
| 2026-05-28 (PM8) | cortex | `b8d3aa0` | **blue/green healthcheck 수정 — Rust 이미지 self-probe** ([B-cortex-dockerfile-healthcheck](/ops/backlog) ✅). production-live 후 두 MCP 컨테이너가 영구 `unhealthy` 로 떠 있던 것 (트래픽 무해 — Caddy alias routing 이 health-gate 안 함, 그러나 blue/green swap 의 healthy gate 잠복 위험) 해소. 원인 = healthcheck `python -c urllib...` 인데 Rust/Debian-slim 이미지엔 python·curl·wget 없음 (`/usr/local/bin/cortex` 바이너리만). fix = `cortex healthcheck` 서브커맨드 (GET `127.0.0.1:$CORTEX_MCP_PORT/healthz`, 2xx→exit 0, `Settings::load` 전 short-circuit 으로 DB 자격증명 독립) + compose test `["CMD","/usr/local/bin/cortex","healthcheck"]` (green 은 `<<: *cortex-mcp-blue` anchor 머지 상속). **index(cortex 1:1 미러)의 python→curl 과 다른 선택** = 패키지 추가 없이 바이너리 재사용 (minimal-base 정합, index 정렬 권장). 검증: host build 8.6s + 서브커맨드 positive(3210)=0/negative(39999)=1 + rebuild 후 blue+green `(healthy)` + 외부 `/cortex/{healthz,mcp}` 200/401 유지. |
| 2026-05-28 (PM7) | index | `bf09547` | **Phase 2 entry — skill MCP discovery (`list_skills` + `get_skill_resource`)** ([D-index-17](/ops/decisions) Phase 2 path 진입). MCP 총 10 tools (8 → 10). (9) `list_skills()` 가 `/Users/axe/index/skills/` 의 모든 skill (현재 ic + ingest) 의 SKILL.md frontmatter (`name` / `description` / `allowed-tools` / `required_model` 등) + sha256 + sub-dir 존재 여부 (`references` / `scripts` / `tests` / `agents`) 반환. (10) `get_skill_resource(skill, path?)` 가 path 미지정 시 SKILL.md, 지정 시 skill dir 기준 relative resource fetch — file = `content` + sha256 + size, directory = `entries[]` listing. **Security**: (a) `..` path traversal 차단 (`PATH_TRAVERSAL` error), (b) skill 이름 영문/숫자/_/- 만 허용, (c) canonicalize 후 skill_dir starts_with 재검증 (symlink escape 차단), (d) invalid → `NOT_FOUND` + context. /index/schemas 도 15번째 schema (`index.skill_resource@1.0`) 추가 → total 15 (9 active + 6 stub). 다음 consumer = [B-blueprint-skill-mcp-client](/ops/backlog) (Blueprint Agent SDK 가 본 두 tool 로 skill discovery, filesystem mount 의존 제거) → [D-index-17](/ops/decisions) sunset 기준 (b) 충족 path. |
| 2026-05-28 (PM6) | index | `2dfc484` | **MCP surface 4→8 tools + /index/schemas 14 envelope 활성화** — Phase 0 다음 layer 진입. 신규 4 tool: (5) `list_deals(stage?, sector?)` portfolio overview, (6) `get_deal(deal_code)` full snapshot (target_company + funds[] + financial_model + scenarios[]), (7) `cross_deal_benchmark(driver, scenario)` A5 MCP 노출, (8) `get_exit_matrix(deal_code, scenario?)` leaf-level detail (joint_probability + dead_leaf + concentration). `/index/schemas` 가 빈 list → 14 schema 본문 ([D-index-7](/ops/decisions)): 8 active (target_company / deal / fund_investment / financial_model / financial_driver / financial_scenario / exit_matrix_leaf / financial_output) + 6 stub (dd_finding / ic_decision / portfolio_kpi / risk_alert / valuation / lp_comm — Phase 1 backlog 표시). `metadata.frozen_enums` ([D-index-15](/ops/decisions) immutable freeze): instrument 5 / status 6 / path 6 / risk_kind 5. dsl_operators 12개 freeze + 9 D-index-N decision_references. 신규 CLI `index dump-schemas` (auth bypass envelope JSON). 회귀 검증: validate-model 27/27 + 3 deal IRR ±1pp IC baseline 유지. 다음 consumer = ic skill `--push-to-index` ([D-index-13](/ops/decisions) atomic batch) + Blueprint citation resolver (`index.financial_output` kind). |
| 2026-05-28 (PM5) | index | (az CLI) | **`axe ship index` Azure prereq 5/7 자동화 완료 — Entra app + SP + permissions + vault 5 secret + .env.local merge**. `ai@axellc.com` 권한으로 az CLI 경유: (1) `az ad app create "Index MCP"` → `appId=47fe856f-75e8-457b-a10e-fce1559939f5`, (2) `az ad app credential reset --years 2` → secret 발급 (escape_dollar N/A — `$` 미포함, 다행), (3) `az ad sp create` (delegated grant prereq), (4) `az ad app permission add` (Microsoft Graph User.Read scope), (5) `axe secret push index` ×5 (db-password / jwt-secret / oauth-client-secret / pii-passphrase-axec / 기 등재 anthropic-api-key shared) → `axe secret check index` ✓ 5/5, (5.5) `axe secret pull index` → `/Users/axe/index/.env.local` atomic merge 완료. 로컬 docker compose restart 후 `/index/.well-known/oauth-protected-resource` 가 real tenant id 반영 (`https://login.microsoftonline.com/122fb574-7efa-476a-95b6-bee81bce2cce/v2.0`). **Manual 잔존 2건** (Soohun Global Admin 전용 — `ai@axellc.com` 권한 부족 확인 완료): (a) tenant admin consent — `az ad app permission admin-consent` 시도 → `401 Forbidden Authorization_RequestDenied`, (b) cloudflared route — **cortex 와 동일 함정 재확인** (named tunnel 의 dashboard-managed remote config 가 local file 을 override). local `config.yml` 의 `/index` 항목을 4012 로 갱신해도 cloudflared 가 dashboard 의 `http_status:503` 을 load. Cloudflare Zero Trust dashboard 의 tunnel `axelabs` Public Hostnames 에서 /index path service 를 dashboard 갱신 필요 (matrix/cortex/frame/hive/blueprint 와 동일). 검증 후 `curl https://axe.axelabs.ai/index/healthz` → `{"service":"index","status":"ok"}` 예상. |
| 2026-05-28 (PM4) | cortex | `dfa9330` | **Cortex production live — claude.ai connector + 12 MCP tools 확인** (첫 비-Python = Rust + axum + sqlx MCP 서비스, artifact-first Day 1). `https://axe.axelabs.ai/cortex/mcp` 가 Entra ID Bearer 로 12 tool (whoami / list·search·get·register_person / classify·update_person / log·list_interactions / connect·disconnect·sync_google_now) 노출. **5 테이블** (artifact / citation / artifact_event append-only / mcp_schema / google_oauth_token) + RLS FORCE + `cortex_app` NOSUPERUSER role 로 per-user 격리 ([D-cortex-2](/ops/decisions)). Google OAuth Web flow (per-user refresh_token pgp_sym_encrypt) + People API pull/opportunistic-push ([D-cortex-3·4](/ops/decisions)). claude.ai 연동까지 **7 함정** 돌파 ([known-gaps](/ops/known-gaps) Cortex 섹션): DB pass base64 URL 파싱 / env_file 따옴표 literal / RFC 9728 resource-level path / RFC 8414 path-insertion (authorization_servers→Microsoft 직접, [D-cortex-8](/ops/decisions) AS proxy dormant) / connector client_secret 입력 / **MCP tool property key ASCII-only** (`메모`→`memo`, 한글 key 1개가 tools/list 전체 400) / Cloudflare tunnel Dashboard remote-managed. 잔여 = [B-cortex-xlsx-import-run](/ops/backlog) (660행 enrichment) + [B-cortex-mcp-catalog-publish](/ops/backlog) (`axe mcp publish`). |
| 2026-05-28 (PM3) | index | `38dcac8` | **`axe ship index` production prereq 완료** — `axe ship` CLI 에 `index` 등재 (`SHIP_SERVICES` + `SHIP_DIRNAME_MAP`), `customers.yaml axe.services.index` block 신설 (5 secret manifest: db-password / jwt-secret / oauth-client-secret / pii-passphrase-axec / anthropic-api-key shared), Dockerfile cortex→index 정정 + `SQLX_OFFLINE=true` + `.sqlx/` 28 query cache checked-in (DB 없이 Docker 빌드 가능), docker-compose healthcheck python→curl 정정, `.env.local.example` index-specific 재작성. **검증**: docker compose up → 4 컨테이너 healthy (postgres :4000 + mcp-blue :4010 + mcp-green :4011 + axe-index-proxy :4012), `/healthz` 200, `/index/mcp` 401 + WWW-Authenticate (RFC 9728), `/.well-known/oauth-protected-resource` envelope 정상. **Manual 잔존** (Soohun Global Admin 전용): (1) az ad app `"AXE Index MCP"` 등록 + credential reset, (2) tenant admin consent, (3) `axe secret push index` (5 vault item), (4) cloudflared route `axe.axelabs.ai/index/*` → `host.docker.internal:4012`, (5) GitHub repo + remote add, (6) `axe ship index` 첫 deploy. 상세 runbook = [/services/index](/services/index#production-배포-axe-ship-index). |
| 2026-05-28 (PM2) | index | `4ef1581` | **[D-index-10](/ops/decisions) A8 PASS — MCP `tools/list` + `tools/call` 4 tool 통합 ⇒ D-index-10 acceptance 8/8 ALL PASS**. `src/mcp.rs` skeleton 137 → 566 line (fully functional dispatcher). 4 tool: (1) `propose_deal_closure(seed)` D-index-13 atomic batch (4 sub-tool 흡수, UUIDv5 idempotency_key retry-safe), (2) `validate_financial_model(deal_code)` (A7 6 check), (3) `compute_outputs(deal_code, scenario?)` (exit_matrix aggregation per scenario), (4) `query_irr(deal_code)` (per-fund display + summary weighted IRR). 검증: 3 deal 모두 IC baseline ±1pp PASS (Iippo 36.52% / Sentry 40.26% / Canopy 26.39%). irr::weighted_* 함수 재사용으로 validate.rs in-memory 와 byte-identical 결과 보장. 3-layer error model (D-index-14): L1 HTTP (auth middleware) + L2 MCP body (JsonRpcError + error_code + context) + L3 skill. dev 회귀용 `index mcp-call TOOL --args JSON` CLI 도입 (auth bypass). **D-index-10 8/8** = A1 (DB ingest) + A2 (IRR ±1pp) + A3 (1호/2호 독립) + A4 (per-fund baseline) + A5 (cross-deal benchmark) + A6 (⏸️ xlsx 별 backlog) + A7 (validate_financial_model 27/27) + A8 (MCP 4 tools). 다음 = axe ship index 또는 Phase 2 skill MCP discovery. |
| 2026-05-28 (PM) | index | `00dc6c5` | **[D-index-10](/ops/decisions) A7 PASS — validate_financial_model 3/3 deals (Iippo + Sentry + Canopy) 0 warnings 0 errors**. `index validate-model` CLI 6개 sanity check 도입 (driver_dag.cycle / scenario_coverage / exit_matrix.sanity / leaf_probability_sum / leaf_probability_sanity / fund_investment.invariants) — `src/validate_model.rs` 608 라인. 핵심 발견·수정: (1) `revenue[y-1]` self-lag 가 같은-period DAG cycle 로 오인 → cycle detection 에서 self-edge skip (lag = 시간축 recurrence, not 같은-period cycle). (2) Sentry/Canopy 는 exit-matrix-only 모델 (driver 는 informational, proceeds 는 leaf 직접) → scenario_coverage 0% 를 PASS 로 인식, exit_matrix_leaves count 함께 보고. (3) Canopy Initial BW status='paid' 인데 paid_date NULL → 2025-06-01 보강. 결과 9 check × 3 deal = 27/27 PASS. **D-index-10 6/8 acceptance** (A1+A2+A3+A4+A5+A7). 잔여 = A6 (xlsx round-trip) + A8 (MCP tool integration). 다음 = `B-index-A6-xlsx-roundtrip` + Phase 2 (B-index-skill-versioning-schema / B-index-skill-mcp-discovery / B-blueprint-skill-mcp-client). |
| 2026-05-28 (Round 6) | docs | (TBD) | **🧹 Ready 중복 5건 제거 (concurrent index 세션 promote 누락분)**. 구조 점검 중 발견 — 5 항목이 Ready + Done 양쪽 동시 등재 (index/pmc 세션이 ✅ Done 으로 옮기며 Ready 사본 제거 누락): B-pmc-skill-skeleton, B-index-customers-yaml, B-index-lp-deliverable-export, B-index-skill-mcp-discovery, B-blueprint-skill-mcp-client. Done 본이 ✅+commit/LoC 증거로 authoritative → stale Ready 사본 5개 제거 (그들의 promotion 완성). 잔여 중복 0 검증. Ready 88 → 83 (실제 -5 active, phantom-todo 해소). 표 구조 점검 = 중간 빈줄 0 ✓. ground truth: in-progress 1 / ready 83 / 신규 60 / Done 54 / Archive 15. |
| 2026-05-28 (Round 5) | docs | `b04f0e4` | **🗄️ Done 섹션 lifecycle 정비 + 집계 방법 정정**. (1) Done 에 1주+ 경과 (2026-05-22/23) ship 완료 항목 15개 → 신규 `## 🗄️ Archive` compact 표로 이동 (lifecycle "이미 ship 된 ✅ 항목 promote" 준수). 각 항목 narrative 는 Ship Log + decisions.mdx 에 영구 보존 확인 후 verbose row 제거, Archive 는 ID→decision trace 만 (compact). Done staging 비대 해소. (2) **집계 정정**: 세션 내내 사용한 full-file `awk` 가 섹션 경계 배정 버그로 Ready/Done undercount (awk: ready 75 / 실제 명시 line 경계 python+sed+awk-range 3중 검증 = **ready 88**, 세션 중 불변). 🆕 신규만 일치 → **신뢰 지표 = 신규(분류 큐) 75 → 60 (-15)**. 기존 라운드의 "활성 151→136" 절대값은 불변 Ready 를 13 undercount 한 artifact 로 정정. 현재 ground truth: in-progress 1 / ready 88 / 신규 60 / Done 54 / Archive 15. |
| 2026-05-28 (Round 4) | docs | `acd26b7` | **🤖 Round 4 — deep audit (60 신규) with MCP verification, backlog 136→136 (0 reduction)**. 1 agent (Explore) 가 잔여 60 신규 항목 audit → 3 항목 silent-done 추천 (B-hive-send-202605, B-hive-mark-paid-202605, B-hive-202604-recon). **운영자 가치 = MCP 검증 결과 audit 결론 모두 inaccurate**: hive MCP `payroll_list_send_log` + `payroll_list_dispatch_log` 직접 query → (a) B-hive-send-202605: 강태훈 ✅ sent (5/25 graph_api) + 한진우 ❌ pending (RRN 선행) = **partial**, (b) B-hive-mark-paid-202605: paid_finalized 0 records = **NOT done**, (c) B-hive-202604-recon: dispatch_log 0 records = **NOT done**. 본 finding 의 교훈 = agent audit 은 description-circular 위험, prod MCP 검증 필수. 변경 = B-hive-send-202605 description 정확화 (강태훈 sent + 한진우 pending) 1줄. 활성 backlog 136 그대로. 누적 (Round 1+2+3+4) 151→136 (-15). |
| 2026-05-28 (Round 3) | docs | `5c7b262` | **🤖 Round 3 — reports landing + silent-done audit, backlog 138→136 (-2)**. (1) `/ops/reports/` 폴더에 `index.mdx` 신설 (77 라인, 4 섹션: 목적/보유/가이드/backlog 연계 + 3 report 표) + reports/_meta.js anthropic entry 추가. (2) Audit-driven silent-done 이동 — D-day 5/25 Ship Log narrative 근거: `B-customer-deploy-generalization` ✅ (R1-R5 완료, Phase 3 3rd-customer 만 split), `B-realchoice-port-collision-audit` ✅ (5/5 endpoint LIVE = implicit pass), `B-realchoice-vault-instance-decision` ✅ ((a) 채택 확정, description 정정 후 이동). 신규 62 → 60, Done 48 → 51. 누적 (Round 1+2+3) 151 → 136 (-15). |
| 2026-05-28 (Round 2) | docs | `1b45ab9` | **🤖 Round 2 — 4-agent 병렬 upstream draft + D-day traps consolidation, backlog 142→138 (-4)**. (1) `B-anthropic-connector-input-attrs` ✅ `/ops/reports/anthropic-connector-input-attrs-2026-05` 173 라인 (claude.ai Custom Connector modal 4 input 식별자 부재 → Anthropic 측 보고 draft). (2) `B-vault-axe.2-patches-upstream-pr` ✅ `/ops/reports/timshel-vaultwarden-upstream-pr-2026-05` 165 라인 (axe.2 2 patch upstream PR description draft, mainline backport 성격). (3) `B-trap-33-frame-hive-multi-issuer-docs` ✅ `/architecture/auth` line 147 정정 + 함정 row 추가 (v2 강제 + multi-issuer defense in depth). (4) `B-ops-reports-sidebar` ✅ `content/ops/_meta.js` reports entry 등재. 추가 consolidation: `B-vault-d-day-traps-2026-05-25` + `B-onboard-d-day-traps-2026-05-25` 두 trap inventory entry ✅ done 으로 이동 (모든 sub-trap ✅ 또는 split 완료). 신규 66 → 62, Done 42 → 48. 빌드 검증: 65 페이지 indexed (+2 신규). 누적 (Round 1 + 2) 활성 backlog 151 → 138 (-13). |
| 2026-05-28 | docs | `5e0f2a1` + `065cf63` | **🤖 6-agent 병렬 docs cleanup — backlog 151→142 (-9 active items)**. 멀티 에이전트 wave 1 (6 agents parallel) 로 docs SSOT 갱신: (1) `B-vault-setup-playbook-v2` ✅ [/onboard/vault-setup](/onboard/vault-setup) +84 라인 (taehun 5건 피드백 inline: Windows Hello + Phase 강제/선택 + TOTP UI + 자동 채우기 분기 + 표준/변형). (2) `B-vault-revoke-scope-doc` ✅ [/architecture/vault-policies](/architecture/vault-policies) `## Vault scope` 신설 (8-row 분리표) + [/ops/runbook/employee-offboarding](/ops/runbook/employee-offboarding) 외부 service 회수 step. (3) `B-bw-cache-recovery-procedure-docs` ✅ [/architecture/secrets](/architecture/secrets) 함정 표 row + [/ops/runbook/vault-recovery](/ops/runbook/vault-recovery) 새 ## 섹션. (4) `B-blueprint-scope-change-runbook-docs` ✅ [/architecture/auth](/architecture/auth) 함정 row + `## OAuth scope 추가 시 운영자 절차` 신설. (5) `B-claudeapp-fd-leak-anthropic-report` ✅ `/ops/reports/claudeapp-fd-leak-2026-05` 113 라인 self-contained draft (Anthropic support 제출용). (6) `B-docs-ssot-extension-2026-05-26-corrections` ✅ B4-B7 정정 (topology artemis_default + services/frame `${HOME}` + partner/registration `--allow-no-subscriptions` + partner/deploy 18-step 함정 표). 추가 backlog cleanup: 신규 75 → 66 (✅ 항목 7건 Done 으로 이동, 1건 description 갱신, 1건 자동화 prong 만 잔존으로 축소). 11 파일, +300 라인, -28 라인. |
| 2026-05-27 | docs | `6228f1d` | **[D-ops-41](/ops/decisions) — SSH client-side automation (Windows) 영구 fix** — Soohun Kang 실전 셋업 (Windows 11 + cloudflared 2026.5.1 + OpenSSH for Windows 9.5p2) 도중 발견한 6 함정 (#9~#14) 영구 해소. `/onboard/ssh-access` Step 7 의 `Scheduled task 자동화` 블록 폐기 → **user-context Scheduled Task + VBScript wrapper** (`cloudflared-ssh-axe-tcp`, AtLogOn + VBS 무한 루프, `wscript.exe` 0-flash hidden, 정상/비정상 종료 모두 5초 뒤 재기동) 로 전환. 신규 § "Token 자동 갱신 (Windows)" 추가 — **self-rescheduling PS1 task** (`cloudflared-token-renewal`, JWT `exp` claim 파싱 → `exp - 5min` 에 1회 fire, `-RunLevel Highest` 필수). 24h 마다 사람이 매일 수동 `cloudflared access login` 실행하던 ❌ → ✅ 자동. NSSM/SYSTEM 서비스화 폐기 사유 박제 (부록 — JWT user-scoped vs SYSTEM `%SystemRoot%\System32\config\systemprofile\` 격리 → 무한 token lock 루프). 함정 정리 표 8행 → 14행 확장. "매 작업 시 사전 작업" 표 갱신 (PC 로그온 + token 만료 5분전 모두 자동 + 선택 sticky session). **검증**: `Get-Process cloudflared, wscript` 둘 다 살아있고 `MainWindowHandle = 0` (가시적 창 0) / `Get-NetTCPConnection -LocalPort 2222 -State Listen` LISTENING / `ssh -p 2222 axe@localhost` `axe@AXEs-Mac-mini ~ %` prompt 정상 / PowerShell 창 모두 종료 후 신규 창 동일 검증 PASS (TCP forward 생존 확인) / renewal task `renewal.log` 에 `token exp=... / next run: ...` 두 줄 정상. |
| 2026-05-26 22:40 | docs | `bb61969` | **blurgram carve out — docs.axelabs.ai 에서 blurgram 흔적 0** (운영자 결정 "blurgram 은 자체 docs 로 별도 관리"). `content/ops/{backlog,known-gaps,decisions,inventory}.mdx` + `content/onboard/ssh-access.mdx` 5 파일, 33 deletions only. 이동 destination = blurgram repo 의 신규 `docs/AXE_HOSTING.md` (D-axe-36 MVP host pattern + D-axe-41 AXE 운영 편입 + D-axe-42 자체 AI 비활성 + 운영 inventory) + `docs/dogfooding/2026-05-26-cycle-relaxed-peach-squid.md` (외부 LLM citizen 첫 cycle 16 row 관찰표 보존) + `docs/status/03-backlog.md` 의 R/U 2 항목 추가 (`B-blurgram-dogfooding-feedback` + `B-blurgram-activity-log-sink`) + calendar alarm 2 row (8/25 + 11/25 sunset) D-axe-41 substitute 로 무효화 표시. 내용 누락 0. 검증: `grep -rn blurgram content/` → 0, live `curl https://docs.axelabs.ai/ops/known-gaps.md \| grep -c blurgram` → 0. memory 측 (`project_mvp_hosted_tunnels.md` + `project_blurgram_agent.md` + `MEMORY.md` index) cross-ref 도 정합 갱신 (operator 회상 보조로만 보존, SoT = blurgram repo). |
| 2026-05-26 22:00 | docs + axe-cli | `5726912` + `c03768a` | **backlog 갯수 정리 — 11 task 중 8 처리** (5 live + 1 axe CLI defensive + 2 draft). **1차 batch (`5726912`)**: B-bw-cli-version-pinning (`/architecture/secrets` Bootstrap 섹션 신설 + 함정 표 row + `/partner/macmini-prep` §6 신설 + 함정 row, bw 2025.7.0 표준 정합), B-docs-cache-control-static (`next.config.mjs` headers 에 `/llms.txt`+`/llms-full.txt`+`/changes.json` `s-maxage=60` 추가, Cloudflare 옛 응답 잔존 차단), B-trap-24-blueprint-mcp-admin-consent (`/partner/registration` Option A 사전 확인 표에 admin consent grant 권한 4 role 명시 + 함정 표에 manual grant 절차 + Option B 함정 모음 row 추가). **2차 batch (`c03768a`)**: B-axelabs-bootstrap-blueprint-mcp-app (trap #18 영구 fix — `public/axelabs-bootstrap.sh` App #4 Blueprint MCP 등록 step 추가 Frame MCP 패턴 1:1 mirror + JSON pack `blueprint_mcp` 필드 + `axe customers ingest` optional 흡수 backward compat + `/partner/registration` "3 개" → "4 개" + Option B App #4 섹션 신설 + SHA-256 갱신 `ae6f771e...`), B-customers-yaml-mkdir-trap (trap #20 — root cause grep 검증 결과 phantom 확정 + axe CLI `_load_yaml`+`_load_customers_yaml_rt` `path.is_dir()` defensive sanity check), B-trap-23-hive-volume-compose-prefix (R6 통합 결정, R6 row 비고에 hive volume 명시 추가). 라이브 검증: `https://docs.axelabs.ai/llms.txt` cache-control `s-maxage=60` ✓ + bootstrap.sh SHA = local 일치 ✓ + npm run verify:box PASS ✓. **남은 3 운영자 본인**: B-axe-labs-ai-2fa, B-cf-token-rotation, B-bp-mcp-teams-admin-consent. **draft 2 사용자 trigger**: B-vault-axe.2-patches-upstream-pr (`/Users/axe/vault/UPSTREAM_PR_DRAFT.md`), B-claudeapp-fd-leak-anthropic-report (`/Users/axe/.axe/ANTHROPIC_FD_LEAK_REPORT_DRAFT.md`). |
| 2026-05-26 17:35 | docs | `df85ba0` + `3dde8eb` + `ef8138e` | **MCP Connectors catalog LIVE — Vaultwarden `MCP Connectors` org collection (`1a62e754-...`) + `axe mcp publish/list` CLI + `axe secret rotate` step 4.5 auto-hook** ([D-vault-mcp-catalog](/ops/decisions)). 운영자/직원 (4명 access) 가 `claude.ai/customize/connectors` 등록 시 4 조각 (이름·URL·client_id·client_secret) 을 Bitwarden 확장 한 클릭에 자동 suggest. SoT 변경 0 (catalog = customers.yaml + vault 의 derived view). 3 MCP seed (frame/hive/blueprint) 완료. 본 세션 부수 발견: (a) **bw 2025.7.0 cache stale root cause 확정** = server-side patch deploy 후 cached `cryptoSymmetricKey` MAC fail, fix = `bw logout && bw login` 1분 절차 ([known-gaps](/ops/known-gaps) "매니페스트 / vault 측 미해결" 표). 오진 2회 (L2 REST API 마이그레이션 / KDF rotation) 후 정정 — backlog matching 만으로는 부족, premise 검증 필수 ([memory](#) feedback_session_start_ritual). (b) **bw `--passwordenv` silent failure** = positional `bw unlock "$PW" --raw` 만 작동. (c) **Keychain account 일관성** = `-a ai@axellc.com` 표준 (secrets.mdx:495), `$(whoami)` 사용 시 별 entry 생성 + find 가 옛 token 반환. (d) **customers.yaml frame_mcp 정정** = "proxy-only" stale 주석 해제, claude.ai 가 confidential client 요구하므로 secret 포함 publish. **backlog ✅**: [B-vault-mcp-catalog](/ops/backlog) + [B-bw-cache-recovery-procedure](/ops/backlog) 신규. axe CLI: `cmd_mcp_publish` + `cmd_mcp_list` + argparse + rotate hook (~190 LOC). |
| 2026-05-26 14:24 | frame | soohunkang/frame `3f9a707` | **D-frame-register-entity-atomic LIVE — 강태훈 bug report 의 root cause #2/#3 영구 fix + DB 좀비 정리 + axev→axe_ia_001 GP 관계 등록** ([D-frame-register-entity-atomic](/ops/decisions)). 강태훈 2026-05-22 Teams 메시지 (chat `19:5fda...@thread.v2/1779450170089`, sender taehun.kang@axellc.com) 의 KIP 등록 버그리포트 audit + fix + 회신 cycle. (1) ck_policy_standard mismatch 는 PR #38 (`3d8181d`) + 0019 in-place ALTER 로 이미 fix, 7 schemas 모두 적용 완료. (2) **잔여 위험 2건 코드 fix** (`src/frame/db/migrations.py:88 register_entity`) = (a) existing row 의 standard/kind/schema_name mismatch 시 ValueError (silent override 금지), (b) `upgrade_entity` 실패 시 compensating `DROP SCHEMA CASCADE` + `DELETE shared.entity` (좀비 회수, 기존 row 보호). 6 신규 pytest (`tests/test_register_entity_atomicity.py` mismatch standard/kind/all-diffs · idempotent identical · zombie cleanup · pre-existing 보호) + 16 기존 PASS 무회귀. (3) **DB 좀비 정리** = `axe_ia_001_diag` + `bug_check_kip_20260524` (actor=taehun.kang) DROP SCHEMA CASCADE + DELETE shared.entity (단일 트랜잭션, cross-ref 0 확인). 7 entities → 5 (axec/axev/axtest/axep/axe_ia_001). (4) **axe_ia_001 정상 회복** = 48 fund_ksme accounts + accounting_policy bootstrap + alembic 0019 head + fund_meta (GP=axev, 755M 약정, 21명 LP, 2026-04-22 등록 866-80-03471). 회계 데이터 0 = 사용 시작 준비. (5) **`shared.entity_relationship` row #112** = (axev → axe_ia_001, gp_managed_fund, effective_from=2026-04-22, ownership NULL — AXEV GP 자기 commit 분리 미명시). **axep** (액스파트너스 유한책임회사, 의도 불명, 데이터 0) 는 보존 ([known-gaps](/ops/known-gaps) 등재). **deploy 검증**: `axe ship frame` 통과 (docs-check no drift / 1 commit push / blue→green flip / `axe.axelabs.ai/frame/health` 200 / active=green:3711). 강태훈 회신 draft 완성, 강수훈이 Teams 로 forward 예정. **backlog ✅**: [B-frame-fund-ingest-verify](/ops/backlog) + [B-frame-register-entity-atomic](/ops/backlog). |
| 2026-05-26 16:17 | vault (axe org) | (compose env + API policies + docs) | **vault axe.3 post-deploy 정책 layer 박제 — server env `SSO_AUTH_ONLY_NOT_SESSION=true` + Org Policies 4종 + 신규 docs 페이지** ([D-ops-40](/ops/decisions) Progress xi-xii). ai@ KDF rotation 검증 완료 (Master password change + rotate encryption key 만으로 SSO→MP 정상). server env 1종: `SSO_AUTH_ONLY_NOT_SESSION=true` → SSO 인증만, session = Vaultwarden 자체 30일 idle refresh (60s 다운타임, 모든 SSO user 자동 적용). Org Policies 4종 (Owner API): MasterPassword(min 12, complexity 1) + PasswordGenerator(len 20) + SingleOrg + PersonalOwnership. MaximumVaultTimeout 시도 HTTP 400 — Timshel source 의 `// Not AGPLv3 Licensed` 확인 (Bitwarden commercial license, Vaultwarden 영구 미지원, `SSO_AUTH_ONLY_NOT_SESSION` 이 가용 best 대체). 신규 docs [/architecture/vault-policies](/architecture/vault-policies) 박제 (3 layer 모델: server env + Org Policies + per-client preferences, 새 직원 onboarding 표준 setup, customer sovereignty 안내). **잔여**: soohun/taehun/jinwoo KDF rotation (각 본인 5분, ai@ flow 그대로). [B-vault-axe.2-sso-mp-incomplete](/ops/backlog) ✅ 이동은 3명 완료 후. |
| 2026-05-26 13:19 | vault (axe org) | axelabs-ai/vault `799015b` | **vault axe.3 LIVE — `ghcr.io/axelabs-ai/vault@sha256:a26208a0...` 으로 manifest-digest 재핀** ([D-ops-40](/ops/decisions) Progress). 3.5h 실 진행: realchoice 측 build pipeline (build.sh + Dockerfile + GHA workflow + 2 axe.2 patches) vendor + axe.3 patch 2개 (organizations Owner-skip 3 site + cipher.permissions backport — line 600 `post_bulk_access_collections` 추가 발견 → 3곳 모두 fix). 로컬 docker arm64 build 검증 5분 → main push → GHA 13분 multi-arch (amd64+arm64) GHCR push → imagetools alias `1.34.1-6-axe.3`. axe-macmini deploy: data + sqlite 백업 → pull + up → 60s healthy. **검증 3건 in-production**: VERIFY 1 `bw create org-collection` → SQLite users_collections 에 Owner ai@ row 명시 insert ✅, VERIFY 2 raw GET `/api/sync` → cipher.permissions `{delete:true,restore:true}` server emit ✅ (bw 2025.7.0 출력은 null — 옛 client 가 unknown field 미파싱), VERIFY 3 `bw delete item` rc=0 ✅. external alive HTTP 200 (0.28s). **GHCR auth**: PAT 발급 → AXE vault `Platform — Service Secrets / ghcr-axelabs-ai-pull-pat` 저장 ([D-ops-ops-17](/ops/decisions) SoT, keychain 회피). **잔여**: 4명 KDF rotation (PBKDF2 → Argon2id, [B-vault-axe.2-sso-mp-incomplete](/ops/backlog) runbook) + Truvia 안내 (customer self pull). **backlog ✅**: [B-vault-fork-build-pipeline](/ops/backlog) + [B-vault-org-perm-3-quirks](/ops/backlog). [D-ops-37](/ops/decisions) image 라인 axe.3 digest 로 갱신, rollback 주석 (axe.2 ImageID + timshel digest) 보존. |
| 2026-05-26 (심야) | vault (axe org) | (운영 데이터 + docs) | **vault organization 권한 모델 정착 + OpenAI item 통합 + 3 권한 함정 root-cause 진단** ([D-ops-32](/ops/decisions) Progress + [D-ops-38](/ops/decisions) 첫 실 적용 + [B-vault-org-perm-3-quirks](/ops/backlog) 신규). **collection 작업**: D-ops-32 의 6 collection 전부 `bw create org-collection` 으로 신설 (AXEC/AXEV/AXEP/Platform Service Secrets/Platform Infrastructure/Shared Tools). **권한 fix**: server-side `users` 배열 매핑 함정 (Owner skip + manage=0 강제) 으로 6 collection 모두 ai+soohun 권한 누락 → vaultwarden stop → SQLite 직접 `users_collections` INSERT/UPDATE/DELETE (transaction) → start. **OpenAI item 통합**: soohun 이 personal vault → AXE org share 한 두 item (`chatgpt.com` + `platform.openai.com`, 같은 ai@ 계정) 을 1 item multi-URI (Base domain match) 로 통합. cipher delete/move 가 bw CLI 의 client-side `permissions.delete: false` reject 로 막힘 → `*/admin` HTTP endpoint 직접 호출 (access_token = bw data.json 추출) 로 우회 → 영구 삭제 + Platform — Infrastructure 단독 collection. 최종 = 1 item, 권한 정합, MCP connector 영향 0. data/ 추가 백업 (`db-pre-permissions-fix-20260526-111834.sqlite3`). |
| 2026-05-26 (저녁) | vault (axe tenant) | (compose 단독) | **vault axe.2 패치 — axe-vaultwarden 1.34.1-6-axe.2 deploy** ([D-ops-37](/ops/decisions)). Bitwarden client >= 2026.4 (Chrome ext + bw CLI) 와 Timshel 1.34.1-6 사이 2 protocol 불일치 영구 fix. 이미지 출처: realchoice-macmini local build (axelabs-ai/vault 의 GHCR push 미구축) → docker save/load streaming (LAN 7s) → axe-macmini import (arm64, ImageID `sha256:11536845...`). compose image 라인 교체 + commentary 갱신 (Timshel digest 이전 값 rollback 주석 보존). `/vault/identity/accounts/prelogin/password` 200 OK 회귀 검증 ✅ (이전 404). **운영자 수동 검증 결과**: (a) MP 단독 web 로그인 ✅, (b) SSO 성공 → MP 단계 ❌ (web + Chrome ext + native app 3 client 모두 동일 → server-side 원인 확정. realchoice-macmini 동일 image 는 정상이라 회귀 아님, 기존 user wrapped MP schema 미마이그레이션 가설). 후속 = [B-vault-axe.2-sso-mp-incomplete](/ops/backlog). data/ 2.5MB 사전 백업 (`backups/data-pre-axe.2-20260526-093846.tgz`). **backlog**: `B-vault-d-day-traps-2026-05-25 #12` server-side 영구 fix 등재, 신규 `B-vault-fork-build-pipeline` + `B-vault-axe.2-patches-upstream-pr` |
| 2026-05-25 (오전) | infra+docs | (다수) | **🎯 realchoice (Truvia 주식회사) D-day-resume 완료 — 5/5 endpoint LIVE + customer sovereignty 첫 실제 적용**. 5/25 09:00 KST 일정 앞당김 (Truvia 요청 "지금 즉시"). **운영자 책임 3건**: (1) cloudflared catch-all 교체 09:28 (5 rule → 1 rule, trap #10 fix `127.0.0.1:8090`). (2) hive repo PAT 임시 push (axelabs-ai/hive private clone, ~/.netrc 즉시 제거). (3) customers.yaml realchoice 블록 sovereignty 정리 (`legal_name=Truvia 주식회사`, 5 sso.apps client_id 만 유지, services secret manifest 일체 제거 — customer 측 자체 SoT). **Truvia 자체 (sovereignty 본질)**: blueprint MCP + hive MCP Entra app 자체 등록 + secret 자체 (openssl rand) + .env + compose up + axe-realchoice-ingress Caddy 신설 (host port 8090) + 5 service self-deploy. **5 endpoint health**: `/` 200 / `/frame/health` 200 / `/vault/alive` 200 / `/blueprint/mcp/health` 401 (OAuth) / `/hive/health` 200. **신규 trap 5건** (#18 bootstrap.sh Blueprint MCP app 미등록 / #19 docker volume external 사전 부재 / #20 customers.yaml directory 잘못 생성 / #23 hive volume compose project prefix / #24 admin consent Global Admin 부재). **신규 backlog 5건** (B-customer-sovereignty-architecture Q3 + 4 trap 영구 fix). axe CLI 변경: `_render_cloudflared_config` catch-all + `_svc_step_ingress_swap` no-op + `--yes` flag + `_svc_step_customer_vault_check` bw 2025.7.0 + APPDATA_DIR 격리 |
| 2026-05-26 (PM) | docs+axe-cli | (다수) | **Truvia 5/26 회신 반영 — D-day blocking + backlog 확장** (B-customer-deploy-generalization Phase 1 후속). Truvia 측 D-ops-32 완료 보고 (realchoice vault organization `eac93965-...` + ai@ invite + collection 4종) + 4 신규 함정 (#12-#15) + docs SSOT 갱신 권장 (7 페이지 + 17 함정 통합 + 5 표준). **5/27 D-day blocking 처리**: bw-bootstrap.sh 갱신 (bw 2025.7.0 pin + BITWARDENCLI_APPDATA_DIR 격리), wrapper 3종 (`start-{frame,blueprint,hive}.sh`) 가 ~/.bw-appdata-dir source, axe CLI `_svc_step_customer_vault_check` 가 bw version assertion + appdata 격리 검증, `_svc_step_secrets_bootstrap` 가 cross-vault sync 도 appdata 격리 전파. **backlog 등재**: `B-vault-d-day-traps-2026-05-25` 의 #12-#15 본문 추가 (8 함정 누적), `B-onboard-d-day-traps-2026-05-25` 의 #6/#16/#17 본문 추가 (12 함정 누적). 신규 backlog 6종 (`B-vault-org-create-automation`, `B-vault-org-cli-automation`, `B-port-conflict-preflight`, `B-frame-keychain-to-vault`, `B-bw-cli-version-pinning`, `B-docs-ssot-extension-2026-05-26`). known-gaps 에 **axelabs 5 표준** 신설 섹션 (macmini 패턴 등가 / Timshel image / bw 2025.7.0 / customer-deploy R1-R5 / customers.yaml schema). **회귀 0** — axe-side deploy + customer dry-run 모두 통과 |
| 2026-05-26 (AM) | axe-cli+infra | (axe CLI 미관리) | **B-customer-deploy-generalization Phase 1 완료** — `_deploy_service_customer(service, customer_id, ...)` 신설 (axe CLI line ~3265, 13-step service-agnostic). SERVICE_DEPLOY_CONFIG 참조하여 frame/blueprint/hive customer-측 deploy 통일. 5 요건 빌트인: R1 `${HOME}` 변환 (remote_dir_template), R2 vault SoT (customer macmini 측 `bw get password` — keychain 의존 폐기), R3 `$` → `$$` escape (`escape_dollar` flag), R4 `image_override` 슬롯 (customers.yaml). wrapper 3종 정비 (`start-{frame,blueprint,hive}.sh` 모두 `~/.bw-session` + `.secrets.list` 기반). customer 측 1회 부트스트랩 helper `bw-bootstrap.sh` 신설. `cmd_deploy_blueprint` body 가 dispatcher delegate, hive/frame customer 분기 활성. realchoice customers.yaml 의 3개 OAuth secrets 에 `escape_dollar: true` 적용. **회귀 0** (axe-side frame/blueprint-mcp/hive deploy dry-run 모두 통과). known-gaps trap 4·5·6 영구 fix 표지. **Pending Phase 2** = Truvia 5/27 D-day-resume 시 `axe deploy {frame,blueprint,hive} realchoice --apply` 일괄 |
| 2026-05-25 (PM) | docs+axe-cli+infra | `70f0599` → `8c82595` (5 commit) | **realchoice D-day frame+vault layer LIVE + customer-deploy 일반화 착수** — onboard 18-step ✅ 완료 (`realchoice.axelabs.ai/frame/health` HTTP 200) + Vault OIDC SSO 통합 ✅ (Q3 (a) 채택, `~/vault` = `soohunkang/vault` repo, SSO 로그인 → 잠금 해제 정상). D-day 함정 누적 10 (onboard) + 4 (vault) = 14, 모두 backlog 등재 (`B-onboard-d-day-traps-2026-05-25` + `B-vault-d-day-traps-2026-05-25`). vault-recovery runbook 의 sso_nonce schema PostgreSQL/SQLite 분기 + `verifier` column 명 정정. Truvia C 채택 후 **`B-customer-deploy-generalization` 진입** (M1, ETA 2026-05-27, 5 요건 R1-R5 빌트인). axe CLI `SERVICE_DEPLOY_CONFIG` skeleton (frame/blueprint/hive 메타) + cmd_deploy stub. plan SSOT: `/Users/axe/customer-deploy-generalization-plan.md`. 다음 세션 entry = `/Users/axe/.axe/NEXT_SESSION.md` §0-bis Phase 1.2~3 |
| 2026-05-25 06:50 | docs+axe-cli+infra | (다수) | **realchoice D-day execution 진입 (in-progress)** — RE^6 (D-day 즉시 시작 피벗) + RE^7 (운영자 사전 점검) + TXT 등재 (`MS=ms12037986`) + JSON pack 수신 + `axe customers ingest realchoice --apply` ✅ (vault 3 secret + customers.yaml fill) + `axe onboard realchoice --apply` step 1-13 ✅. axe CLI line 2588 step 12 fix (`security find -w` → metadata-only) 적용. 발견 6 함정 (`B-onboard-d-day-traps-2026-05-25`): Tailscale alias resolver / SSH non-login PATH / TXT+CNAME 공존 / keychain partition 격리 / start-frame.sh wrapper fetch. **step 14 차단** — Truvia 회신 대기 (옵션 A = 직접 실행 / 옵션 B = keychain ACL partition-list 변경). 핵심 entry = `/Users/axe/.axe/NEXT_SESSION.md` §0-bis |
| 2026-05-25 10:00 | docs | (다수) | **Truvia D-7 RE^4 회신 처리** — payslip Phase 3 deferral / 외부 회계법인 별도 회신 (`B-frame-cross-check-workflow` 신규) / macmini 이진우 자택 IP 동일 (`B-realchoice-tailscale-onboard` 신규) + `B-frame-lpm-classify` ETA 3 단계 명시 (D+90 minimum viable / D+120 rule-pre-classifier / 2026-12-01 stable) + `/services/frame` 에 **신규 customer 1 차 사이클 runbook** 신설 (D-day ~ D+30 의 chart auto-seed → ingest → trial balance → payroll 매칭 → 수작업 분개 → 회고 순서). Truvia D+30 사이클 effort 산정 명확화 (200~500 건 분개, 1 인 2~5 일/월) |
| 2026-05-23 21:00 | axe-cli+docs | (axe CLI 미관리) | **`axe customers ingest <id> <pack.json>` CLI 신설 (B-onboard-azure-pack ✅)** — axelabs-bootstrap/v1 schema 검증 + customers.yaml fill (ruamel round-trip, comment 보존) + services 매니페스트 4 슬롯 + vault push × 3 묶음. dry-run 기본. realchoice 가상 pack 으로 모든 plan 출력 검증 + 3 에러 path (bad schema / customer mismatch / unknown block) 검증. customer-onboarding.mdx 의 D-day 명령 흐름이 secret push × 3 → ingest 1 명령으로 축소. 트루비아 RE^2 §8 즉시 착수 요청 완료. axe CLI 변경 (`/Users/axe/.axe/bin/axe` cmd_customers_ingest + INGEST_MANIFEST_TEMPLATE + REQUIRED_PKGS += ruamel.yaml>=0.18) 은 git 미관리 — axe-backup 자동 보존 |
| 2026-05-23 20:30 | docs | (다수) | **realchoice 측 RE^2 합의 반영 + 운영자 측 5/25 D-7 약속 docs 등재** — `D-magnet-tenant-map-1` (customers.yaml service_tenant_map 신설, magnet RLS tenant_id ↔ AXE customer ID 매핑 SSOT) + `D-nemotron-1` (`/services/nemotron-personas` placeholder, D+14 라이선스 회신 대기) + `B-frame-lpm-classify` priority 상향 (RE^2 Q7: 2026 4Q 병행 운영 수작업 분개 risk) + backlog 5 신규 항목 (`B-realchoice-d7-checklist`, `B-realchoice-d-plus-checklist`, `B-magnet-tenant-env-injection`, `B-nemotron-catalog-promote`, `B-operator-bus-factor`). 7 D 결정 confirm + 8 Q confirm + cfo@realchoice.co.kr 신설 합의. D-7 (5/25) 트루비아 측 회신 대기 3 항목 (Hive 발송 도메인 / 호수회계법인 cross-check / macmini IP) |
| 2026-05-23 19:30 | docs | [`d0590e7`](https://github.com/) | **운영 주체 표기 = 액스코퍼레이션 주식회사 + 컨테이너 이름 컨벤션 명시** — narrative 9 페이지 (index/glossary/partner/* /ops/inventory/secret-rotation) 의 "강수훈" 인명 + "AXE LLC" → "액스코퍼레이션 주식회사 (axec entity)". customers.yaml axe.legal_name 정정. `/partner/deploy` 에 도입 후 macmini 컨테이너 구성 도식 + 3 패턴 (customer-prefix / customer-agnostic / historical axe- prefix) 신설. `B-container-name-customer-prefix` 등재 — Truvia RE 측 도식 의문 직접 답변 |
| 2026-05-23 19:00 | docs | [`d91e0bf`](https://github.com/) | **landing role-router callout** — docs.axelabs.ai URL 단독 송부 시 customer IT/직원/운영자 3-path 즉시 분기 가능. hero 다음 표 추가 + Quick Links 의 customer 항목을 partner entry 로 교체. 4-link 묶음 송부 의존 폐기 |
| 2026-05-23 18:30 | docs | [`0861d73`](https://github.com/) [`101fa0d`](https://github.com/) | **D-onboard-bootstrap-publish** — `axelabs-bootstrap.sh` (17749B, SHA-256 `7d2d607...`) 를 `https://docs.axelabs.ai/axelabs-bootstrap.sh` raw 노출. partner/registration §Option A self-contained + partner/macmini-prep 신설 + partner/domain-prep §A/§B + partner/handoff JSON pack. customer IT 가 docs link 만으로 자력 완료 가능 — 별도 안전채널 메시지 (`realchoice_entra_id_setup_v4.md`) 의존 폐기 |
| 2026-05-23 18:00 | docs+axe-cli+infra | (다수) | **Phase 1/2 contributor platform 세션** — D-bp-entity-17 (EntityRole + hive/frame OIDC 연동) 3 PR merge/ship + D-frame-fund-ksme-policy-check (axe_ia_001 좀비 fix) + D-dev-platform-1~6 (multi-user dev access · axe customers add/github-team/vault-bootstrap CLI · axe-labs-ai GitHub identity · Cloudflare Zero Trust App · axe vault unlock Keychain-backed bw session) + D-host-setup-1 (`/ops/host-setup` 13 layer SSOT 신설). 강태훈 Teams 회신 4건. 함정 +5건 (PTY exhaustion · Fine-grained PAT Resource owner · gh CLI keyring stale · bw subprocess BW_SESSION env 누락 · Vault session idle timeout). backlog +10 항목 (axe host inventory/bootstrap CLI · pat rotation cron · 2FA · pty-max launchd · customer deploy · user add 등). 강태훈 SSH pubkey + GitHub username 회신 대기 |
| 2026-05-23 11:30 | docs | [`a0c06f9`](https://github.com/) | **박스 정렬 함정 4번째 영구 차단** — Sarasa Bold @font-face 제거 (Cloudflare 503 영구캐시 fix) + `verify-box-alignment.mjs` (Playwright origin 측정) + `axe ship docs` 자동 통합 + sync-axe-ui 가 woff2 url 에 `?v=<SHA>` 부착 (브라우저 폰트 캐시 무효화). 4 layer 누적 차단. [known-gaps](/ops/known-gaps) 분석 등재 |
| 2026-05-23 11:00 | axelabs+blueprint+artemis+docs | [`a4d8b7e`](https://github.com/) | **@axe/ui v0.3.2 + 3 소비자 배포** — 43+ 컴포넌트 (DataTable/Pagination/Chart/AlertDialog/Accordion/DropdownMenu/EmptyState/ErrorBoundary/StatusBanner/Tree/Timeline/MasterDetail/ResponsiveTabs/MessageWithSources/TypingIndicator/Code/Section/Hero/Footer/Splitter/usePolling/useEventSource/useScrollSpy) + Perf P0/P1 (sideEffects · overrides · optimizePackageImports · Fontshare 비차단) + QA P0 7 + P1 11 fix. Blueprint dogfood — native `confirm()` → `AlertDialog` (SkillsClient.tsx, +53/-3). 모두 production 안정 |
| 2026-05-23 10:00 | infra | [`bfc50ce`](https://github.com/) | **D-ops-35** — `axe deploy hive {customer}` subcommand 신설 (frame blue/green 패턴 1:1 mirror, 8-step). axe `--apply` 실 검증: blue:3810 → green:3811 active 무중단, edge health 200. hive 가 `axe ship hive` 의 manual_hint 만 남아있던 격차 해소. realchoice 6/1 deploy 의 step 4 manual ssh 폐기. axe CLI 변경 (`/Users/axe/.axe/bin/axe`) 은 git 미관리 — axe-backup snapshot 으로 보존 |
| 2026-05-23 09:10 | docs | [`74616be`](https://github.com/) | Ship Log + Highlights — 5/22~23 Vault end-to-end (D-ops-24~33) narrative 등재 (다른 세션 docs ritual) |
| 2026-05-23 08:57 | docs+infra | [`3e75e83`](https://github.com/) | `axe secret send` CLI 신설 — 매니페스트 lookup → bw GET → bw send 파이프. stdin 주입 (argv 노출 0) + locked-vault pre-check. 옵션 `--to`/`--days`/`--access`/`--password`/`--customer`. 운영자 → customer IT 안전 secret 전달 채널 (anonymous one-time URL) |
| 2026-05-23 09:00 | docs+infra | [`7988028`](https://github.com/) | **D-ops-33** — `axe vault bootstrap {customer} [--apply]` subcommand 신설. D-ops-24/26/27 4-key env 패치를 코드로 항구화 (수동 4-block → 1 command). Idempotent + dry-run default. axe 검증 ("bootstrap 불필요" detect) + realchoice dry-run (file 부재 깔끔 에러). runbook customer-onboarding.mdx D+1 섹션 1-command 화. `B-onboard-cli-vault-bootstrap` env 패치 부분 ✅ |
| 2026-05-23 08:42 | docs | [`4c12081`](https://github.com/) | runbook customer-onboarding.mdx: D-ops-24~32 lessons codified — D+1 Vault 부트스트랩 4-block 섹션 + 함정 표 6건 추가. `deploy-new-entity.sh` 일반화 (customer-agnostic) + `B-realchoice-deploy-prep` backlog |
| 2026-05-22 22:30 | infra | _pending_ | **D-ops-31 deploy 완료** — axep PII passphrase 2개 vault push + frame blue/green swap (active=green:3711) + hive sequential force-recreate. edge frame/hive health 200, axec/axev 영향 0. 자동화 스크립트 `/Users/axe/.axe/vault/deploy-axep.sh`. 부수 함정 등재: `axe secret push` 가 BW_SESSION env 무시, macOS Keychain (`axe.vault.session`) 만 읽음 |
| 2026-05-22 21:55 | docs | f1f87bc | **Teams bot integration spec 신설** ([blueprint.mdx](/services/blueprint)) — `## Teams bot integration` section: agent identity (ai@/cfo@) · inbound 처리 흐름 · 첨부 처리 contentType 표 (reference / inline image / messageReference / unhandled) · reply 안전 정책 (sanitizer / silent-drop / in-place edit). [Blueprint PR #372](https://github.com/soohunkang/blueprint/pull/372) (`messageReference` 첨부 본문 fetch fix — 봇 false-negative 제거) 의 docs-first anchor. backlog 2건 (`B-bp-teams-context-msgref` + `B-bp-teams-attachment-contenttype-audit`) + known-gaps Blueprint 섹션 등재 동반 |
| 2026-05-22 17:50 | docs+infra | _pending_ | D-ops-31 + D-ops-32 — axep entity 신설 (액스파트너스 유한책임회사, frame+hive register-entity 적용) + customers.yaml entities 배열·PII secret·user_entity_map 갱신 + Vault collection v1 구조 6-collection 설계 (Platform-Service/Platform-Infra/AXEC/AXEV/AXEP/Shared). 후속: PII passphrase 2개 push + frame/hive ship + collection web UI 마이그레이션 |
| 2026-05-22 16:40 | docs | _pending_ | D-ops-29 + D-ops-30 — dual-identity (`ai@` automation / `soohun.kang@` human Owner, 둘 다 vault Owner access_all=1) + Blueprint `/api/admin/broadcast-dm` endpoint 추가 (operator broadcast 1:1 DM, fan-out from cron-failure-alert pattern) |
| 2026-05-22 16:00 | docs | _pending_ | D-ops-28 — bw CLI 2025.7.0 다운그레이드 (Timshel 1.34.1-6 ↔ CLI 2026.x `toWrappedAccountCryptographicState` crash 우회) + 한진우/강태훈/강수훈 AXE org member 4명 invite + confirm 완료 (자동화 `invite-members.sh`) + 업스트림 vault 1.36.0 native SSO 마이그레이션 backlog |
| 2026-05-22 15:00 | blueprint | _pending_ | D-bp-entity-16 — admin role 자동 sys entity 포함. hydrate 가 customers.yaml 의 explicit list 뒤에 sys append (admin 전용 가시성, 일반 user 403 유지) |
| 2026-05-22 14:30 | blueprint | _pending_ | D-bp-entity-14 — /axe/usage entity scope. UsageLog → Session → Workspace.entityId 경로로 axec/axev 비용 분리. workspace 미존재 = sys |
| 2026-05-22 14:00 | blueprint | _pending_ | D-bp-entity-15 — switch-account ownership 검증을 authenticatedUserId 기준으로. impersonated session 의 sibling switch 403 silent fail 버그 해소. selectAccount 에러 노출 |
| 2026-05-22 13:30 | blueprint | _pending_ | D-bp-entity-13 — EntitySelector 도 button + popover (AccountSwitcher 패턴 미러). UI 일관성 + slug chip 표시 |
| 2026-05-22 13:00 | blueprint | _pending_ | D-bp-entity-12 — TopNav 사용자 이름이 AccountSwitcher trigger (M365/Gmail 패턴). 별도 `<select>` 폐기, button + popover, click-outside + Escape close |
| 2026-05-22 12:40 | blueprint | _pending_ | D-bp-entity-11 — "전체 entity" 폐기 (PR #360 + #361). 항상 specific scope 강제, fallback chain URL → localStorage → defaultEntity → scopes[0] |
| 2026-05-22 12:30 | blueprint | _pending_ | D-bp-entity-10 — AccountSwitcher 항상 노출 + `+ 다른 계정으로 로그인` (PR #358 + #359 hotfix) |
| 2026-05-22 11:30 | docs | _pending_ | D-ops-27 — Vaultwarden operator setup 마무리: `SSO_ONLY=false` 유지 (emergency MP fallback) + `ORGANIZATION_INVITE_AUTO_ACCEPT=true` (멤버 초대 흐름 단순화) + backup verify (snapshot `9c2eb955` 에 vault data 포함) |
| 2026-05-22 10:10 | docs | _pending_ | D-ops-26 — Vaultwarden JIT user provisioning 활성 (`SIGNUPS_ALLOWED=true`). 신규 employee 의 "Failed to retrieve the invitation" 차단 해소 |
| 2026-05-22 09:25 | docs | _pending_ | D-ops-24 — Vaultwarden SSO + Entra ID `email_verified` 면제 (`SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION`) + `/vault/#/sso` 직링크 안내 |
| 2026-05-22 12:50 | docs | [`21d815a`](https://github.com/) | build 산출물 sync (axe-ui VERSION + llms.txt) — ship working tree check 통과용 |
| 2026-05-22 12:48 | docs | [`ac4f52e`](https://github.com/) | architecture/axe-ui 페이지 신설 — @axe/ui 적용 5분 절차 + light/dark 토글 + 함정 표 |
| 2026-05-22 12:30 | docs | [`21042ac`](https://github.com/) | B-search-deploy ✅ + 본 chapter ship 7건 Ship Log 등재 |
| 2026-05-22 11:55 | docs | [`ce4dc18`](https://github.com/) | troubleshooting AADSTS7000215 — frame MCP Advanced 칸 비워야 (D-ops-15.5) |
| 2026-05-22 10:11 | docs | [`f520d3a`](https://github.com/) | D-ops-26 — Vaultwarden JIT user provisioning 활성 |
| 2026-05-22 08:48 | docs | [`4d7aed8`](https://github.com/) | alpine builder 에 `apk add git` (changes.json 빈 응답 진짜 fix) |
| 2026-05-22 08:46 | docs | [`b441a97`](https://github.com/) | .git 을 builder stage 에 포함 (changes.json 빈 응답 1차 fix) |
| 2026-05-22 08:42 | docs | [`564aa61`](https://github.com/) | auth/troubleshooting 보강 + docker-compose.yml repo 화 |
| 2026-05-22 08:40 | docs | [`c8f8544`](https://github.com/) | .claude/ ignore (claude code per-project local config) |
| 2026-05-22 08:37 | docs | [`eed16f3`](https://github.com/) | /ops/updates 신설 + /api/changes JSON feed (시간축 4-페이지 분리 완성) |
| 2026-05-22 08:21 | docs | [`49dc3ad`](https://github.com/) | D-bp-entity-3 — General bucket 제거 + sys entity 도입 |
| 2026-05-22 08:10 | docs | [`9c13bcc`](https://github.com/) | Pagefind 자산 cache-control 60s (s-maxage) — 옛 응답 캐시 잔존 회피 |
| 2026-05-22 01:49 | docs | [`3de1434`](https://github.com/) | Pagefind 검색 + roadmap/backlog 신설 + mdx ?metadata 함정 17 위치 정리 |
| 2026-05-22 01:35 | docs | [`7984aa7`](https://github.com/) | D-bp-alert-1 — operator alert AXE-native (Slack 폐기) |
| 2026-05-22 01:16 | docs | [`437cd5e`](https://github.com/) | D-ops-22 — frame 펀드 도메인 지원 (KIP/KVF, shared schema 확장) |

---

## Highlights

> 큐레이션. 의미 있는 변경만, narrative. 직원·외부 IT 가 "지난 한 달 무엇이 새로 생겼나" 5분 안에 파악.
>
> 등재 절차: 운영자가 1-2 주에 한 번, Ship Log 와 backlog ✅ 항목을 검토하고 narrative 한 단락 작성.

### 2026-05-22 ~ 23 — Vault end-to-end 셋업 + axep entity 신설 + customer 일반화

axe customer 의 Vaultwarden 을 6명 (operator 4 + 2 dual-identity) 사용 가능 상태로 본격 셋업. 첫 employee SSO 시도부터 5 시리얼 함정 해결 → 결정 9 건 ([D-ops-24](/ops/decisions) ~ [D-ops-33](/ops/decisions)):

- **D-ops-24** Entra ID id_token 의 `email_verified` claim 부재 → Timshel fork 거부 → `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION=true`
- **D-ops-26** `SIGNUPS_ALLOWED=false` 가 JIT user 생성 차단 → "Failed to retrieve the invitation" → `SIGNUPS_ALLOWED=true`
- **D-ops-27** `SSO_ONLY=false` 유지 (Entra 장애 emergency MP fallback) + `ORGANIZATION_INVITE_AUTO_ACCEPT=true` (직원 Accept 자동)
- **D-ops-28** bw CLI 2026.4.1 ↔ Timshel 1.34.1-6 호환 미스매치 (`toWrappedAccountCryptographicState` crash) → CLI 2025.7.0 다운그레이드. 항구 해소는 `B-vault-upstream-migration` (dani-garcia/vaultwarden:1.36.0 native SSO)
- **D-ops-29** dual-identity 패턴 (`ai@` automation / `soohun.kang@` human Owner) — bot/human sender 혼동 회피
- **D-ops-30** Blueprint `/api/admin/broadcast-dm` endpoint — operator broadcast 1:1 Teams DM (vault onboarding 안내 3명 발송 검증)
- **D-ops-31** axep entity 신설 (액스파트너스 유한책임회사) — frame+hive register-entity + customers.yaml + PII passphrase 2개 + frame blue/green + hive sequential. axec/axev 무중단 검증
- **D-ops-32** Vault collection 구조 v1 종합 설계 (6-collection: Platform-Service/Platform-Infra/AXEC/AXEV/AXEP/Shared, entity 1개 customer 는 4-collection 변형)
- **D-ops-33** `axe vault bootstrap {customer} --apply` CLI 신설 — D-ops-24/26/27 4-key 적용 자동화. realchoice 6/1 deploy 가 axe 의 5/14~22 시리얼 함정 자동 회피

부수 발견 함정 2건: (a) `axe secret push` 가 `BW_SESSION` env 무시하고 macOS Keychain (`axe.vault.session`) 만 읽음 — 자동화 스크립트가 keychain 갱신 통합, (b) MDX acorn 파서가 backtick 안 `${VAR}` 와 `<placeholder>` 도 JSX 로 파싱 — D-ops-30 decision row 작성 시 2회 build fail.

산출 스크립트: `/Users/axe/.axe/vault/invite-members.sh` (org member invite 자동), `/Users/axe/.axe/vault/deploy-axep.sh` (PII push + ship), `/Users/axe/.axe/vault/deploy-new-entity.sh` (customer-agnostic 일반화), `axe vault bootstrap` (subcommand).

### 2026-05-22 — docs.axelabs.ai 검색 + 운영 ritual 4-페이지 분리

`docs.axelabs.ai` 의 우상단 검색박스가 처음부터 동작 안 했음 (Nextra v4 의 검색이 Pagefind 정적 인덱스 기반인데 빌드 스크립트에 단계 누락). 본일 fix + 라이브 배포 — 4 함정 시리얼 해결: ① Pagefind build 단계 누락 / ② Nextra dev `?metadata` 의 acorn 파싱이 backtick 안 `<placeholder>` 와 `${VAR}` 까지 잡는 함정 (17 위치 plain text ASCII 로 정리) / ③ `git commit 누락 → 옛 image ship` (commit-before-ship ritual) / ④ Cloudflare `max-age=14400` 옛 404 응답 4시간 캐시 (`s-maxage=60` 명시로 미래 회피). 검색 라이브 동작 검증: `cf-cache-status: HIT`, 45 KB.

동시에 운영 흐름의 entry point 가 [`known-gaps`](/ops/known-gaps) 단일 페이지에 누적되어 다른 세션이 "무엇부터" 가 안 보이던 문제 해소 — 시간축 4-페이지 분리:

- [`backlog`](/ops/backlog) (현재) — 실행 큐 lifecycle 🆕→📋→🔧→✅
- [`roadmap`](/ops/roadmap) (미래) — M1~M5 마일스톤 큰 그림
- **본 페이지** (과거) — Ship Log + Highlights + API feed
- [`known-gaps`](/ops/known-gaps) (사실) — 함정·미해결

또한 본일 후반 `/api/changes` JSON endpoint 신설 — `scripts/generate-changes-json.mjs` 가 build 시점 git log → `public/changes.json` export. `cache-control: s-maxage=60` 으로 ship 마다 60초 안에 fresh. LLM agent 가 `curl https://docs.axelabs.ai/api/changes?since=YYYY-MM-DD` 로 변경 fetch 가능. 본 endpoint 도입 중 두 추가 함정 발견: ⑤ `node:22-alpine` 의 `git` 바이너리 미포함 (apk add 필요) / ⑥ 같은 macmini 의 compose project 분리 시 container 이름 충돌 (`docker rm -f` cleanup 필요).

관련 결정: [D-docs-search-1](/ops/decisions), [D-docs-roadmap-1](/ops/decisions), [D-docs-updates-1](/ops/decisions).

### 2026-05-21 ~ 22 — frame 펀드 도메인 + Blueprint entity·PARA dispatch + hive payroll v2

- **frame 펀드 회계** ([D-ops-22](/ops/decisions)): `shared.entity` 에 `entity_kind` (corporate/kip/kvf) + `fund_meta` JSONB. AXEV 산하 KIP/KVF 조합 회계 처리 가능. K-IFRS 1110 통제 미달 (운용 관계 — parent-child 아님) 명시
- **Blueprint entity 도입** ([D-bp-entity-1](/ops/decisions), [PR #339](https://github.com/) + [#341](https://github.com/)): Workspace 에 `entityId` FK + `paraLayer` enum
- **PARA dispatch sub-consensus** ([D-bp-entity-2](/ops/decisions)): copy-with-provenance (sourceWorkspaceId/sourceArtifactPath/copiedAt). UI 는 PR 5 예정
- **sys entity 도입** ([D-bp-entity-3](/ops/decisions), [PR #344](https://github.com/) + [#345](https://github.com/)): `Workspace.entityId` nullable → NOT NULL. ad-hoc / 시스템 row 는 `sys` entity. General bucket 본질 제거
- **hive payroll v2** ([D-hive-21](/ops/decisions) ~ [D-hive-26](/ops/decisions) + [D-frame-1](/ops/decisions)): 한국 도메인 본질 7가지 (간이세액표 / 비과세 / 보수월액별 / 부양가족 / 정산 / 일할 / 보험별 라운딩). 분개 trigger = 실 거래 (matching principle) — D-frame-1 의 pending_payroll + match_pending_sweep 흐름
- **D-bp-alert-1**: Blueprint silent-drop L2 operator alert. AXE-native (Slack 폐기, `[OPERATOR-ALERT]` 마커 tail → macOS notification)

---

## API feed

LLM agent / 외부 시스템이 시간순 변경 사항을 JSON 으로 받는 endpoint:

```
GET /api/changes
GET /api/changes?since=2026-05-01
GET /api/changes?limit=20
GET /api/changes?since=2026-05-01&limit=50
```

응답 (예시):

```json
{
  "site": "https://docs.axelabs.ai",
  "since": "2026-05-01",
  "total": 5,
  "changes": [
    {
      "commit": "49dc3adb",
      "date": "2026-05-22T08:21:48+09:00",
      "subject": "docs(decisions): D-bp-entity-3 — General 제거 + sys entity (#344+#345)",
      "url": "https://docs.axelabs.ai/ops/decisions"
    }
  ]
}
```

`since` 는 ISO 8601 또는 YYYY-MM-DD. `limit` default 30, max 100.

본 endpoint 는 git log 기반 — `git log --format=...` 을 build 시점이 아닌 **request 시점** 에 실행. 캐싱 없음 (변경마다 즉시 반영).

LLM 사용 예: 다른 agent 가 자기 컨텍스트 갱신할 때 `curl https://docs.axelabs.ai/api/changes?since=$(date -v-7d +%Y-%m-%d)` 로 지난 7일 변경 fetch.

---

## 운영 ritual

### Phase 1 (현재) — 수동

매 `axe ship SERVICE` 후:

1. 본 페이지의 **Ship Log** 표에 한 줄 추가
   - 형식: `| 2026-MM-DD HH:MM | SERVICE | [SHORT-HASH](url) | COMMIT-SUBJECT |`
2. backlog 의 ✅ done 항목 검토 → 의미 있는 것은 본 페이지 **Highlights** 에 narrative 한 단락
3. 1-2 주에 한 번 — Ship Log 의 의미 있는 항목 묶어서 Highlights 갱신

### Phase 2 (계획) — 완전 자동

`axe ship` 의 post-deploy hook 이:
1. 본 페이지의 Ship Log 표 첫 행에 commit 정보 자동 append
2. backlog 의 `🔧 in-progress` 중 ship 한 service 의 related 항목을 ✅ done 으로 자동 이동
3. ✅ done 1주 후 본 페이지 Ship Log 로 자동 archive

구현 = [`B-axe-ship-update-hook`](/ops/backlog) (Phase 2).

## 본 페이지의 의도

[backlog](/ops/backlog) 와 [roadmap](/ops/roadmap) 은 "다음/미래" 의 시점. 본 페이지는 **이미 한 일** 의 정직 기록. 의도는 3 가지:

- **회고** — "지난 5번 ship 중 어디서 문제 났나" 운영자가 5초 안에
- **공유** — 직원·외부 IT 가 "최근 변경" Highlights 로 narrative 따라가기
- **자동 연동** — LLM agent 가 `/api/changes` 로 정기 polling
