Skip to content

DeepSeek Harness Trajectory 로그 읽는 법

Trajectory · 세션 로그 · tool/call · 문제 해결

cwd와 agentPreset을 먼저 읽고, tool/result가 없는 tool/call을 찾으세요.

DeepSeek Harness Trajectory 로그를 세션 헤더에서 짝 없는 tool/call까지 읽는 장면

채팅 말풍선보다 세션 헤더를 먼저 읽기

실행이 실패한 뒤 DeepSeek Harness Trajectory 로그를 읽으려면, 마지막 말풍선을 건너뛰고 영구 세션 로그를 엽니다. JSONL 영속화 설명은 세션마다 추가 전용 논리 로그가 하나이고, 기본은 .jsonl.zstd, 압축을 끄면 원본 .jsonl이라고 합니다. 첫 논리 줄이 세션 헤더입니다. type: session과 함께 version, id, 선택적 cwd, createdAt, 선택적 parentSession, 필수 delegationDepth가 있습니다. agentPreset이 남는 이유는, 재개할 때 도구와 프롬프트를 그것이 정하기 때문입니다.

최상위 세션의 delegationDepth는 0입니다. 없거나 잘못되면 로그 전체가 거부됩니다. 0이 아니면 위임된 자식 세션 안입니다. 누른 프리셋에 없어야 할 도구 이름은 자식 쪽일 수 있습니다. parentSession은 위를 가리킵니다. cwd는 그때 묶인 작업 공간 루트이고, 세션 로그 입문이 먼저 묻는 질문입니다. 이 글은 그 질문이 이미 실패한 실행이 된 뒤의 읽는 순서입니다.

기본 브랜치의 영속화 카탈로그는 SESSION_FORMAT_VERSION을 0에 고정하고, 프리릴리스 형식은 호환을 약속하지 않는다고 적습니다. 이 사이트의 0.1.5 RC 메모는 세션 데이터가 올라간 뒤 옛 형식으로 읽을 수 없다는 이야기입니다. 둘은 같은 정수가 아닙니다. 디코드한 헤더의 version을 읽으세요. 다른 세대용으로 쓴 자체 리더라면 리더를 고칩니다.

그다음 각 줄은 저장 레코드 하나입니다. 디코드 뒤 순번은 연속입니다. 인덱스 i의 이벤트는 seq === i입니다. 빈칸은 리더가 줄을 버린 표시입니다. 묶인 chunk이거나 모르는 플러그인 이벤트인 경우가 많고, 모델이 기록을 지운 것이 아닙니다. 하위 플러그인은 영속화 카탈로그에 없는 타입을 합칠 수 있습니다.

tool/call마다 tool/result를 맞추기

카탈로그는 이벤트를 서피스와 로그만으로 나눕니다. 서피스만 LLM 메시지가 됩니다. 이번에 볼 것은 user/message, assistant/message, tool/result입니다. tool/call은 로그만입니다. 채팅보내기는 결과 본문을 보여 주고, 모델이 낸 원문 인자는 숨길 수 있습니다.

tool/call은 turn, step, callId, name, arguments를 갖습니다. arguments는 모델이 그대로 낸 JSON 문자열이고, 파싱되지 않았습니다. callId로 tool/result와 짝을 짓습니다. 결과는 turn, step, 도구 결과 메시지, 선택적 error(name과 code), 선택적 meta입니다. meta는 JSON이어야 합니다. 파일 도구 dsh-tool-fs는 결과 시점의 차이를 여기에 둘 수 있습니다. 다른 도구에 meta가 없는 것은 정상입니다.

호출은 끝에서부터 따라갑니다. 실패는 대개 결과가 없는 마지막 callId이거나, error가 있는 결과입니다. 플러그인 세 개를 동시에 열지 마세요. name이 실을 생각이 없던 도구라면, 다시 묻기 전에 플러그인 보안 점검표에서 멈추세요.

TOOL_NOT_STARTED와 TOOL_OUTCOME_UNKNOWN으로 갈라진 세션 시간축

TOOL_NOT_STARTED인가 TOOL_OUTCOME_UNKNOWN인가

세션 코어 설명에는 회복용 두 문장이 있습니다. 동의어가 아닙니다.

  • TOOL_NOT_STARTED — 어시스턴트 쪽 도구 요청은 있으나, 영구적인 tool/call이 기록되지 않았습니다. 업스트림 표현으로는, Harness가 시작으로 기록하기 전에 끊겼고, 아직 필요하면 다시 시도할 수 있습니다. 도구가 돌았다는 증거는 없습니다.
  • TOOL_OUTCOME_UNKNOWN — 영구적인 tool/call은 있고 결과는 기록되지 않았습니다. 결말은 알 수 없습니다. 다시 시도해도 되는 것은 읽기 전용이거나 멱등인 작업뿐입니다. 부작용이 있을 수 있으면 먼저 바깥 상태를 확인하거나 사용자에게 묻세요. 맹목적으로 다시 시도하지 마세요.

셸은 같은 모양에 타입이 다릅니다. command/run은 commandId로 command/done과 짝이고, command/run은 로그만입니다. run은 있고 done이 없으면, 결과 없는 호출의 셸 버전입니다. 「다시」를 보내기 전에 작업 공간을 보세요.

llm/retry도 로그만입니다. 실패한 요청 뒤의 제공자 재시도 하나입니다. 실패한 모델 요청에는 assistant/message가 없습니다. 채팅이 갑자기 잠잠해 보이면, 도구를 탓하기 전에 llm/retry나 빠진 어시스턴트 메시지를 찾으세요. 사용량이 있으면 타입이 usage인 assistant/chunk입니다. 사용량 chunk가 없을 때만 assistant/message.usage로 돌아갑니다.

채팅이 숨기는 로그만 줄

승인은 감사이지 말풍선이 아닙니다. approval/asked와 approval/decided는 같은 id를 쓰고, 둘 다 로그만입니다. 묻지 않고 셸이 돌았다고 말하기 전에 이 두 줄을 찾으세요. 프리뷰의 버튼 문구는 움직입니다. 오늘 카탈로그가 이름 붙인 것은 이 이벤트 타입입니다.

같은 블록의 assistant/chunk 델타가 세 개 이상 이어지면 한 줄의 묶음이 될 수 있습니다. text-chunks, reasoning-chunks, tool-call-chunks입니다. 슬래시가 없어 이벤트 타입이 아닙니다. 읽을 때 풀어집니다. 줄 수가 최대 seq보다 적어도, 묶음 줄이 있으면 기록이 잘린 것이 아닙니다.

로그 이벤트는 Cordis 이벤트가 아닙니다. 카탈로그는 라이브 버스를 별도의 session/event 방출이라고 적습니다. 플러그인 소스에서 Cordis 훅을 grep해도 영구 줄은 나오지 않습니다.

십 분 순서

1. 로그를 디코드합니다(.jsonl.zstd를 존중). 헤더의 cwd, agentPreset, delegationDepth, version을 읽습니다.
2. 디코드 뒤 seq가 연속인지 확인합니다. 아니면 빈칸을 해석하기 전에 리더를 고칩니다.
3. tool/result가 없는 마지막 tool/call, 또는 error가 있는 결과를 찾습니다.
4. 다시 시도하기 전에 빈칸을 TOOL_NOT_STARTED 또는 TOOL_OUTCOME_UNKNOWN으로 나눕니다.
5. 이름이 뜻밖이면 마지막으로 넣은 플러그인을 뺍니다. 다음 것을 더하지 마세요.
6. 결함에는 callId, name, 헤더 version을 적습니다. 마지막 사과문 스크린샷은 템플릿이 아닙니다.

이 순서가 정하지 않는 것

이것은 비행 기록 장치를 남기는 이유에 대한 글이 아닙니다. 그것은 세션 로그 입문에 있습니다. 느린 길은 관측성 튜토리얼입니다. agentPreset의 이름은 모드가 말하는 그대로입니다. 이 글은 Standard와 PTC를 고르지 않습니다. 「UI는 켜져 있고 도구는 전부 맹목」은 빠진 tool/result가 아니라 문제 해결입니다.

쓰는 태그의 헤더 version이나 타입 이름이 위에 링크한 카탈로그와 다르면, 그 태그가 이깁니다. 프리뷰 호환은 일부러 깨집니다. DSH 버전과 플러그인 SHA를 같은 메모에 적고, 절반만 디코드한 로그로 결함을 내지 마세요.

포털에서 계속

설치 가이드, 튜토리얼, 플러그인 디렉터리로 이어서 보세요.