공개 호출계약을 고정하는 것을 목표로 한다. 새 기능을 얹기보다 표면을 확정하고 그 표면이 실제로 도는지 증명하는 데 무게를 둔다. 계약은 dartlab.{engine}("{axis}", ...) 와 Company 파사드 둘뿐이다.
증명은 격리 가상환경에 wheel 을 설치해서 한다. 공개 표면 17 시나리오가 빈 데이터 상태에서 전부 통과하고, 번들 리소스 열여덟 종이 wheel 안에 다 들어 있다.
Added
- Bring Your Agent Runtime. 로컬에 설치된 Codex CLI, Claude Code, Cline을 각각 app-server JSON-RPC, stream-json, ACP v1로 연결한다. 인증·모델·native transcript는 CLI가 소유하고 DartLab은 MCP, Skill OS, 금융 엔진, ref를 제공한다. Runtime Center와
dartlab agent는 탐지·설치·MCP 연결 계획을 보여 주며 SHA-256 digest를 명시적으로 승인하기 전에는 설정을 바꾸지 않는다. - Product Outcome local 원장.
started → scoped → grounded → delivered → verified → retained전이를 SQLite에 저장한다. exact evidence 확인 receipt가 같은 outcome의 opaque hash와 일치할 때만 verified가 되며 질문·답변·provider·model·token·원본 ref·파일 경로는 저장하지 않는다. dartlab.data데이터 작업대. 축은catalog와query둘이다.catalog는 지금 무엇을 어디까지 읽을 수 있는지(자산, 커버리지, 공백, 스냅샷 ID)를 돌려주고,query는 전종목 시점 고정 질의를 돌려준다. 세대는 불변이고, 큰 결과는 이어읽기로 나눠 받으며, 무거운 실행은 별도 프로세스로 격리된다. factor, graph, narrative, resource 는 별도 축이 아니라query의 투영이다.dartlab.macro("simulate")완결. 거시 시뮬레이션의 신용 축과 국면 경로까지 배선을 마쳤다. BVAR 팬 차트, 충격반응, 시나리오 조건부 경로.- 전종목 원천 스트리밍. DART 와 EDGAR 원천을 샤드 커서로 이어 읽는다. 중간에 끊겨도 이어서 재개한다.
Changed
- AI production 경로를 direct provider에서 Agent Runtime으로 전환.
dartlab.ask,/api/ask, Agent Gateway, 로컬 UI가 같은 runtime SSOT를 사용한다. provider secret/OAuth/Ollama pull API는 410 migration 안내를 반환하고 MCP tools/list에서는 runtime 재귀를 만들던ask를 제거했다. - Agent Runtime 준비 상태를 fail-closed로 강화. CLI와 DartLab MCP가 모두 확인된
groundedReadyruntime만 선택한다. Claude는 MCP 검색용ToolSearch와 읽기 전용 DartLab MCP만 노출하고, Cline도 공식 CLI 연결 계획과 digest 승인 경로를 사용한다. - 재무비율 계산을 하나의 L0 공식으로 통합. DART와 EDGAR의 단일 시점·시계열 계산이 같은 공식을 사용하고, 연간·분기·YTD 비교 간격과 통화를 호출자가 명시한다. 수익성과 운전자본 비율은 기초·기말 평균잔액을 사용한다.
- DART raw 스키마 소유권 정리. 실제 생산자인
gather/dart가 finance·report 계약 둘만 소유하며, 검증을 켠 상태의 오류는 호출자에게 그대로 전달한다. - 시뮬레이터 입력을 데이터 작업대 스냅샷으로 전환. 시뮬레이션이 읽는 자료가 시점 고정 스냅샷이 되어 같은 입력이 항상 같은 결과를 낸다.
- 브라우저 노트북 커널을 공유 런타임(
pyproc)으로 이관. 실패 시 옛 경로로 자동 폴백한다.
Fixed
미래 정보 누설과 재현성
- 회계 기간을 시점으로 오독해 종합평가를 통째로 죽이던 계약 검사.
latestPeriod: "2026"을 2026-12-31 로 읽어, 연중에 나온 정상 자료가 미래로 판정됐다. - 실행마다 순서가 바뀌던 전종목 스캔. 병렬 집계가 행 순서를 보장하지 않아 내용 봉인, 스냅샷 ID, 재생 검증이 전부 구실을 못 했다.
- 미래 정보 차단 규칙을 두 시장이 나눠 갖던 것. 한쪽 경계만 느슨해지면 그 시장 답만 조용히 미래를 봤다.
- 판단 대상인 주가로 판단 근거를 만들던 것.
- 베타가 매 실행 달라지던 것.
부르면 죽던 자리
- 여덟 계정이 다 갖춰졌을 때만 죽던 분식 회계 탐지. Company 전용 캐시 래퍼가 키워드 전용 순수 계산기에 붙어 있어, 자료가 갖춰진 회사일수록 확실히 터지고 없는 회사에서는 호출 자체가 없어 조용했다.
- 두 스레드가 함께 메모리를 읽으면 죽던 보고서. 프로세스 전역 ctypes 상태를 호출마다 덮어써서, 배경 감시 스레드와 본 스레드가 겹치면 무너졌다. 무거운 호출일수록 잘 죽었다.
- 부르면 즉시 죽던 매출 예측 앙상블 두 소스, 목록에 있는데 부르면 죽던 프리셋 둘, 앞 100 행이 비어 있으면 죽던 문서 검색, 이동평균 결측 오염으로 죽어 있던 세 지표.
- KRX 영숫자 종목코드를 미국 티커로 오분류하던 것.
받아 놓고 무시하던 인자
scope와ifrsOnly. 별도 재무제표를 달라고 해도 연결 재무제표가 나왔다.- 수수료를 물린다고 적어 놓고 무비용 성과를 보여주던 백테스트.
- 모르는 단위를 백만원으로 아는 척하던 것, 결측을 그럴듯한 숫자로 메우던 보고서, 값 0 을 값 없음으로 세던 자리.
계산이 틀리던 자리
- 자본잠식 기업의 비율 부호 뒤집힘, 종합순위가 하위 종목을 상위로 내보내던 것, 정규분포 CDF 오차, 좋은 전략을 0 점으로 만들던 하방편차, 상수로 굳어 있던 과적합 확률, 정교한 옵션이 할인율을 낮추던 것, ADX 30 을 인쇄하고 방향성이 없다고 말하던 추세 서사.
격리 실행
- 결과를 다 보낸 자식을 부모가 실패로 뒤집던 판정, 자식이 보낸 실패 코드를 부모가 지우던 것, 멈춘 자식이 원인을 말하지 않던 것, 자식 join 무한 정지.
보안
- 외부 본문을 감싼다고 적어 놓고 맨몸으로 보내던 경계. 웹과 공시 본문에 붙는 신뢰 불가 표시가 직렬화 세 길목에서 벗겨지고 있었다.
정리
- 중복 정의 100 벌에서 22 벌로. 같은 본문이 여러 파일에 흩어져 있으면 한쪽만 고쳐도 같은 자료가 다르게 읽힌다. 옮길 때마다 옛 구현과 새 구현을 같은 프로세스에 올려 대조했고 총 6 만 회 이상에서 불일치 0 이다. 남긴 22 벌은 계층을 어기거나 뜻이 달라지는 것들이고, 그 이유가 각 커밋에 적혀 있다.
- 복잡도 31 이상 함수 197 개에서 150 개로. 가장 복잡했던 자식 프로세스 감독 두 함수(63, 60)를 획득, 순환, 판정으로 갈랐다. 자원 획득 순서와 해제 순서를 문장 단위로 보존했음을 흉내낸 파이프로 1 만 회 대조해 확인했다.
- 품질 게이트를 차단으로 세웠다. 그 게이트의 기준선이 강행규칙으로 금지된 폴더를 가리키고 있어 한 번도 안 읽혔고, 게이트가 비차단이라 계속 빨간불인 채였다.
마이그레이션
- 공개 계약은
dartlab.{engine}("{axis}", ...)와Company파사드 둘뿐이다. 그 밖의 내부 메서드에 기대던 코드가 있으면 지금 옮긴다. statements(code, scope="separate")가 이제 실제로 별도 재무제표를 돌려준다. 연결 기준 값에 맞춰 둔 것이 있으면 다시 본다. 삼성전자 기준 자기자본이 201 조에서 133 조로 바뀐다.- 전종목 스캔 결과의 행 순서가 종목코드 기준으로 고정됐다. 순서가 실행마다 달라지던 것에 우회를 넣어 뒀다면 걷어내도 된다.
- 회계 기간 표기
"2026"은 그 해 전체를 뜻한다. 연말 시점으로 읽어 미래 판정하지 않는다.