본문으로 건너뛰기
5분 AI.
GITHUB TRENDING TYPESCRIPT WEEKLY #16 딥다이브 · 2026-10-23 분석

billion-context 딥다이브
— 오래된 대화는 접고, 필요한 원문은 다시 펼친다

프록시·플러그인

빠른 판단

무엇
오래된 대화를 계층 요약으로 접고 저장한 원문을 필요할 때 복원하는 컨텍스트 압축 프록시·플러그인
이럴 때
긴 코딩 세션에서 모델에 보여줄 문맥을 관리하면서 요약에서 빠진 원문을 다시 찾을 수 있게 할 때
입력
길게 누적된 에이전트 대화와 복원 요청
결과
계층 요약 문맥·보관 원문과 필요 구간 복원 결과
코딩 에이전트와 모델 API 사이에서 대화를 계층적 요약으로 바꾸는 컨텍스트 압축 플러그인입니다. 흥미로운 부분은 요약 문장보다 그 주변에 있습니다. 서로 다른 API를 같은 메시지로 다루는 방법, 압축한 원문을 복원하는 상태 설계, 프롬프트 캐시를 지키는 순서 규칙을 실제 TypeScript 코드로 살펴봅니다. 저장소: ranxianglei/billion-context · ⭐2,452 · 포크 210 · 최신 릴리스 v0.1.204 (2026-10-23 GitHub 기준) · 소스 커밋 fdbddd0 기준.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

모델의 기억 용량을 늘리는 대신, 매번 보여 주는 대화를 관리한다

billion-context는 오래된 대화 구간을 모델이 작성한 요약으로 접고, 필요하면 저장한 원문을 다시 꺼내는 도구입니다. npm 패키지 이름은 billion-context, 실행 명령은 bili이고, bili-proxy는 같은 진입점을 가리키는 별칭입니다.

수십억 토큰을 한 번에 모델에 넣는 것이 아니라, 작은 창 안에 남길 내용을 계속 고르는 시스템입니다. 제목의 큰 숫자는 장기간 세션에서 다룬 누적 입력량의 맥락으로 읽어야 합니다. 모델 자체의 컨텍스트 창이 커지거나, 요약만으로 모든 세부 정보가 보존되는 것은 아닙니다.

용어
컨텍스트 창과 토큰
컨텍스트 창은 모델이 한 번의 요청에서 참고할 수 있는 입력·출력의 용량입니다. 토큰은 그 용량을 세는 단위로, 글자나 단어와 정확히 일치하지 않습니다. 대화 본문 외에도 시스템 지시, 도구 정의, 이미지와 추론 관련 데이터가 예산에 영향을 줍니다.
한 문장 비유

좁은 책상 위에는 요약 카드, 서랍 안에는 원래의 회의록

하루 종일 회의하면 책상 위가 회의록으로 가득 찹니다. 끝난 안건은 요약 카드로 바꾸고, 원본 회의록은 서랍에 넣습니다. 새 안건을 다룰 공간은 생기고, 정확한 숫자가 필요할 때는 원본을 꺼냅니다.

책상이 컨텍스트 창, 요약 카드가 압축 블록, 서랍이 원문 저장소입니다. 서랍이 남아 있어야 다시 펼칠 수 있다는 점까지 같은 비유입니다.

1-1. 네 가지 도구가 만드는 학습용 지도

도구독자가 이해할 동작코드에서 볼 곳
compress메시지 범위와 요약을 받아 압축 블록을 만든다kernel/src/compress.ts
decompress요약에 가려진 원문이나 하위 내용을 다시 조회·노출한다src/decompress-shared.ts
search_context활성 압축 블록의 제목·요약에서 관련 내용을 찾아 복원할 위치를 좁힌다src/decompress-shared.ts
acp_status사용량과 압축 가능한 범위를 확인한다src/acp-status.ts

중요한 경계가 있습니다. 커널의 createCore().decompress()는 블록 조회를 제공하는 작은 함수입니다. 사용자가 보는 전체 복원 동작은 프록시의 원문 저장·조회와 커널의 블록 활성 상태 처리까지 합쳐 완성됩니다. 함수 이름만 보고 제품 기능 전체가 한 함수에 들어 있다고 생각하면 흐름을 놓치기 쉽습니다.

1-2. 연결 방식은 세 가지, 압축 책임은 두 갈래

README는 네이티브 플러그인, 클라이언트를 함께 띄우는 런처, API 기본 URL 변경을 안내합니다. 코드에서는 요청의 pluginMode 여부에 따라 도구를 누가 실행하는지가 달라집니다. 연결 방법과 압축 실행 주체를 별개의 축으로 읽으면 구조가 쉬워집니다.

학습 목표
배울 것은 프롬프트 한 줄보다 넓다

이 저장소는 대화 데이터를 바꾸는 미들웨어의 사례입니다. 입력을 줄이면서도 메시지의 순서, 도구 호출의 짝, 원문 복원, API 호환성과 장애 복구를 함께 지키는 방법을 배울 수 있습니다.

2왜 주목받는가

긴 코딩 세션의 비용과 기억 문제를, 클라이언트 사이의 공통 계층에서 다룬다

2-1. 관심을 끄는 문제는 세 가지다

코딩 에이전트는 파일 내용, 검색 결과, 명령 출력, 수정 내역을 계속 대화에 붙입니다. 요청마다 많은 이력을 다시 전송하면 입력량이 커지고, 창이 차면 정리 작업이 필요합니다. 이 프로젝트는 조금씩 접기·필요하면 펼치기·여러 클라이언트에 연결하기를 한 제품에 묶었습니다.

2026-10-23 GitHub 기준 스타 2,452개, 포크 210개이며 GitHub Trending TypeScript Weekly #16에 선정됐습니다. 이 지표만으로 사용자 유입 원인을 확정할 수는 없지만, 아래의 설계가 기술적으로 관심을 끌 만한 지점입니다.

  1. 증분 처리: 전체 대화를 한 번에 다시 쓰기보다 범위를 지정해 블록 단위로 관리합니다.
  2. 복원 경로: 요약이 놓친 세부 사항을 원문 저장소에서 다시 찾을 수 있도록 설계했습니다.
  3. 호스트 분리: 압축 엔진과 API·플러그인 연결 코드를 나눠 재사용 범위를 넓혔습니다.

2-2. 비슷한 해결책과 무엇이 다른가

다음 표는 처리 방식의 비교입니다. 특정 제품의 품질 순위나 비용 벤치마크를 뜻하지 않습니다. 클라이언트별 설치 차이는 이 저장소의 CLIENTS.md와 실제 어댑터를 함께 읽어야 합니다.

접근 / 제품군문제를 푸는 위치billion-context의 학습상 차별점
큰 컨텍스트 모델모델이 받는 입력 용량을 늘린다주어진 창 안에서 무엇을 남길지 관리한다. 모델 교체와는 다른 선택이다
호스트의 자동 요약각 에이전트 내부에서 이력을 정리한다범위·블록·원문 조회를 공통 엔진으로 다룬다. OpenCode와 병용 시 중복 압축 주의가 README에 명시돼 있다
opencode-acpREADME상 OpenCode 1.x용 독립 확장본 저장소는 OpenCode 외에도 여러 호스트의 연결·실행·업데이트 경로를 포함한다
billion-context-piREADME상 pi용 독립 확장본 저장소에는 pi 네이티브 진입점과 공용 프록시가 함께 있다. 동시 활성화는 중복 압축 위험이 있다
일반적인 RAG검색으로 필요한 문서 조각을 고른다대화의 시간 순서와 도구 실행 이력을 접고 복원한다. 내부 검색 기능은 이 과정을 보조한다

이 프로젝트의 강점은 요약 하나가 아니라, 요약을 오래 유지하는 데 필요한 상태와 복구 경로를 함께 구현했다는 점입니다.

2-3. 홍보 수치와 소스가 증명하는 것은 다르다

프로젝트 측 설명소스에서 확인되는 장치읽는 기준
100K 창으로 장기 세션모델별 창 설정, 보호 구간, 압축 권고, 사전 예산 검사모든 작업이 100K에서 성공한다는 보장은 아니다
토큰 5배 절감요약 치환, 도구 결과 저장, 사용량·캐시 집계README의 홍보 설명이다. 작업별 동일 절감률을 보장하지 않는다
캐시 적중률 95~97%안정적인 앞부분, 캐시 사용량 원장, 바이트 차이 검증 코드README의 정상 세션 설명이다. 제공자·TTL·모델 전환에 따라 달라진다
압축을 되돌릴 수 있음블록 원문 보관, 중첩 블록 관계, 복원 도구요약 자체의 무손실성을 뜻하지 않는다. 저장된 원문이 복원을 뒷받침한다
비유

여행 가방을 작게 싸는 기술과, 모든 여행에서 정확히 같은 무게를 줄인다는 주장은 다릅니다. 무엇을 챙겼는지, 무엇을 다시 꺼내야 하는지에 따라 절감량과 추가 작업이 달라집니다.

코드를 읽을 때도 같은 태도가 유용합니다. 메모리 절감 장치를 발견했다면 적용 조건을 찾고, 복구 함수를 발견했다면 복구할 데이터가 실제로 저장되는 경로까지 따라가야 합니다.

3기술 스택 전체 지도

실행 코드는 Node.js와 TypeScript, 화면은 서버가 조립하고 빌드는 묶어서 배포한다

3-1. 백엔드와 압축 엔진

루트 package.json은 ESM을 뜻하는 "type": "module"과 Node.js >=20을 선언합니다. tsconfig.json은 strict: true, target: ES2022, module: NodeNext, moduleResolution: NodeNext입니다.

역할의존성 선언실제로 읽을 코드
HTTP 서버Node.js 내장 node:httpsrc/server.ts의 startServer(), http.createServer(dispatch)
압축 커널acp-kernel: file:./kernel
자체 버전 0.0.160
kernel/src/compress.ts의 createCore()
스키마 호환zod: 4.1.8OpenCode 네이티브 도구 등록 경로. 모든 진입점의 공통 프레임워크는 아니다
네트워크·스트림undici: ^7.29.0
ws: 8.22.0
상류 요청, WebSocket 중계와 Responses 연결
인증서node-forge: ^1.4.0src/ca.ts, src/mitm.ts의 인증서 기반 중계
영속 저장SQLite 엔진 선택 + mysql2: ^3.15.3src/storage/driver.ts, src/storage/backend.ts, src/storage/mysql.ts
선택적 이미지 처리jimp: 1.6.1 — 선택 의존성src/image-rescale.ts에서 필요할 때 로드
pi 하위 에이전트billion-context-pi-subagents: file:./pi-subagents
자체 버전 0.2.2
pi-subagents/src/와 src/agent/pi-subagents.ts

여기서 ^는 버전 범위입니다. package-lock.json의 루트 설치 해석값은 TypeScript 5.9.3, tsup 8.5.1, tsx 4.23.9, esbuild 0.27.7입니다. 선언된 최소 범위와 고정된 설치 결과를 구분해서 읽어야 합니다.

용어
ESM · 번들 · 실행 의존성
ESM은 import·export로 파일을 연결하는 모듈 방식입니다. 번들은 여러 모듈을 배포 파일로 묶는 작업입니다. 빌드 때 내부로 묶인 라이브러리와, 실행할 때 별도 패키지로 찾는 의존성은 설치·장애 조건이 다릅니다.

3-2. 프론트엔드: 독립 SPA보다 서버에 가까운 화면

src/web/page.ts의 renderPage()가 HTML을 조립하고, src/web/client.ts와 src/web/styles.ts가 브라우저 동작과 스타일을 제공합니다. 설정 편집, 세션 조회, 로그 탐색을 위해 별도의 React·Vue 애플리케이션을 빌드하는 구조는 아닙니다.

화면 계층구현 방식배울 점
내장 관리 화면renderUI() → renderPage()서버 버전·실행 상태를 화면과 연결하는 방법
설정 편집기parseConfigDraft(), 주석·후행 쉼표 처리JSONC를 읽는 화면과 서버의 해석을 일치시키기
세션 탐색src/web/sessions-data.ts목록은 작게 보내고 블록 내용은 필요할 때 읽는 조회 설계
dsh 화면 연동src/agent/dsh-native-client.ts, React는 호스트 외부 의존성호스트 UI에 들어가는 작은 어댑터와 본체 UI를 구분하기
공식 웹사이트website/의 HTML·CSS·JavaScript정적 문서 사이트와 실행 중 관리 화면은 별개의 산출물이다

React의 별도 버전 범위는 루트 의존성에 없습니다. tsup.config.ts의 브라우저용 설정에서 react를 외부로 남겨 dsh 호스트의 모듈 로더가 제공하게 합니다. 따라서 이 저장소 전체를 React 앱이라고 부르면 실제 구조와 맞지 않습니다.

3-3. 빌드·배포·검증

영역설정과 버전구체적인 의미
TypeScript 도구루트 선언 typescript: ^5.5.0, tsup: ^8.0.0, tsx: ^4.0.0타입 검사·번들·TypeScript 테스트 실행을 분담한다
Node.js용 번들 전략target: node20, splitting: false, sourcemap: false여러 진입점을 독립 파일로 만들고 소스맵 배포를 끈다
내부 패키지 포함noExternal에 커널·pi 구성요소 등 명시내부 엔진을 빌드 결과에 포함한다. 커널의 별도 npm 조회에 기대지 않는다
테스트node:test, node:assert/strict루트 npm test는 전용 잠금·실행 스크립트를 거친다
CI.github/workflows/ci.yml
Ubuntu·Windows, Node.js 22·24
core / full / skip 범위를 결정하고 테스트를 분할한다
컨테이너FROM node:24-slim, BILI_VERSION=latest소스 컴파일 대신 공개 npm 패키지를 설치한다. 버전 인자로 고정할 수 있다
배포 자동화.github/workflows/release.yml, .github/workflows/pages.yml릴리스는 검사 후 npm 배포, 웹사이트는 빌드 없이 정적 폴더 게시
문서와 코드의 차이
“의존성 없는 실행 파일”이라는 설명은 적용 범위를 확인한다

AGENTS.md 일부 설명에는 의존성이 없거나 zod만 외부라는 표현이 남아 있습니다. 현재 package.json에는 mysql2와 zod가 실행 의존성, jimp가 선택 의존성으로 선언돼 있습니다. 일부 기능이 지연 로드된다는 사실과 패키지 전체에 실행 의존성이 없다는 주장은 구분해야 합니다.

4아키텍처 심화 분석

한 요청의 이동 경로와, 그 안에서 반복되는 네 가지 설계 패턴

4-1. 전체 시스템 구조

HTTP 서버 진입점은 src/server.ts의 startServer()입니다. 여기서 createEngineContext()로 엔진과 상태를 준비하고, http.createServer(dispatch)가 요청을 받습니다. 실제 라우팅과 전달은 src/server/handle.ts와 src/server/relay.ts로 나뉩니다.

에이전트 클라이언트 / 호스트 플러그인 | | HTTP 요청 · 지원 경로의 WebSocket v +------------------------------------------------------+ | src/server.ts : startServer() | | createEngineContext() + http.createServer(dispatch) | +--------------------------+---------------------------+ | v src/server/handle.ts : handle() | 프로토콜 · 세션 · 예산 확인 | v src/server/prepare-openai.ts · src/server/prepare-anthropic.ts src/server/prepare-responses.ts · src/server/prepare-google.ts | API 메시지 <--> CoreMessage[] | v +------------------------------------------------------+ | kernel/src/compress.ts : createCore() | | processTurn() : 참조 부여 · 압축 뷰 · 권고 · 보호 | | applyCompression() : 범위 검사 · 요약 블록 생성 | +--------------------------+---------------------------+ | +----------------+----------------+ | | v v src/session.ts src/persist.ts 메모리 세션 · 지연 원문 조회 SessionStore | | | SQLite / 선택적 MySQL | JSON 저장·호환 경로 v src/server/relay.ts : forward() | v 상류 모델 API | v src/loop/core.ts : runCompressLoop() | +-- 프록시 도구면 실행 후 내부 요청 계속 +-- 일반 응답이면 스트림을 클라이언트에 전달

이 그림의 압축 루프는 프록시 모드의 대표 경로입니다. 플러그인 모드에서는 호스트가 도구를 실행하므로 같은 루프가 모든 요청에서 같은 일을 한다고 해석하면 안 됩니다. prepareOpenai()의 injectTools = shouldInject && !pluginMode가 이 경계를 드러냅니다.

4-2. 패턴 ① 포트와 어댑터: 외부 형식은 가장자리에서 번역한다

kernel/src/types.ts의 CoreMessage는 id, role, contentType, text, toolName, toolCallId 같은 공통 필드를 둡니다. Anthropic·OpenAI·Responses·Google 형식 변환은 kernel/src/wire/가 담당합니다.

엔진은 API마다 다른 JSON 필드를 직접 알 필요가 줄어듭니다. 토큰 계산도 createCore(ports)의 Ports.countTokens로 주입할 수 있습니다. 입력 형식과 환경 의존 동작을 바깥으로 밀어낸 설계입니다.

// kernel/src/compress.ts — 실제 공개 인터페이스 일부
export interface Ports {
  countTokens?: (text: string) => number;
}

// kernel/src/types.ts — 학습을 위해 핵심 필드만 발췌
export interface CoreMessage {
  id: string;
  role: MessageRole;
  contentType: MessageContentType;
  text?: string;
  toolName?: string;
  toolCallId?: string;
}

출력 스트림에도 같은 원리가 적용됩니다. src/loop/core.ts의 CompressLoopAdapter는 buildRequest(), parseStream(), emitText(), emitToolCall() 등을 요구합니다. 공통 루프는 ParsedStreamEvent를 보고 판단하고, 실제 API 바이트 형식은 어댑터가 만듭니다.

용어
판별 유니온 (discriminated union)
kind: "text"와 kind: "tool_call"처럼 구분 필드가 있는 여러 타입을 하나로 묶는 방식입니다. kind를 확인하면 TypeScript가 그 경우에 존재하는 필드를 좁혀 줍니다. 스트림 이벤트의 잘못된 조합을 줄이는 데 유용합니다.

배울 점은 “모든 API를 완전히 똑같게 만든다”가 아닙니다. 서명·도구 식별자처럼 공통 필드만으로 충분하지 않은 정보는 별도로 보존해야 합니다. 실제 이벤트 타입에 signature, redacted_thinking, standalone_signature가 있는 이유입니다.

4-3. 패턴 ② 파이프라인과 단일 판단 규칙: 추천과 실행이 같은 기준을 쓴다

processTurn()은 buildNodes()가 만든 노드 목록을 runPipeline()에 넘깁니다. 각 노드는 메시지·상태·부수 결과를 담은 NodeIO를 받아 다음 단계로 전달합니다.

// kernel/src/pipeline.ts — 실제 순회 로직
let io = initial;
for (const node of nodes) {
  if (node.enabled && !node.enabled(io, ctx)) continue;
  io = node.run(io, ctx);
}
return io;
buildNodes()의 주요 순서 — 일부 단계를 묶어 표시 reconcileLiveIds → assignRefs → syncBlocks → prune → 변환 전 뷰 보관 → CCR / absorb / crush / filter → 압축 호출 숨김 → viewLatch → recommend → nudge → emergencyTruncate → renderRefs renderTags = "none"이면 마지막 참조 태그 렌더링은 생략 참조 번호를 부여하는 단계 자체는 유지

여기서 깊이 읽을 함수가 kernel/src/unit-projection.ts의 projectUnit()입니다. 범위 경계, 도구·추론 쌍, 보호 도구, 미디어, 최근 메시지와 턴 무결성을 함께 검사합니다. applyCompression()의 실행 경로와 추천 경로가 같은 판단 함수를 사용합니다.

이전처럼 추천은 전체 압축 후보를 한꺼번에 보고, 실행은 제출된 범위 하나만 보면 모순이 생길 수 있습니다. “압축 가능”이라고 안내한 구간이 실제 실행에서는 도구 호출의 짝을 끊어 매번 거부되는 식입니다. applyView는 두 판단이 같은 종류의 메시지 배열을 보도록 전달하는 장치입니다.

추천과 실행의 규칙을 공유해야, 가능하다고 보여 준 작업이 실제로도 같은 조건에서 가능해집니다.

비유

예매 화면은 좌석이 비었다고 표시하는데 결제 서버는 늘 매진이라고 답한다면, 두 화면을 예쁘게 고쳐도 문제가 해결되지 않습니다. 두 판단이 같은 좌석 상태와 규칙을 보게 해야 합니다.

4-4. 패턴 ③ 계층 블록과 파생 뷰: 원문, 요약, 현재 입력을 구분한다

CompressionBlock에는 summary 외에도 directMessageIds, effectiveMessageIds, directBlockIds, tier, generation, active가 있습니다. 직접 포함한 메시지, 중첩한 하위 블록, 결과적으로 덮는 원문 범위를 구분합니다.

메시지 참조 m00001 ... m00040 ──> T1 블록 b1 메시지 참조 m00041 ... m00080 ──> T1 블록 b2 b1 + b2 + 다른 대상 ──> T2 블록 b3 | 더 높은 수준의 요약 저장된 상태: 원문 참조 + 블록 관계 + 요약 + 원문 내용 모델에 보낼 뷰: 활성 요약 + 압축하지 않은 메시지

위 번호와 구간은 개념 예시입니다. 실제 범위는 보호 규칙을 통과해야 합니다. kernel/src/prune.ts의 prune()가 덮인 메시지를 뷰에서 빼고 요약을 배치합니다. 활성 블록의 요약은 acp_summary_ 접두의 뷰 전용 메시지로 나타날 수 있습니다.

플러그인 모드에서는 호스트 이력에 남은 압축 도구 호출이 요약을 운반할 수 있습니다. 프록시 모드에서는 acp_summary 계열 메시지가 운반할 수 있습니다. prune()는 해당 블록의 원래 압축 호출이 이미 보이면 요약을 중복 렌더링하지 않도록 검사합니다.

핵심은 저장 상태와 모델에게 보여 줄 배열을 같은 것으로 취급하지 않는 것입니다. 또한 tier 1·2·3과 generation의 young·old는 서로 다른 필드입니다. 계층의 높이와 블록이 살아남은 세대 상태를 하나의 숫자로 뭉개지 않았습니다.

기본값은 어디까지나 출발점이다

kernel/src/config.ts기본값읽을 때 주의할 점
growthFloor / growthCap각각 50,000성장 간격의 기준을 고정한다. 매번 정확히 50,000에서 무조건 압축하는 뜻은 아니다
preserveRecentMessages3최근 보호의 한 축이다. 사용자 메시지·토큰·도구 쌍 규칙도 함께 작동한다
preserveRecentTokens5,000메시지 개수만으로 보호 범위를 결정하지 않는다
minCompressRange5,000토큰 수가 아니라 원문 문자열의 UTF-16 코드 단위 길이 기준이다
tier2Trigger / tier3Trigger1,000 / 2,000하위 계층 블록 수 기준이다. 토큰 수로 읽으면 안 된다
truncate.threshold0.95긴급 절단의 안전장치다. 정상 요약 흐름과 구별한다
absorb / crush / ccr커널에서는 기본 비활성프록시 설정·호스트 경로에서 바뀔 수 있으므로 최종 설정을 확인한다

캐시도 이 뷰 설계와 연결됩니다. 앞부분이 조금만 바뀌어도 재사용 가능한 접두부가 줄어들 수 있어, 요약 삽입 위치와 참조 태그를 안정적으로 유지하려는 코드가 많습니다. src/server/snapshot-render.ts는 서버의 정식 이력에서 앞부분을 렌더링하는 별도 경로지만, src/rollout.ts의 snapshotRender 기본 배포 비율은 0입니다.

4-5. 패턴 ④ 장애를 고려한 영속화: 작은 저장본이 정상 데이터를 지우지 못하게 한다

src/session.ts의 LazyBlockContents는 저장을 마친 원문 내용을 메모리에서 내렸다가, get()·반복·size 조회 시 다시 읽습니다. 다시 읽기에 실패하면 빈 Map을 정상 데이터로 반환하지 않고 예외를 냅니다.

이 선택은 데이터 보존과 직결됩니다. 원문이 사라진 것처럼 보이는 빈 상태를 다음 저장에서 기록하면 디스크의 정상 원문까지 지울 수 있기 때문입니다. tests/memory-blockcontent-lazy.test.ts는 이 동작을 읽어 볼 회귀 테스트입니다.

파일 저장은 kernel/src/persist/store.ts의 StateStore.writeInner()에서 임시 파일 쓰기 → 파일 동기화 → 세대 확인 → 이름 변경 순서로 공개됩니다. commitSeq가 바뀌었다면 오래된 쓰기를 버려 더 최근 상태를 덮지 않게 합니다.

// src/persist.ts — 통합 인덱스 일반 조회 경로의 복구 조건을 축약
const ahead = envRequests > indexedRequests ||
  (envRequests === indexedRequests &&
   envelopeNextBlockId > indexNextBlockId);

// 앞선 JSON 저장본이면 통합 저장소 반영을 시도하고 그 상태를 사용
// 같거나 뒤처진 저장본이면 기존 인덱스 상태를 유지

재시작 뒤 처음 읽는 경로에서는 통합 인덱스와 JSON 저장본이 서로 어긋날 수 있습니다. SessionStore.loadSync()의 통합 인덱스 일반 조회 경로는 요청 수가 더 큰지, 같다면 nextBlockId가 더 큰지 비교합니다. 별도의 불일치 복구 경로에서는 활성 블록 수와 참조 수를 비교하기도 합니다. 파일 수정 시각 대신 데이터의 진행 상태를 복구 기준으로 사용한 사례입니다.

tests/storage-orphan-recovery.test.ts에는 인덱스 요청 수 390, JSON 저장본 요청 수 876인 상황을 만들어 후자를 복원하는 사례가 있습니다. 복원 뒤 JSON 파일을 지우고 재시작해도 인덱스가 복구 상태를 유지하는지까지 검사합니다.

설계 관찰
정상 경로보다 복구 기준이 더 많은 것을 설명한다

지연 로딩 실패를 빈 데이터로 바꾸지 않는 규칙, 오래된 쓰기를 거부하는 세대 번호, 두 저장본의 진행 상태 비교는 모두 “무엇을 진실로 취급할 것인가”라는 같은 질문에 대한 답입니다.

5디렉토리 구조 해부

실행 진입점부터 읽고, 한 번에 하나의 데이터 구조만 따라간다
billion-context/ ├── package.json / package-lock.json 패키지 계약과 설치 버전 ├── tsconfig.json / tsup.config.ts 타입 검사와 배포 묶음 ├── src/ │ ├── index.ts CLI 진입점 │ ├── server.ts HTTP 서버·엔진 초기화 │ ├── server/ 요청 준비·라우팅·상류 전달 │ ├── loop/ 압축 도구 루프·API별 스트림 │ ├── agent/ 호스트별 플러그인 어댑터 │ ├── session.ts / session-id.ts 세션 상태·대화 정체성 │ ├── persist.ts / state-hydration.ts 저장·재로딩 │ ├── storage/ 통합 저장소·SQLite·MySQL │ ├── web/ 관리 화면과 조회 API │ ├── launcher.ts / mcp.ts 런처·도구 연결 │ ├── config.ts / knobs.ts 설정 해석·우선순위 │ └── kimi/ / zcode/ 호스트 전용 연결 경로 ├── kernel/ │ ├── src/compress.ts 압축 코어와 처리 파이프라인 │ ├── src/unit-projection.ts 압축 가능 여부의 공통 판단 │ ├── src/wire/ 외부 API ↔ 공통 메시지 │ ├── src/search/ 검색 점수·알고리즘 등록 │ ├── src/persist/ 범용 파일 상태 저장 기구 │ └── tests/ 커널 회귀 테스트 ├── pi-subagents/ pi 하위 에이전트 구성요소 ├── hermes-plugin/ Python 호스트 플러그인 ├── tests/ 프록시·통합·회귀·E2E 테스트 ├── scripts/ 빌드 검사·CI·릴리스 도구 ├── verif/ TypeScript 일부의 기호 실행 검증 ├── proof/ 캐시 안정성의 SMT 명세 ├── paper/ 프로젝트의 방법론·실험 설명 ├── website/ 정적 소개·문서 사이트 ├── reference/ / devlog/ 구조 안내·개발 결정 기록 └── .github/workflows/ / Dockerfile 검사·배포·컨테이너

트리는 학습에 필요한 경로를 골라 축약했습니다. 특히 kernel/src/persist/는 파일을 안전하게 쓰는 범용 기구이고, src/persist.ts는 제품의 세션 저장 정책입니다. 이름이 비슷해도 책임의 크기가 다릅니다.

읽는 목적추천 순서이 순서가 유용한 이유
전체 그림package.json → src/index.ts → src/server.ts무엇이 실행되는지부터 정한다
압축 원리kernel/src/types.ts → kernel/src/config.ts → kernel/src/compress.ts자료형과 기본값을 알고 동작을 읽는다
원문 복원src/session.ts → src/decompress-shared.ts → src/persist.ts메모리 상태·도구 처리·디스크를 연결한다
호환성 문제kernel/src/wire/ → src/loop/ → 해당 회귀 테스트입력 변환과 출력 재구성을 모두 본다

5-1. 코드 규모는 어떤 기준으로 셌는가

커밋 fdbddd0의 Git 추적 텍스트 파일을 확장자별로 센 수치입니다. 빈 줄과 주석, 끝에 개행이 없는 마지막 줄도 포함한 물리적 줄 수입니다. 테스트 지원 코드·선언·설정도 포함됩니다. TypeScript가 많다는 사실과 제품 구현이 그만큼 길다는 주장은 구분해야 합니다.

언어 / 확장자파일 수줄 수
TypeScript .ts1,395466,088
JavaScript .js + .mjs306,861
Python .py21,554
HTML5711
CSS1281
Shell .sh133

TypeScript 중 테스트 경로·테스트 파일은 303,709줄, 나머지 구현·설정·선언은 162,379줄입니다. src/ 구현은 128,146줄, kernel/src/는 23,413줄, pi-subagents/src/는 4,648줄입니다. 이 세 하위 경로 수치는 전체 집계와 겹칩니다.

처음부터 46만 줄을 읽으려 하지 말고, 작은 자료형 하나와 그 자료형을 지키는 테스트 하나를 짝지어 읽으세요. reference/architecture.md의 테스트 개수 같은 요약은 현재 파일 집계보다 오래될 수 있습니다. 현재 tests/를 비롯한 저장소 전체의 *.test.ts 파일은 합계 1,013개입니다.

6학습 포인트 (기술별)

문법을 외우는 대신, 그 문법이 지키려는 데이터를 찾는다

6-1. TypeScript: 상태를 타입으로 드러내기

CompressionTier = 1 | 2 | 3, BlockGeneration = "young" | "old"처럼 가능한 값을 좁혀 두면 임의의 숫자·문자열을 넘기는 실수가 줄어듭니다. UnitProjectionFatal의 kind: "zone" | "split"은 “실패했다”보다 구체적인 사유를 전달합니다.

실습 아이디어: CoreMessage에서 도구 호출과 결과를 구분하는 필드를 표시하고, ParsedStreamEvent의 각 kind에서 읽을 수 있는 필드를 표로 정리합니다. 타입이 금지하는 값과 런타임 검사로만 막을 수 있는 값을 나눠 보세요.

6-2. 토큰 계산: 빠른 추정과 실제 사용량을 구분하기

kernel/src/tokenize.ts의 기본 계산은 정확한 모델별 토크나이저가 아닙니다. 지정한 한·중·일 문자 범위는 글자 수를 세고, 나머지는 UTF-16 코드 단위 4개를 한 토큰으로 추정해 올림합니다. 이 선택은 한국어를 단순히 전체 길이 ÷ 4로 계산하는 과소 추정을 줄입니다.

// kernel/src/tokenize.ts — defaultCountTokens()의 실제 핵심
const cjk = text.match(/[\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]/g);
const cjkCount = cjk?.length ?? 0;
return cjkCount + Math.ceil((text.length - cjkCount) / 4);

// 손으로 계산해 보기
// "가나다abcd" → 3 + ceil(4 / 4) → 4
// 이 값은 해당 함수의 추정값이며 모델 청구 토큰 수가 아니다.

실습 아이디어: 영어 코드, 한국어 설명, 이모지가 있는 세 문장을 골라 손으로 계산합니다. JavaScript의 text.length는 UTF-16 코드 단위 길이라는 점도 확인합니다. 이후 src/server.ts의 effectiveTokenCount()에서 사용량과 추정값을 구분하는 흐름을 읽습니다.

6-3. 비동기 스트림: 문자열 대신 이벤트의 생명주기 보기

runCompressLoop()는 AsyncGenerator<Buffer>를 반환합니다. 한 번에 완성된 응답만 만드는 대신, 읽은 이벤트에 맞춰 결과 바이트를 조금씩 내보냅니다. MAX_LOOP_ROUNDS = 10은 내부 루프를 제한하는 상수입니다.

본문, 추론, 도구 호출, 사용량, 종료 이벤트는 의미가 다릅니다. 특히 서명된 추론 데이터는 “보기 좋게 정리”하려고 바꾸면 다음 재전송에서 실패할 수 있습니다. tests/issue1960-thinking-verbatim.test.ts는 클라이언트 출력과 내부 재요청 양쪽의 보존을 검사합니다.

실습 아이디어: 텍스트 → 도구 호출 → 도구 결과 → 재요청 → 종료라는 타임라인을 그립니다. 이미 독자에게 전달한 텍스트가 있는 시점에 재시도하면 어떤 중복 문제가 생기는지도 적어 봅니다.

6-4. 검색: 점수의 척도를 먼저 맞추기

kernel/src/search/registry.ts는 substring·BM25·fuzzy·hybrid를 기본 등록합니다. 이 모듈의 기본 알고리즘은 hybrid이고, kernel/src/search/algorithms/hybrid.ts는 각 점수의 최댓값으로 정규화한 뒤 BM25 0.7, fuzzy 0.3으로 합칩니다. 프록시 도구 search_context는 이 모듈 대신 createCore().search()로 활성 블록의 제목·요약을 검색하며, 기본 결과 수는 5개입니다.

커널 검색 모듈의 어휘 기반 혼합 점수 = 0.7 × 정규화한 BM25 점수 + 0.3 × 정규화한 fuzzy 점수 이후 역할 가중치 적용 사용자 1.5 / 어시스턴트 1.0 / 도구 0.6 / 요약 블록 1.0

여기서 hybrid는 기본적으로 BM25와 fuzzy의 혼합입니다. “키워드 + 벡터 검색이 기본 활성”이라는 뜻은 아닙니다. 비동기 semantic 경로는 별도 알고리즘을 등록해 사용하는 확장 지점입니다.

실습 아이디어: 문서 세 개에 가상의 두 점수를 넣어 정규화 전후 순위를 비교합니다. 역할 가중치는 확률이 아니므로 최종 점수가 반드시 1 이하일 필요가 없다는 점도 확인합니다.

6-5. 저장·테스트: 결과 예시에서 불변 조건으로 확장하기

StorageBackend는 SQL 문법을 통일하기보다 ingestSession(), getBlocks(), archiveSession() 같은 작업을 계약으로 둡니다. SQLite와 MySQL의 트랜잭션 방식이 달라도 같은 제품 동작을 구현할 수 있게 한 경계입니다.

검증 계층도 구분합니다. 일반 회귀 테스트는 특정 장애를 재현하고, proof/는 명세의 가정 아래 성질을 검사하며, verif/는 지원하는 TypeScript 부분을 공식으로 옮겨 반례를 찾습니다. 세 계층을 합쳐 “전체 프로그램이 증명됐다”고 말할 수는 없습니다.

좋은 테스트는 한 번의 정답뿐 아니라, 입력이 늘거나 다시 읽혀도 유지돼야 할 규칙을 설명합니다. 실습으로 “새 메시지 추가가 이미 완료된 앞부분의 바이트를 바꾸지 않는다”를 문장으로 적고, tests/cache-proof.test.ts에서 그 규칙을 어떤 상황에 적용하는지 찾아보세요.

7하드웨어 / 시스템 요구사항

모델 추론 서버의 요구사항과 프록시의 자원 요구를 분리한다
항목소스에서 확인되는 조건학습·사용 시 해석
Node.jsengines.node: >=20, 번들 타깃 node20패키지가 선언한 최소 런타임 계약이다
검사 환경주 CI는 Node.js 22·24의 Ubuntu·Windows 조합최소 선언과 실제 CI 조합을 구분한다
컨테이너node:24-slim, 포트 8787, 상태별 볼륨 네 개Node.js 런타임과 데이터 보존을 함께 준비한다
CPU특정 코어 수의 공식 최소값 없음JSON 처리·문자열 변환·검색·압축·저장이 CPU를 쓴다
GPU기본 프록시 경로는 모델 가중치를 로컬에 올리지 않음상류 모델 API를 쓸 때 프록시 자체에 추론용 GPU는 필요하지 않다
메모리세션 추정 상주량 기본 목표 512 MiB프로세스 전체 RAM 상한도, 시스템 최소 RAM도 아니다
디스크요약·원문·인덱스·로그가 누적됨컨텍스트 감소가 저장 용량 감소와 같지는 않다
네트워크모델 API·선택적 레지스트리 조회·업데이트 경로상류 주소·인증·연결 지연이 실행 조건에 포함된다

src/knobs.ts의 기본값은 sessions.max = 256, sessions.warmMax = 0, sessions.warmMaxBytes = 64 MiB, sessions.residentMaxBytes = 512 MiB입니다. warmMax가 0이므로 시작할 때 세션을 미리 읽기보다 첫 접근에서 불러오는 흐름이 기본입니다.

512 MiB는 세션 자료의 추정 목표값이며, Node.js 전체 메모리를 그 이하로 고정하는 제한이 아닙니다. 활성 요청의 상태는 유지되고, 파싱 중 객체·응답 버퍼·실행 환경의 메모리도 별도로 듭니다. 소스에는 공식적인 “RAM 몇 GB 이상” 성능 보증이 없습니다.

7-1. SQLite를 어디서 얻는지도 시스템 조건이다

src/storage/driver.ts와 src/storage/engine-bootstrap.ts는 내장 node:sqlite → 호스트가 제공한 better-sqlite3 → 캐시한 사전 빌드 엔진 순으로 경로를 마련합니다. 소스는 내장 모듈의 제공 시작점을 Node.js 22.5로 설명하고, 엔진을 얻지 못하면 legacy JSON 저장으로 내려갑니다.

실제 경로는 런타임·플랫폼·다운로드 허용 설정에 따라 달라집니다. storage.unified의 기본 해석은 full이고, storage.jsonWriter는 기본 켜짐입니다. MySQL은 선택적 별도 경로이며, 기본 사용에 별도 MySQL 서버가 필수인 것은 아닙니다.

7-2. 장기 세션의 비용은 저장소에서도 생긴다

src/paths.ts는 설정·데이터·캐시·실행 상태를 XDG 경로로 나눕니다. 예를 들어 원문과 세션은 ~/.local/share/billion-context/, 로그는 ~/.local/state/billion-context/ 계열에 놓입니다. 컨테이너의 네 볼륨도 이 구분을 반영합니다.

sessions.gc는 기본 비활성입니다. 따라서 긴 대화를 많이 저장한다면 보존 기간·백업·정리 정책을 별도로 결정해야 합니다. Dockerfile은 컨테이너 안의 자동 업데이트를 ACP_AUTO_UPDATE=0으로 끄지만, 이미지 빌드의 기본 패키지 버전은 latest라는 점도 재현성과 연결됩니다.

8직접 해볼 수 있는 실습 과제

설치나 실제 API 호출 없이도, 소스와 작은 예제로 핵심을 확인할 수 있다
과제 1 · 입문

패키지에서 실행 파일까지 연결하기 20~30분

할 일: package.json의 bin·main·exports를 각각 적고, tsup.config.ts에서 대응하는 소스 진입점을 찾습니다.

완료 기준: bili 실행과 패키지를 플러그인으로 불러오는 일이 왜 다른 진입점으로 이어지는지 화살표 세 개로 설명합니다.

힌트: exports["."]는 dsh 네이티브 진입점, exports["./server"]는 OpenCode 네이티브 진입점입니다. main만 보고 모든 사용 방식을 추정하지 마세요.

과제 2 · 입문

요약 블록을 종이 위에 만들기 30~40분

할 일: 사용자 요청·도구 호출·도구 결과·답변·새 요청이 있는 대화 여섯 개를 만듭니다. 각 항목에 원문 ID와 표시 참조를 붙이고, 완료된 구간을 b1 요약으로 표시합니다.

완료 기준: 원문 목록, 저장한 블록, 모델에 보낼 뷰를 각각 그립니다. 도구 호출만 요약하고 결과를 남겼을 때 왜 짝이 깨지는지 설명합니다.

힌트: 원문 ID·mNNNNN·bN은 서로 다른 역할입니다. 참조 숫자가 연속이라는 가정도 하지 않습니다.

과제 3 · 중급

압축 권고와 실행의 모순 찾기 60분

할 일: kernel/tests/issue3236-recommend-apply-consistency.test.ts에서 늦게 도착하는 도구 결과가 있는 대화 모양을 읽고, projectUnit()의 검사 순서와 연결합니다.

완료 기준: 같은 구간을 전체 후보 집합으로 검사했을 때와 개별 범위로 검사했을 때 판단이 달라지는 예를 하나 그립니다. 추천·실행에 같은 입력이 필요한 이유를 세 문장으로 적습니다.

확장: 별도 학습용 예제의 함수 계약으로 checkRange(messages, range)를 설계하고, 화면과 실행이 그 결과를 함께 쓰게 해 봅니다.

과제 4 · 중급

혼합 검색의 순위를 손으로 계산하기 40~60분

할 일: 요약 세 개에 BM25 점수와 fuzzy 점수를 임의로 부여하고, 최댓값 정규화 → 0.7·0.3 혼합 → 역할 가중치 순으로 계산합니다.

완료 기준: 오타에 강한 점수의 비중을 올렸을 때 어떤 문서가 올라오는지 표로 보여 줍니다. 이 검색 모듈의 기본 minScore = 0.01, limit = 10과 순위 계산의 역할도 구분합니다.

힌트: kernel/src/search/index.ts의 runSearch()와 kernel/src/search/algorithms/hybrid.ts를 연결하면 됩니다.

과제 5 · 고급

재시작 복구의 판정표 작성하기 90분

할 일: tests/storage-orphan-recovery.test.ts를 읽고, 인덱스와 JSON 저장본의 요청 수·다음 블록 번호를 바꾼 가상 사례 여섯 개를 만듭니다.

완료 기준: 어느 저장본을 선택하는지, 선택 뒤 인덱스에 반영되는지, JSON 저장본 없이 재시작해도 복구가 유지되는지를 각각 표시합니다.

확장: 요청 수가 같고 블록 번호만 다른 경우, 복구 중 저장 오류, 지연 원문 로딩 실패까지 고려해 “실패를 빈 데이터로 바꾸면 안 되는 이유”를 설명합니다.

8-1. 읽기만 하는 탐색 명령 예시

다음 명령은 저장소 루트 기준입니다. 프로그램을 시작하지 않고 정의와 참조 위치를 확인합니다.

rg -n 'createCore|processTurn|applyCompression' kernel/src/compress.ts
rg -n 'projectUnit|applyView' kernel/src
rg -n 'LazyBlockContents|ensure\(' src/session.ts
rg -n 'ahead|envRequests|indexedRequests' src/persist.ts
wc -l kernel/src/compress.ts src/session.ts src/persist.ts

9관련 기술 심화 학습 로드맵

6주 동안 문법 → 메시지 → 압축 → 스트림 → 저장 → 검증으로 넓혀 간다
주차배울 것읽을 경로작은 결과물
1주차ESM, strict 타입, 유니온, 패키지 진입점package.json, tsconfig.json, kernel/src/types.ts실행·플러그인 진입점 지도와 메시지 타입 표
2주차공통 모델, 어댑터, 참조 식별자kernel/src/wire/openai.ts, kernel/src/wire/anthropic.ts, kernel/src/refs.ts같은 대화를 두 API 형식과 공통 형식으로 그린 비교표
3주차파이프라인, 보호 구간, 계층 요약kernel/src/compress.ts, kernel/src/prune.ts, kernel/src/unit-projection.ts전후 입력 뷰와 압축 불가 구간의 이유 목록
4주차비동기 제너레이터, 스트림 종료·재시도src/loop/core.ts, src/loop/adapter-openai.ts, src/loop/adapter-anthropic.ts도구 호출과 내부 재요청이 있는 이벤트 타임라인
5주차트랜잭션, 원자적 공개, 지연 로딩src/session.ts, src/persist.ts, src/storage/backend.ts복구 판정표와 데이터가 사라질 수 있는 지점 분석
6주차캐시 접두부, 불변 조건, 검증의 한계tests/cache-proof.test.ts, proof/README.md, verif/README.md유지해야 할 성질 다섯 개와 각 성질의 검증 범위

JavaScript가 익숙하지 않다면 1주차를 늘려 객체·배열·Map·Set·Promise부터 익히세요. 압축 알고리즘을 먼저 깊게 파기보다 메시지 배열이 어떻게 변하는지 그릴 수 있어야 이후 코드가 읽힙니다. 각 주차는 파일 전체 완독보다 결과물 하나를 완성하는 것을 목표로 삼습니다.

9-1. 다음 단계로 이어지는 세 갈래

여섯 주 뒤의 목표는 코드를 전부 외우는 것이 아니라, 메시지 하나가 들어와 저장되고 다시 보이는 과정을 설명하는 것입니다.

스스로 확인하기
세 질문에 답하면 구조가 보이기 시작한다

이 데이터의 원본은 어디에 있는가? 지금 보고 있는 것은 원본인가, 파생된 뷰인가? 두 저장본이 다르면 어떤 기준으로 하나를 고르는가? 이 질문을 다른 데이터 처리 프로젝트에도 적용해 보세요.

10핵심 키워드 사전

비슷한 이름을 구분하면 코드의 책임도 나뉘어 보인다
용어쉬운 설명
컨텍스트 창한 번의 모델 요청에서 다룰 수 있는 작업 공간. 장기 세션의 누적 사용량과 다르다
토큰 예산대화·지시·도구·출력 등에 나눠 쓸 용량. 문자열 길이만으로 정확히 계산되지는 않는다
프록시클라이언트와 서버 사이에서 요청·응답을 중계하는 프로그램. 이 저장소에서는 대화 변환도 수행한다
호스트플러그인을 실행하는 에이전트 프로그램. 호스트마다 도구·세션·네트워크 연결 방식이 다르다
ACP이 코드에서 압축 도구·참조 태그·상태에 붙는 이름. 다른 프로젝트의 같은 약어와 자동으로 동일시하지 않는다
CoreMessage여러 API 메시지를 압축 엔진이 다룰 수 있게 정리한 공통 자료형
어댑터외부 API의 구체적인 형식과 내부 공통 형식 사이를 번역하는 부품
파이프라인앞 단계의 결과를 다음 단계로 넘기는 처리 구조. 순서가 결과에 영향을 준다
원문 ID메시지의 실제 정체성을 추적하는 키. 화면에 보여 주는 참조 번호와 구분한다
ref · mNNNNN모델과 도구가 메시지를 지정할 때 쓰는 세션 내 참조. 배열 인덱스가 아니며 중간 번호가 비어 있을 수 있다
block · bN요약, 덮는 메시지 범위, 하위 블록 관계를 묶은 압축 단위
coverage어느 원문 메시지가 활성 압축 블록에 포함되는지 나타내는 범위·집합 관계
tier / generationtier는 요약 계층 1·2·3, generation은 young·old 상태. 서로 다른 축이다
파생 뷰저장한 원문·상태에서 목적에 맞게 만든 표시 결과. 모델 입력용 뷰와 저장 상태는 같지 않다
nudge모델에게 압축을 고려하도록 알리는 안내. 안내 발생과 실제 압축 성공은 별개다
preflight상류 전송 전에 용량과 실행 가능성을 확인하는 사전 검사
프롬프트 접두부 캐시이전 입력과 같은 앞부분을 제공자가 재사용하는 장치. 앞부분의 변화가 비용에 영향을 줄 수 있다
도구 호출 쌍호출과 그 결과의 연결. 호출만 지우거나 결과만 남기면 API의 대화 형식을 깨뜨릴 수 있다
서명된 추론 데이터본문과 서명의 대응을 지켜야 하는 데이터. 재전송 과정에서 임의 정리가 안전하지 않다
CCR큰 도구 결과 원문을 저장하고 참조로 다시 조회하는 기능 계열. 요약과 원문 보관의 역할을 구분한다
BM25 / fuzzy단어 관련성을 계산하는 점수 / 철자가 일부 다르거나 조각이 겹치는 정도를 보는 점수
지연 로딩필요한 시점까지 읽기를 미루는 방식. 적게 읽는 장점과 읽기 실패 처리의 책임이 함께 생긴다
cold load메모리에 없는 세션을 저장소에서 처음 불러오는 과정. 프로세스 재시작 뒤의 복구와 연결된다
원자적 공개완성된 새 상태를 한 번에 보이게 하는 전략. 이 저장소의 파일 경로에서는 임시 파일과 이름 변경을 쓴다
멱등성같은 처리를 반복해도 한 번 처리한 결과와 같아야 하는 성질. 태그·형식 정리의 검증에 유용하다
SMT · 반례조건을 수식으로 주고 만족하는 경우를 찾는 방법과, 원하는 성질을 깨뜨리는 입력 사례
점진 배포일부 설치부터 새 기능을 켜는 방식. 코드가 존재해도 기본 배포 비율이 0이면 일반 경로와 다를 수 있다
혼동하기 쉬운 말
요약 압축과 파일 압축
요약 압축은 모델에게 보일 의미 표현을 바꿉니다. zstd 같은 파일 압축은 저장 바이트를 줄입니다. 전자는 요약에서 세부 정보가 빠질 수 있고, 후자는 올바른 데이터라면 원래 바이트를 복구하는 방식입니다. 원문 복원이 가능하다는 설명을 요약 자체가 무손실이라는 뜻으로 읽지 마세요.

11참고 링크

소스는 커밋에 고정하고, 실행 조건은 선언·설정·코드를 함께 확인한다

11-1. 공식 저장소와 프로젝트 문서

11-2. 관련 기술의 공식 학습 자료

다음 링크는 본문의 개념을 더 공부할 때 볼 공식 문서입니다. 패키지 버전과 실행 지원 조건은 본문의 분석 기준 소스 및 해당 버전 문서와 함께 확인하세요.

11-3. 현재 상태 (2026-10-23 확인)

항목현재 상태
선정GitHub Trending TypeScript Weekly #16 · 2026-10-23 분석
스타 / 포크2,452 / 210 — 2026-10-23 GitHub 기준
생성일 / 주 언어2026-08-06 / TypeScript — 2026-10-23 GitHub 기준
최신 릴리스v0.1.204 · 2026-10-21 — 2026-10-23 GitHub 기준
최근 push2026-10-23 — GitHub 기준
분석 기준 커밋fdbddd0 · 2026-10-23
PR #4373 병합, 원문 메시지: Merge pull request #4373 from z0d0dOr/2026-10-22_orphan-cold-load-recovery
패키지 버전본체 0.1.204 / acp-kernel 0.0.160 / pi-subagents 0.2.2
코드 규모TypeScript 466,088줄 / 1,395파일. 테스트·설정·선언 포함, 빈 줄·주석 포함
테스트 구분TypeScript 테스트 경로·파일 303,709줄 / 그 외 구현·설정·선언 162,379줄. *.test.ts 1,013개
그 밖의 언어JavaScript 계열 6,861줄, Python 1,554줄, HTML 711줄, CSS 281줄, Shell 33줄
라이선스 메타2026-10-23 GitHub API 분류 NOASSERTION, package.json 선언 MIT
실제 라이선스 파일MIT 본문 뒤에 최종 사용자에게 보이는 제품·문서 등의 출처 표시를 요구하는 추가 조건이 있다
성능 수치의 성격100K 창·5배 절감·캐시 적중률 95~97%는 README 기준 프로젝트 측 설명. 보편적인 성능 보증으로 해석하지 않는다
쓰기 전에 알아둘 한계
요약 품질·복원 데이터·연결 방식의 조건을 함께 읽는다

요약은 원문과 다릅니다. 빠진 숫자·예외·결정 이유는 저장한 원문을 다시 찾아야 합니다. 원문·세션 저장소를 지우거나 읽을 수 없으면 복원 기능의 전제도 달라집니다.

호스트마다 지원 범위가 다릅니다. README는 Codex의 MCP 도구 설치만으로 모델 트래픽까지 자동 연결되지 않는다고 설명합니다. 별도 확장과 네이티브 압축을 동시에 켜는 경우도 주의해야 합니다. 기본 배포 비율이 0인 기능을 일반 동작으로 가정하지 마세요.

코드만으로 성능을 보장할 수는 없습니다. README의 품질·절감률·장기 안정성 설명은 모델·작업·세션 조건에 따라 달라지며, 모든 환경에서 같은 결과를 보장하지 않습니다.

라이선스 표기에는 차이가 있습니다. GitHub 분류, 패키지의 MIT 선언, 실제 LICENSE의 추가 출처 표시 조건을 모두 확인해야 합니다. 단순한 MIT 표기만으로 파일의 조건 전체를 설명할 수 없습니다.

데이터는 계속 쌓입니다. 대화·도구 출력에 포함된 내용이 원문 저장과 진단 자료에 남을 수 있습니다. 저장 경로·보존 정책·선택적 암호화의 적용 범위는 실제 설정과 저장 방식에 맞춰 확인하세요.