Overview

Note: This page is reproduced verbatim from the project's Korean-language source documentation. No English version of this document exists in the source repository yet — only the top-level README has an English translation.

System Architecture, Security, and Persistence

English summary: known limitations#

  • On macOS, if sysinfo can't read the full cmdline, processes are grouped by name (possible over-grouping).
  • If the CLI dies via Ctrl-C during cys run, group cleanup falls to the watchdog cycle (5s).
  • Real-time GPU/NPU in Control Center is currently macOS (Apple Silicon) only — Windows shows CPU/MEM only. NPU has no utilization-% public API, so actual power (W) is shown instead.
  • Single-UID trust model — approval signing and self-approval blocking are a detection/fail-safe layer, not a cryptographic defense against a malicious process inside the same account.
  • The mission gate cannot cryptographically stop same-UID forgery — it is handled as a delivery-ledger audit trail.
  • The Windows upgrade-atomicity repair has gone as far as code review and model verification on a Mac dev machine; real-hardware confirmation is in progress.
  • The macOS build is unsigned — the installer helper lowers friction, but a first-run warning can still appear, and "half-install vs. quarantine" is disambiguated with cys doctor app-seal.
  • Radio cannot in principle guarantee cross-channel exactly-once delivery or a zero-miss window — an acknowledged, managed residual risk, not a bug to be fixed.

5. 시스템 아키텍처#

5.1 컴포넌트 지도#

┌─────────────────────────────── 한 저장소, 한 배포 ───────────────────────────────┐
│                                                                                │
│  cys.app   Tauri 2 데스크톱 앱 — 터미널 UI(xterm.js) + Control Center.          │
│            데몬의 thin client. PTY를 소유하지 않으므로 앱이 죽어도 세션 생존.       │
│                                                                                │
│  cysd      헤드리스 코어 데몬 — NDJSON 소켓 서버(UDS / named pipe), PTY 소유      │
│            (portable-pty: openpty·ConPTY), vt100 화면 재구성, 이벤트 버스,        │
│            watchdog·프로세스 원장, 사용량/비용 수집, SQLite 영속 분석, 스케줄러     │
│                                                                                │
│  cys       CLI — pane 안의 AI가 쓰는 동등 노드 클라이언트 (60+ 서브커맨드)          │
│                                                                                │
│  pack      cysjavis-pack/ — 절대지침 10·결정론 도구 86·훅 31·스킬 114·스키마 4.   │
│            빌드 시 바이너리에 임베드, 배포 시 minisign 서명                        │
└────────────────────────────────────────────────────────────────────────────────┘

모든 pane 프로세스에 CYS_SURFACE_ID·CYS_SURFACE_REF·CYS_SOCKET이 자동 주입된다 — pane 안의 AI는 cys identify 한 번으로 자기 주소를 알고, 그 순간부터 소켓의 동등 노드다. "사람만 조종석에 앉는 터미널"과의 근본적 차이가 여기다.

5.2 cysd 데몬 내부#

모듈 (src/bin/cysd/) 역할
main.rs 진입점·accept loop·연결 핸들러·프레이밍·startup lock·자동 복원
handlers.rs RPC 디스패치(60+ 메서드)·발신자 신원 해소·ACL·능력 게이트
state.rs Surface(PTY) 수명주기·scrollback·역할 레지스트리·토폴로지·묘비·큐·헬스룰
governance.rs watchdog(5초)·고아 회수·중복 프로세스·에이전트 사망 감지·큐 배달
events.rs 이벤트 버스 — 단조 seq 링 + broadcast + 재시작 간 단조성 예약
usage.rs / cost.rs 사용량 수동 관측(트랜스크립트·쿼터)·모델 단가표
analytics.rs analytics.db(사용·이벤트·세션·변경 해시체인)
recall.rs transcripts.db(FTS 전문검색 + attest 해시체인 + 보존정책)
channels.rs Slack·Discord 브리지(원격 승인·수신·발신·lockdown)
schedule.rs 30초 tick 스케줄러(원샷·반복·missed-fire)
approval.rs HMAC signed-prefix 승인
deadman.rs hung 데몬 홀더 감지·안전 회수
hwmon.rs CPU 코어별·GPU·NPU·MEM 실시간 스냅샷

굵직한 견고성 장치: vt100 파서 패닉은 catch_unwind로 격리되어 그 청크만 버리고 리더는 불사(state.rs), watchdog tick·백그라운드 writer도 각각 패닉 격리, 응답은 8MB 상한 + round-trip 자기검증 프레이밍(와이어 무결성 이중 가드), 데몬 중복 기동은 소켓 연결 확인 + flock으로 거부.

5.3 프로토콜 — NDJSON, 한 줄 = JSON 하나#

요청  {"id":1,"method":"surface.send_text","params":{"surface_id":"surface:2","text":"..."}}
응답  {"id":1,"ok":true,"result":{...}} | {"id":1,"ok":false,"error":{"code","message"}}

RPC는 60여 개 + channel.* 13종, 이벤트는 90여 종이 흐른다(전수 목록은 User Manual §17). 서버→클라이언트 방향은 events.stream 푸시 스트림이며 시퀀스 번호로 재접속 이어받기가 된다 — 구독을 replay보다 먼저 등록해 갭을 막고, 밀리면(Lagged) 연결을 끊어 재접속 replay를 강제한다.

5.4 팩 실행 계층 — 지침을 집행하는 도구들#

팩의 bin/에는 결정론 도구 86종이 있다(표준 라이브러리·네트워크 0·LLM 호출 0이 기본). 오케스트레이션 한 사이클이 도구로 어떻게 이어지는지:

부트      javis_preflight --fix (존재·매핑·훅 검증 — exit code만이 사실)
          → javis_orchestra check (필수 노드 생존 판정)
라우팅    javis_route --request "…" (fast/deliberate/slow 3단 판정)
위임      javis_task checkout (원자적 체크아웃 — 충돌=exit 9, 선행 미해소=exit 4)
착수 게이트 javis_resource_gate check (서버·노드·load·컨텍스트 사전 차단)
실행 중   javis_event emit (닫힌 enum 이벤트) · javis_wakeup (코얼레싱 웨이크업 큐)
진행 보고  javis_report (todo 체크박스 산술 → 주기 push)
검증      javis_manifest check-criteria (기계 FLOOR) + javis_verdict (리뷰어 판정 스키마)
자율 전진  javis_orchestra gate-status (수렴 판정) → next-action (다음 액션 큐)
종료 게이트 javis_memory add (장기기억 증류 — 색인과 원자적 동기) · javis_adr add (결정 기록)
복원      javis_state_snapshot (세대 보관) · javis_phoenix (부활 저널·정직 상태 enum)

훅(hooks/, 31종)은 두 계급으로 명시 분리된다 — OBSERVABILITY(절대 차단 금지·항상 exit 0: 사용량 관측, statusline)와 GATE(deny-by-default·차단이 목적: 자율주행 guard, 역할 능력 게이트, 기획 선행 게이트). 보안 스캐너(javis_skillscan.py — 46 규칙, 스킬 정적 스캔 + 복원 주입 경로의 메모리 포이즌 스캔)와 MCP 거버넌스 게이트(javis_mcpgate.py — tool-poisoning·rug-pull 감지)가 공급망 방향을 지킨다.

스킬은 114종(skills/)이 실리며, 외부 유래 스킬은 커밋 핀 + 파일별 sha256 매니페스트 (skills/_VENDOR_MANIFEST.json)로 잠그고 skills/THIRD_PARTY.md에 귀속을 남긴다.

5.5 UI는 thin client다#

앱(src-tauri/ + ui/)은 데몬 소켓의 얇은 클라이언트다. 프런트엔드는 프레임워크 없는 순수 TypeScript + xterm.js(의존성 3개)이고, 빌드 산출물이 바이너리에 임베드된다. PTY는 데몬 소유이므로 앱을 재시작·재설치해도 세션은 살아 있고 재-attach만 한다. UI가 hang 이어도 소켓 제어 채널은 살아 있다(out-of-band 회생).

5.6 업데이트 아키텍처 — 이중 채널 + 스큐 교대#

채널 서명 방식
앱(바이너리) Tauri updater 서명 시작 + 6시간마다 확인 → ! 배지 → 세션 가드 → 설치·재시작 → 복원
팩(운영체계) minisign (공개키 바이너리 핀) 무중단 — 서명 검증 → 저널 트랜잭션 반영 → 라이브 노드 재주입. 재시작 0, 배지

팩 검증 사슬은 전건 fail-closed다: 필수 필드 → 채널 → 키링(폐기·미지·만료 거부) → minisign → 다이제스트 → 신선도 창 → replay 단조성(이미 수락한 것보다 오래된 팩 거부). tar 전개는 검증 후에만, in-Rust 하드닝 전개기(심링크·절대경로·경로 이탈 거부)로 수행된다 (src/packsig.rs, src/pack.rs).

플랫폼 재설치(rename-swap) 후 "디스크는 새 버전, 프로세스는 구 데몬"인 스큐가 남으면 UI가 "데몬 vX · 앱 vY — 세션 보존 중" 배지를 띄우고, 클릭 교대 또는 유휴 자동 교대(라이브 세션 0일 때만 — 무손실)로 데몬을 갈아끼운다(rotate_daemon).

5.7 채널 계층 — 함대를 메신저로 연결#

channels.rs는 Slack·Discord 브리지를 제공한다: 승인 요청·보고를 외부 메신저로 내보내고, 허가된 발신자의 원격 승인을 받아들인다. 신뢰 방향은 보수적이다 — 발신자 allowlist·원격 승인 별도 허가(allow-remote-approve)·잠금(lockdown)·모양 기반 redact(토큰·홈경로 차단)·중복/루프 억제가 내장된다.

5.8 free / pro 채널#

팩은 free(내장)와 pro(서명 라이선스로 활성화되는 오버레이) 두 채널을 가진다. 라이선스는 verify-only(서명 검증만, 발급 능력 없음 — src/license.rs)이고, 채널 상태가 손상되면 pro 콘텐츠를 내장 free 팩으로 덮지 않도록 보호된다(강등은 명시적 명령 pack-downgrade-to-free로만).


6. 보안 아키텍처#

위협 모델의 전제: 데몬은 네트워크 리스너가 없고, 같은 OS 사용자 계정 안의 로컬 프로세스들이 클라이언트다(단일-UID 신뢰 노드 모델). 그 안에서:

  1. 발신자 신원 = 커널이 말한다 — 연결마다 peer pid(macOS LOCAL_PEERPID, Linux SO_PEERCRED, Windows GetNamedPipeClientProcessId)를 조회하고 조상 프로세스 체인으로 소속 surface를 해소한다. 자기신고 role은 신뢰하지 않는다. pid 재사용은 start_time 대조로 무효화한다.
  2. 통신 정책acl.json의 role→role 규칙으로 stdin 주입을 게이트한다(예: 리뷰어→워커 deny). 타이핑 가드는 사람 입력 직후의 기계 주입 충돌을 막는다.
  3. 능력 게이트 — deny-by-default. 알 수 없는 역할은 능력 0.
  4. 승인은 사람 또는 서명 — 화면의 승인 프롬프트에 자동 응답하는 코드는 없다(HITL). 반복 위험 명령은 master가 HMAC-SHA256 signed-prefix로 1회 서명하면 guard 훅이 통과시킨다 (cys approval sign — master surface 전용, 상수시간 비교, 시크릿 0600 파일).
  5. 자기결재 차단 — 승인 요청을 올린 노드가 스스로 승인할 수 없다(pid/pgid/surface 각인).
  6. 공급망 — 앱은 Tauri updater 서명, 팩은 minisign 핀. 발행 전 비밀/PII 게이트 (scripts/secret-scan.sh --all, fail-closed)와 팩 전용 스캔이 CI 최우선 단계로 돈다.
  7. PIICYS_CONTROL_REDACT=1이면 세션 식별자를 해시로 가리고 집계만 보존.

정직한 한계의 명문화도 설계의 일부다: 단일-UID 모델에서 승인 서명·자기결재 정책은 "암호학적 보증"이 아니라 탐지·fail-safe 층임을 코드 주석이 스스로 밝힌다. 비밀 스캐너는 정적 패턴 매칭이라 난독화·신종 토큰을 못 잡는다고 명시한다. 한계를 숨기지 않는 것이 이 저장소의 문서 규약이다(README "알려진 한계" 섹션 상설).


7. 영속성과 부활#

  • 세션 영속 — PTY는 데몬 소유. UI 재시작·앱 재설치·업데이트에도 세션 유지.
  • 이벤트 연속성 — seq 단조 + 재시작 간 예약 블록으로, 재접속 클라이언트가 이어받는다.
  • 기록 영속 — 3개의 로컬 SQLite(analytics / transcripts+FTS / channels), 전부 WAL, 열기 실패 시 기능 저하로 우아하게 계속(관측이 본체를 죽이지 않는다).
  • 변조 증거성 — 전사 기록은 해시체인으로 이어지고, cys attest pin/verify로 외부 보관·사후 대조가 된다(producer≠evaluator의 기록 버전).
  • 부활(phoenix) — 상태 스냅샷은 세대 보관되고(javis_state_snapshot), 복원은 부활 저널 상태머신(javis_phoenix)이 수행한다. 복원 상태는 VERIFIED/UNVERIFIED/FAILED 정직 enum으로 보고된다 — "무출력=성공" 해석은 금지되어 있다. 크래시 루프에는 회로차단기가 걸린다. 복원 시 재주입되는 텍스트는 메모리 포이즌 스캔을 거친다(hooks/inject_gate.py).
  • 역할 조직 복원cys restore가 토폴로지 스냅샷의 죽은 역할들을 일괄 재기동·지침 재주입한다. 묘비(tombstone) 규약이 "사용자가 의도적으로 닫은 것"과 "죽어서 부활해야 하는 것"을 구분한다.

8. 자기개선 루프 (RSI)#

시스템은 자기 운영 경험을 자산으로 바꾸는 루프를 내장한다. 다만 측정 무결성이 루프의 전부라는 전제 위에서다(§3-②③⑤).

  1. 수집 — 훅이 반복 교정 신호를 감지해 후보로 적재한다(자동 적용 0, 후보일 뿐).
  2. 학습 5단계 — 제안 → 검색(citation 강제) → 추출(관찰 가능한 행동 주장으로 변환) → 평가(외부 채점·baseline 대비 실측) → 저장/하네스화 (javis_learn.py).
  3. 게이트rsi-gate.sh(fail-closed) + 디렉티브 회귀 트립와이어 (javis_directive_bench.py — 지침이 결함 행동을 실제로 금지하는지 결정론 채점).
  4. 가시화 — Control Center "학습" 탭에서 라운드 타임라인·채택/롤백·발견 누적을 본다.
  5. 영속 — 통과한 것만 스킬(cys skill)·장기기억(javis_memory)·결정기록(javis_adr) 으로 증류된다. "넘어진 사람이 팻말을 세운다" — 실패 경험이 스킬 주의칸으로 쌓인다.

9. 개발 방법론 — 이 저장소가 만들어진 방식#

이 저장소 자체가 위 철학의 산물이다.

  • AI 함대가 작성, 사람이 지휘 — 커밋의 Co-Authored-By 체인이 기록.
  • 클린룸 흡수 — 외부 오픈소스에서 배울 때 코드를 복사하지 않고 규칙·패턴을 표준 라이브러리로 재구현한다. 설계 참고는 NOTICE.md에, 벤더링(실제 코드 반입)은 커밋 핀 + 파일별 해시 매니페스트로 잠그고 귀속을 남긴다(skills/THIRD_PARTY.md, javis_cleanroom.py가 헤더·해시핀·카피레프트 게이트를 기계 검증).
  • 롤백 우선 — 기능은 격리 폴더에서 시작하고, 코드보다 복원 수단을 먼저 만든다.
  • 적대 리뷰 라운드 — 중요 변경은 서로 다른 모델 계열 리뷰어의 반박 라운드를 거친다.
  • 발행 게이트 — 비밀/PII 스캔(fail-closed) → 버전 SOT 검사 → 테스트 → 서명 → 실서명 실검증 폐포 게이트, 전부 CI가 강제한다(.github/workflows/release.yml).

10. 설계 불변식 (요약)#

  1. 데몬·PTY 리더·watchdog은 패닉에 죽지 않는다(격리·복구).
  2. 보안·서명·능력은 fail-closed, 관측은 fail-open, 통신 정책 부재는 fail-open.
  3. PTY·피드 원장·이벤트 seq는 단일 writer.
  4. 데몬 중복 기동은 거부된다.
  5. 의도적 닫힘(묘비)은 부활하지 않고, 죽음은 부활 대상이다.
  6. kill-switch(pause)는 큐·스케줄을 동결하되 직접 send는 통과한다 — "신경 차단"이지 행동 정지가 아니며, 재부팅에도 유지된다.
  7. 와이어 응답은 상한과 자기검증 프레이밍의 이중 가드를 거친다.
  8. 사용자 소유 파일(soul·디렉티브·CLAUDE.md·schedule)은 업데이트가 덮지 않는다.
  9. 페르소나 커스터마이즈는 허용되지만 안전핵(denylist·복구·kill-switch)은 잠겨 있다.

11. 더 읽기#


Back: Architecture & Philosophy · Overview

Was this page helpful?