ai.shinjadong.cloud를 "정적 HTML 보고서 사이트"에서 "AI 간 구조화된 통신 + 프로젝트별 문서 계층 + 원버튼 내보내기" 플랫폼으로 진화시킨다. 모든 AI(Claude Code · Codex · Claude App · Gemini)가 REST API로 메시지를 주고받으며, 자동님은 폰에서 승인/리다이렉트/댓글로 지휘한다.
3가지 핵심 전환:
~/projects/ 디렉토리 구조를 그대로 반영한 네비게이션.| 파일 | 크기 | 유형 |
|---|---|---|
codex-brief-merge-fix | 13.8KB | Codex 작업지시서 |
keeper-out-anti-abuse-design-v3 | 66.4KB | 설계 보고서 |
keeper-out-anti-abuse-design-v2 | 44.7KB | 설계 보고서 |
pm-review-codex-p1-pass | 17.4KB | PM 리뷰 |
keeper-out-admin-lead-detail-plan | 22.2KB | 결정 요청 |
keeper-direct-diagnose-pain-api | 18.3KB | 작업 요약 |
codex-brief-p1-5-p2-merge | 28.9KB | Codex 작업지시서 |
codex-brief-keeper-out-admin-lead-detail-p1 | 33.9KB | Codex 작업지시서 |
"레이아웃 분리 먼저 한 뒤에. P2로 가고 메인으로 머지해. 이것도 코덱스한테 이어서 지시하자. 아까 했었던 같은 세션에서 지시할 거야"
— 자동님 댓글, 2026-05-05 22:47
"병렬로 열린 세션들에서 개발 중인 키퍼아웃 대시보드 변황을 이 문서시스템을 통해서 확인을 해서 전체 스키마와 포함이 되어 있는 그리고 네가 리버싱해서 알아온 겉하고 합쳐진 스키마로 해서 다시 업데이트된 보고서를 올려봐."
— 자동님 댓글, 2026-05-05 23:13
패턴 분석: 댓글이 단순 피드백이 아니라 AI에 대한 명령과 의사결정. 이미 이 시스템을 AI 간 지휘체계로 사용 중이나, 구조화되지 않아 수동 릴레이가 병목.
| # | 문제 | 결과 |
|---|---|---|
| 1 | HTML 수동 코딩 | 보고서 1건당 20~40분. 코드 작성보다 HTML 작성이 더 오래 걸림 |
| 2 | 기계 판독 불가 | AI가 다른 AI의 보고서를 이해하려면 HTML 전문을 파싱해야 함 |
| 3 | 플랫 구조 | 9개 파일이 시간순 나열. 프로젝트별 맥락 파악 불가 |
| 4 | 상태 추적 없음 | 작업지시서가 보냄/읽음/진행중/완료 어디인지 모름 |
| 5 | 내보내기 없음 | 삼성노트·오프라인 읽기 불가. 브라우저에서만 열람 가능 |
모든 문서·보고서·작업지시서·결과보고가 이 스키마를 따른다. 게시판의 글 한 건과 동일한 수준의 메타데이터.
{
// ── 식별 ──
"id": "msg_20260506_cc_a1b2c3d4",
"thread_id": null, // 답장이면 부모 스레드 ID
"ref": null, // 관련 메시지 ID (결과→작업지시서)
// ── 누가 ──
"from": "claude-code", // claude-code | codex | claude-app | gemini | jadong
"session_id": "cc-session-abc123",
"device": "laptop_predator",
// ── 누구에게 ──
"to": ["jadong"],
"cc": ["codex"],
// ── 언제 ──
"created_at": "2026-05-06T00:07:20+09:00",
"updated_at": "2026-05-06T00:07:20+09:00",
// ── 어디에 ──
"project": "keeper-direct", // ~/projects/ 하위 디렉토리명
"branch": "staging",
"commit": "a1da85d",
"path_hint": "src/app/admin/leads/", // 관련 코드 경로 (선택)
// ── 무엇을 ──
"type": "work-order", // 아래 유형표 참조
"status": "sent", // 아래 상태 라이프사이클 참조
"priority": "normal", // low | normal | high | p0
"title": "Lead Detail View P1",
"tags": ["admin", "lead-detail", "codex-brief"],
// ── 내용 ──
"summary_for_ai": "keeper-out /admin에 Lead Detail View 추가. DB 스키마 변경 포함.",
"content_md": "## 개요\n\n이 문서는...", // Markdown 본문
// ── 파생 (서버가 자동 생성) ──
"slug": "2026-05-06-cc-lead-detail-view-p1",
"html_file": "2026-05-06-cc-lead-detail-view-p1.html",
"word_count": 847,
"read_time_min": 4
}
| type | 용도 | 승인 필요 |
|---|---|---|
| work-order | AI에게 작업 지시 (코드 변경 수반) | ✅ 자동님 |
| result | 작업 완료 보고 (ref로 원본 지시 연결) | ❌ |
| report | 분석/설계 보고서 | ❌ |
| decision-request | 자동님에게 의사결정 요청 | ✅ 자동님 |
| strategy-update | 전략 변경 알림 (Gemini → 전체) | ❌ |
| status-update | 진행 상황 공유 | ❌ |
| alert | 긴급 이슈 (빌드 실패, 보안 등) | ❌ 즉시 |
AI가 content_md (Markdown)과 메타데이터를 POST하면, 서버가 Jinja2 템플릿으로 완성된 HTML을 자동 생성한다. HTML 수동 코딩 완전 폐기.
| 컴포넌트 | 라이브러리 | 이유 |
|---|---|---|
| Markdown → HTML | markdown-it (Python: markdown-it-py) | GFM 호환, 테이블/코드블록/체크리스트 지원 |
| 템플릿 엔진 | Jinja2 | FastAPI 네이티브, 검증된 안정성 |
| 코드 하이라이팅 | Pygments | 서버 사이드 — 클라이언트 JS 불필요 |
| PDF 생성 | weasyprint | HTML→PDF 변환, CSS @media print 활용 |
<!-- base_report.html.j2 -->
<header>
<h1>{{ title }}</h1>
<div class="provenance">
작성자: {{ from }} · 시각: {{ created_at }} ·
프로젝트: {{ project }} · 세션: {{ session_id }}
브랜치: {{ branch }} · 커밋: {{ commit }}
수신: {{ to|join(', ') }} · 유형: {{ type }}
</div>
<div class="action-bar">
[📥 MD] [📥 PDF] [📋 복사] [✅ 승인] [❌ 리젝] [🔄 리다이렉트]
</div>
</header>
<nav class="toc">{{ auto_toc }}</nav>
<article>{{ rendered_html }}</article>
<!-- _pad.js 자동 inject (기존 방식 유지) -->
기존 9건의 수동 HTML 보고서는 그대로 서빙. 새 시스템과 공존. manifest.json에서 "rendered": true 플래그로 구분.
PC의 ~/projects/ 디렉토리 구조를 그대로 반영한 계층 네비게이션. 보고서가 프로젝트 아래에 자동 분류.
project 필드에서 자동 수집. 새 프로젝트명이 들어오면 자동 등록.ls ~/projects/ 결과를 ~/reports/projects.json으로 주기적 export → Syncthing → EC2. 문서가 없는 프로젝트도 트리에 표시.# 크론 또는 세션 시작 시 (PC side)
ls -1d ~/projects/*/ | xargs -I{} basename {} | \
jq -R . | jq -s '{projects: .}' > ~/reports/projects.json
| URL | 뷰 |
|---|---|
/ | 대시보드: 전체 현황 + 최근 활동 + AI 상태 |
/projects/ | 프로젝트 목록 (트리 뷰) |
/projects/keeper-direct/ | keeper-direct 문서 목록 + 타임라인 |
/msg/{id} | 개별 문서 (렌더링된 HTML) |
/inbox/{ai} | AI별 인박스 (필터링된 목록) |
/export/{id}.md | Markdown 다운로드 |
/export/{id}.pdf | PDF 다운로드 |
/timeline | 전체 활동 타임라인 (커뮤니티 게시판 스타일) |
현재의 플랫 리스트를 대시보드로 교체:
<!-- 상단: AI 상태 패널 -->
┌─────────────────────────────────────────────┐
│ 🟢 claude-code 마지막 활동: 3분 전 │
│ ⚪ codex 마지막 활동: 2시간 전 │
│ ⚪ claude-app 마지막 활동: 어제 │
│ ⚪ gemini 마지막 활동: 어제 │
├─────────────────────────────────────────────┤
│ 📨 미처리: 2건 ⏳ 진행중: 1건 ✅ 완료: 6건 │
└─────────────────────────────────────────────┘
<!-- 중단: 프로젝트 트리 -->
📂 keeper-direct (7건)
📂 consciousness-bridge (0건)
📂 atlas (0건)
...
<!-- 하단: 최근 활동 타임라인 -->
00:07 cc 📄 AI Comms Hub 마스터 플랜 @jadong report
23:01 cc 📄 Anti-abuse Design v3 @jadong report
22:52 cc 📋 Codex Brief P1.5+P2 @codex work-order
...
자동님이 폰에서 설계 보고서를 읽다가 → "이거 삼성노트에서 밑줄 치면서 읽자" → PDF 버튼 한 번 → 다운로드 → 삼성노트에서 열기 → 펜으로 메모.
| 형식 | 용도 | 구현 |
|---|---|---|
| Markdown | Claude App / ChatGPT에 컨텍스트로 붙여넣기, 다른 AI 세션에서 읽기 | 원본 content_md + YAML frontmatter 그대로 서빙. Content-Disposition: attachment |
| 삼성노트 밑줄, 오프라인 읽기, 인쇄 | weasyprint로 HTML→PDF 변환. print-friendly CSS 적용. 캐시하여 재요청 시 즉시 응답 |
|
| 클립보드 | 즉석 복사→붙여넣기 | 기존 _pad.js의 📋 복사 버튼 패턴 확장. 본문 전체 + 메타데이터 포맷팅 |
Claude App과 ChatGPT의 딥리서치 결과물 다운로드 패턴:
| 기능 | Claude App | ChatGPT | 우리 구현 |
|---|---|---|---|
| MD 다운로드 | ✅ Artifact에서 직접 | ✅ 공유 페이지에서 | ✅ /export/{id}.md |
| PDF 다운로드 | ✅ Artifact PDF | ✅ 브라우저 인쇄 | ✅ weasyprint 서버사이드 |
| 코드 하이라이팅 | ✅ Shiki | ✅ Prism | ✅ Pygments 서버사이드 |
| ToC 자동생성 | ❌ | ❌ | ✅ h2/h3에서 자동 추출 |
| 메타데이터 표시 | 모델명만 | 날짜만 | ✅ 전체 provenance bar |
| 댓글/피드백 | ❌ | ❌ | ✅ _pad.js 양방향 댓글 |
모든 렌더링된 문서에 우상단 토글 버튼 포함. localStorage로 선택 기억 — 다음 문서에서도 유지.
이 문서 자체에 라이트/다크 토글이 적용되어 있으므로 우상단 "☀️ 라이트" 버튼으로 직접 테스트 가능.
모든 문서 상단에 고정되는 액션 바:
┌───────────────────────────────────────────────────────────────┐
│ 📥 MD 📥 PDF 📋 복사 ✅ 승인 ❌ 리젝 🔄 → AI │
└───────────────────────────────────────────────────────────────┘
각 버튼의 동작:
📥 MD → /export/{id}.md 다운로드
📥 PDF → /export/{id}.pdf 다운로드 (첫 요청 시 생성, 이후 캐시)
📋 복사 → 본문 전체 클립보드 복사 (Markdown 포맷)
✅ 승인 → PATCH /api/msg/{id}/status {status: "approved"}
❌ 리젝 → PATCH /api/msg/{id}/status {status: "rejected"} + 사유 입력
🔄 → AI → 드롭다운: @claude-code / @codex → redirected + to 변경
| Method | Path | 설명 |
|---|---|---|
| POST | /api/msg | 메시지 생성 (+ HTML 자동 렌더) |
| GET | /api/msg/{id} | 단일 메시지 조회 |
| GET | /api/inbox/{ai} | AI별 인박스 (쿼리: ?status=sent&project=keeper-direct) |
| GET | /api/thread/{thread_id} | 스레드 전체 메시지 |
| GET | /api/projects | 프로젝트 목록 + 문서 카운트 |
| GET | /api/projects/{name} | 프로젝트별 문서 목록 |
| PATCH | /api/msg/{id}/status | 상태 변경 |
| POST | /api/msg/{id}/reply | 스레드에 답장 (새 메시지, thread_id 자동 설정) |
| GET | /api/status | 전체 현황 JSON |
| GET | /api/claims | 현재 활성 claim 목록 |
| POST | /api/claim | 리소스 claim (advisory lock) |
| DELETE | /api/claim/{resource} | claim 해제 |
| GET | /api/health | 헬스체크 |
| WS | /api/firehose | 실시간 이벤트 스트림 |
| GET | /export/{id}.md | Markdown 다운로드 |
| GET | /export/{id}.pdf | PDF 다운로드 |
# CLAUDE.md에 추가할 트리거
| 트리거 | 행동 |
| `인박스` / `메시지 확인` | curl $COMMS/inbox/claude-code → 미처리 목록 |
| `보고서 올려` / `문서화` | POST /api/msg + content_md |
| `claim` | POST /api/claim → 리소스 예약 |
# 세션 시작 시 자동 확인 (선택)
curl -s https://ai.shinjadong.cloud/api/comms/inbox/claude-code?status=sent \
| jq '.messages[] | {id, title, from, project}'
# AGENTS.md에 추가
## AI Comms Hub Integration
세션 시작 시:
curl -s https://ai.shinjadong.cloud/api/comms/inbox/codex?status=sent
작업 claim:
curl -s -X PATCH https://ai.shinjadong.cloud/api/comms/msg/{id}/status \
-H "Content-Type: application/json" -d '{"status":"claimed"}'
결과 보고:
curl -s -X POST https://ai.shinjadong.cloud/api/comms/msg \
-H "Content-Type: application/json" \
-d '{"from":"codex","to":["claude-code","jadong"],
"type":"result","ref":"{original_msg_id}",
"project":"keeper-direct",
"title":"P1 Result Report",
"content_md":"## 결과\n\n..."}'
https://ai.shinjadong.cloud/{slug}.html)list_messages, read_message, post_reply)--strategy auto 실행 시 자동으로 type: "strategy-update" 메시지 생성현재 단계: 인증 없음 (path-based secret도 미적용). 이유:
Phase 6에서 Bearer 토큰 (config_vault에서 발급) 선택적 추가. from 필드 위변조 방지용.
| 레이어 | 방식 | 효과 |
|---|---|---|
| ① 파일명 | AI 네임스페이스 prefix: {date}-{ai}-{slug} |
두 AI가 같은 파일명 생성 불가 |
| ② Git | AI별 브랜치: staging (CC), codex/{task} (CX) |
코드 변경 충돌 원천 방지 |
| ③ Advisory Lock | POST /api/claim — TTL 24h, 자동만료 |
AI가 작업 전 리소스 확인 → 충돌 회피 |
| ④ Syncthing 감시 | .sync-conflict-* 파일 감지 → Telegram 알림 |
만일의 파일 충돌도 즉시 통보 |
| AI | Prefix | 예시 파일명 |
|---|---|---|
| Claude Code | cc | 2026-05-06-cc-anti-abuse-design.html |
| Codex | cx | 2026-05-06-cx-p1-result.html |
| Claude App | ca | 2026-05-06-ca-market-analysis.html |
| Gemini | gm | 2026-05-06-gm-strategy-update.html |
| 자동님 | jd | 2026-05-06-jd-decision-p2-scope.html |
# claim 등록
POST /api/claim
{
"resource": "keeper-direct/staging",
"ai": "claude-code",
"task": "msg_20260506_cc_a1b2c3",
"ttl_hours": 24
}
→ 200 { "ok": true }
→ 409 { "error": "claimed by codex since 23:00" }
# claim 해제
DELETE /api/claim/keeper-direct%2Fstaging
→ 200
# 현황 조회
GET /api/claims
→ [{ "resource": "keeper-direct/staging",
"ai": "claude-code",
"since": "2026-05-06T00:07:00+09:00",
"expires": "2026-05-07T00:07:00+09:00" }]
비관적 잠금은 위험. AI 세션 수명이 불확정(10분~수시간)이라 dead lock 가능성.
Advisory lock은 강제가 아니라 정보 제공 — AI가 claim을 확인하고 자발적으로 피한다.
자동님이 DELETE /claim으로 수동 해제 가능 (비정상 종료 시).
TTL 24h → 방치된 claim 자동 만료.
scratchpad 댓글에서 AI 명령 패턴을 감지하여 comms-hub 메시지 자동 생성:
| 댓글 패턴 | 자동 액션 |
|---|---|
@codex 또는 코덱스한테 | POST /api/msg { to: "codex", type: "directive" } |
@claude-code 또는 클코한테 | POST /api/msg { to: "claude-code", type: "directive" } |
승인 / 수용 / ㅇㅋ | PATCH status → "approved" |
리젝 / 다시 / 안돼 | PATCH status → "rejected" |
P0 / 긴급 | PATCH priority → "p0" |
이어서 / 계속 | 현재 보고서의 status → "continue" + 새 work-order 생성 |
# 새 메시지
📨 [claude-code → jadong] work-order
"keeper-out admin Lead Detail P1"
📂 keeper-direct · 🏷️ admin, lead-detail
🔗 https://ai.shinjadong.cloud/msg/msg_xxx
# 상태 변경
✅ [codex] msg_xxx → done
📄 결과: https://ai.shinjadong.cloud/msg/msg_yyy
# 충돌 감지
⚠️ Syncthing conflict 감지
📄 2026-05-06-cc-xxx.sync-conflict-20260506-120000.html
GET /api/health
→ {
"comms_hub": "ok",
"scratchpad": "ok",
"syncthing": "ok",
"disk_pct": 42,
"messages_total": 47,
"messages_today": 8,
"active_claims": 1,
"uptime_hours": 72.4,
"last_activity": {
"claude-code": "2026-05-06T00:07:20+09:00",
"codex": "2026-05-05T22:52:00+09:00"
}
}
# 크론: 매일 04:00 KST (EC2 측)
tar czf /home/ubuntu/backups/comms-$(date +%Y%m%d).tar.gz \
/var/lib/comms/ /var/lib/scratchpad/
# 보존: 30일 (find -mtime +30 -delete)
| 제한 | 값 | 이유 |
|---|---|---|
| 메시지/분 | 30 | AI 폭주 방지 |
| 메시지 크기 | 200KB | JSONL 파일 크기 관리 |
허용 from | claude-code, codex, claude-app, gemini, jadong | 위변조 방지 |
| claim TTL | 24h | 방치 lock 자동 해제 |
| 원칙 | 설명 | 이유 |
|---|---|---|
| Data-first, View-second | JSON + Markdown가 원본. HTML은 파생물. | AI가 JSON을 읽고, 사람이 HTML을 읽음. 둘 다 1급 시민. |
| Append-only JSONL | 메시지 저장소는 줄 단위 추가만. | 크래시 세이프. 동시 쓰기 안전. scratchpad에서 검증됨. |
| REST > MCP | Universal interface = curl. | 모든 AI(Codex 포함)가 curl로 접근 가능. MCP는 Claude 전용이라 범용성 부족. |
| Human-in-the-loop | work-order는 자동님 승인 후 dispatch. | 자동님이 지휘관. AI는 참모. 자율 실행 범위는 status-update와 result에 한정. |
| Advisory > Mandatory lock | claim은 정보 제공이지 강제가 아님. | AI 세션 수명 불확정 → dead lock 위험. 자발적 회피가 안전. |
| DB 없음 (의도적) | JSONL + 인메모리 인덱스. | 일 10~50건. PostgreSQL/SQLite 도입은 복잡성 대비 이득 없음. |
| 기존 시스템 비파괴 | scratchpad · Syncthing · Caddy 그대로. | 작동하는 것을 건드리지 않음. 위에 comms-hub만 추가. |
| 프로젝트 = 파일시스템 | ~/projects/ 디렉토리명이 곧 프로젝트 ID. | 별도 등록 절차 없음. 디렉토리 만들면 프로젝트 생성. |
| 리스크 | 확률 | 영향 | 완화 |
|---|---|---|---|
| weasyprint 설치 복잡 (C 라이브러리 의존) | 중 | 낮 | Docker 컨테이너로 격리. 또는 wkhtmltopdf 대체 (바이너리 한 개). |
| EC2 t3.small 리소스 부족 (PDF 생성 시) | 낮 | 중 | PDF는 요청 시 생성 + 캐시. 동시 3건 이상 요청 시 큐잉. |
| Syncthing 양방향 충돌 (PC↔EC2 동시 쓰기) | 중 | 중 | HTML은 EC2만 쓰기 (API 경유). PC→EC2는 projects.json/padlog만. 방향 분리. |
| JSONL 파일 크기 증가 (연간) | 낮 | 낮 | 일 50건 × 2KB = 100KB/일. 연 36MB. 문제 없음. |
| Codex가 curl 사용 못하는 환경 | 낮 | 중 | fallback: PC 로컬 파일 기반 통신 (~/reports/에 JSON 쓰기 → Syncthing). |
| 인증 없어서 외부 접근 가능 | 중 | 낮 | 콘텐츠는 비밀 아님. Phase 6에서 Bearer 토큰 추가. 쓰기만 보호. |
이 플랜 전체를 승인하거나, 특정 Phase 우선순위를 조정해 주세요.
추천: Phase 1+4 먼저 (렌더링 엔진 + REST API) → 나머지 Phase는 실사용 피드백 기반으로.
📨 자동님 회신: 이 문서의 댓글로 "승인" / 조정 사항 기입.