5.1.49와 5.1.50은 배포되지 않았으며, 해당 변경 사항은 이번 릴리즈에 함께 포함됩니다.
세션 시작과 작업 RPC 연결이 더 이상 작업 호스트의 생존 확인(liveness probe)을 기다리지 않습니다. 복구는 호스트별로 독립적으로 실행되며, 종료 이후에는 자식 작업을 점유하거나 되살리지 않고, 더 최신의 소유권 주장(ownership claim)은 그대로 유지합니다. (#11335) DAG 복구와 workpool 정합(reconciliation)은 이제 같은 세션 시작 정합을 공유 게이트(하나의 게이트)로 기다리되, admission을 점유하지 않습니다. 이에 따라 일시 중지된 DAG의 복구 가능한 자식이 고아로 잘못 판정되지 않고, 고아 워커의 대기 중인 workpool 항목은 delivery_uncertain으로 표시되지 않고 다시 전달됩니다. (#11525)
세션이 이미 삭제된 동기 작업을 이어서 진행하면, 이제 30분 동기 폴링 타임아웃을 기다리지 않고 즉시 새 작업을 시작하라는 오류와 함께 실패합니다. 서버가 세션을 계속 "찾을 수 없음"으로 보고하는 경우에도 동기 폴링이 중단됩니다. 완료된 동기 작업 세션은 고정된 10분 대신 background_task.taskCleanupDelayMs 설정을 따릅니다. @orgito님이 제보해 주셨습니다. (#11524, #11520 수정)
문서 셸 변경 이후 omo.dev 배포가 다시 동작합니다. /design 쇼케이스가 자체 루트 레이아웃이 되면서 기존에 상속받던 시간 단위 재검증(revalidation)을 잃었습니다. 그 결과 사전 렌더링된 페이지 하나에 만료 시간이 없었고, 배포의 에셋 보존 검사가 빌드를 거부했습니다. 디자인 레이아웃은 사이트의 1시간 HTML 수명 안에서 다시 1시간마다 재검증합니다. (#11587, #11585 수정)
릴리즈 PR은 다음 릴리즈의 changelog 프래그먼트가 컷 이후 기준 브랜치에 추가되더라도 더 이상 changelog 게이트에서 실패하지 않습니다. (#11574)
프론트엔드 스킬이 디자인 리뷰어가 확인하는 10가지 원칙에 따라 작업하도록 바뀌었습니다. 새 화면, 리디자인 또는 디자인 시스템을 설계하기 전에 가이드라인 원문을 전부 읽고, 페르소나와 여정 단계별 이상적인 상태를 정의하며, 모든 격차를 원장(ledger)에 기록합니다. 컨트롤은 모든 상태에서 같은 박스 크기를 유지하며, 스피너나 화살표가 패딩을 추가하지 않습니다. 포인터 타겟은 최소 24px이고, 색상 역할이 컴포넌트보다 먼저 정의됩니다(shadcn/ui 구조 기반). 브리프가 요청하지 않는 한 글래스 효과와 날짜가 드러나는 트렌드 표면은 사용하지 않으며, 제거(subtract) 단계에서는 컨트롤 개수를 셉니다. 모든 UI 또는 디자인 시스템 산출물은 기준별 WCAG 2.2 AA 결과를 명시합니다. (#11536, #11534 수정)
macOS 컴퓨터 사용 기능은 엔진이 호출 도중 죽더라도 누르고 있던 키와 버튼을 해제합니다. 누르기 입력 요청이 들어오면 이제 엔진 바이너리를 숨김 해제 헬퍼(hidden release helper)로 다시 실행하고, 모든 누르기, 드래그 이동, 해제 이벤트를 이 헬퍼로 스트리밍합니다. 엔진이 종료되거나 충돌하거나, 요청이 무언가를 누른 상태로 풀려나면, 헬퍼가 같은 경로를 통해 (2초 이내에) 해제 이벤트를 보냅니다. 단, 사용자가 실제로 누르고 있는 키나 버튼은 사용자에게 맡깁니다. 헬퍼는 자체 세션에서 실행되며, 그룹 종료 시 전달되는 hangup과 terminate 신호를 해제가 끝날 때까지 무시합니다. 또한 자신을 생성한 엔진이 부모이고 스트림에 생성별 토큰이 포함된 경우에만 실행됩니다. 다른 플랫폼은 변경되지 않습니다. (#11535)
사용 가능한 로그인이 없는 provider의 프로세스 자식 작업은 실패하는 대신 다음 provider로 넘어갑니다. 엔진이 자식의 첫 프롬프트를 provider_credentials_missing 또는 provider_credentials_expired로 거부하면, 작업은 해당 provider의 나머지 모델을 건너뛰고 fallback 체인의 다음 provider에서 시작합니다. 다른 대안이 없으면 부모 세션의 모델에서 끝납니다. 각 이동은 provider 이름이 포함된 task_model_fallback 이벤트로 기록됩니다. 엔진이 이 코드를 보내지 않으면 이전과 완전히 동일하게 동작합니다. 프로세스 모드에서 그 밖의 방식으로 첫 프롬프트가 거부된 경우에도 이제 엔진이 검증한 오류 코드가 task_start_failed 이벤트와 시작 실패 메시지에 cause_code로 포함됩니다(예: host_refused: host_memory_pressure). 이는 진단용이며 작업의 동작을 바꾸지 않습니다. (#11440, #10806의 일부) (#11525)
서브에이전트로 보내는 대기 중 steer는 자식 경계를 넘어서도 자신의 id를 유지하며, 확인 응답이 유실된 경우 다시 전송하기 전에 먼저 확인합니다. 아직 시작 중인 자식을 위해 대기열에 들어간 메시지는 대기열에 들어갈 때의 id로 전달되므로, 재시작 후 반복된 drain은 두 번째 복사본을 전달하지 않고 재생됩니다. 자식의 확인 응답이 유실되면 omo는 자식에게 해당 id를 보유하고 있는지(get_pending_inputs) 묻습니다. 보유 중이면 완료 처리하고, 보유하지 않으면 같은 id로 다시 보내며, 응답을 읽을 수 없으면 추측하지 않고 불확실 상태를 유지합니다. (#11427, sisyphuslabs/omo-desktop-app#2838의 일부) (#11525)
모델 프로필 알림이 더 이상 모델에 전달되지 않습니다. "model profile ... has no available model" 같은 알림이 대화의 일부로 전송되어, 모델이 사용자의 첫 메시지보다 먼저 이를 읽었고, 시작이 느린 경우 추가 모델 요청 비용이 들 수도 있었습니다. 이제 알림은 대화 밖에 머무릅니다. 조치가 필요한 경우 데스크톱 앱이 다음 단계(Provider 인증 설정에서 로그인하거나 컴포저에서 모델 선택)와 함께 알림을 표시하며, 헤드리스 실행은 이를 로그로 남깁니다. 작동하는 provider를 대신 사용했지만 저장된 로그인이 실패한 경우에도, provider 이름과 함께 다시 인증하라는 알림이 여전히 표시됩니다. 레지스트리에서 더 이상 찾을 수 없는 프로필 모델은 다른 모델을 선택하라는 단계와 함께 보고됩니다. (#11365, #11525)
메모리 읽기 권한 부여가 이제 raw-string 도구가 실제로 여는 파일을 확인합니다. 경로를 정규화하기 전에 네이티브 파일시스템 탐색을 따라 포함 여부를 확인하므로, 디렉터리 심볼릭 링크 뒤에 ..가 오는 경우 프로젝트 메모리 권한이 다른 신원으로 리디렉션될 수 없습니다. 내장 도구는 기존의 해석된 경로 동작을 유지하며, 누락된 노트도 기존의 정규 상위 경로를 통해 계속 읽을 수 있고, 같은 디렉터리의 대소문자 별칭도 계속 허용됩니다. (#11339) (#11525)
완료된 Momus 리뷰 판정이 이제 계획 파일 옆에 번호가 매겨진 Markdown 산출물로 저장됩니다. 각 .omo/plans/{plan}.reviews/NNN-okay.md 또는 NNN-reject.md 산출물에는 판정, 타임스탬프, 모델, 계획의 sha256, 리뷰 소요 시간, 리뷰어 세션 id, 판정 블록이 기록됩니다(판정 앞의 추론 과정은 저장되지 않습니다). 따라서 세션이 끝나도 완료된 리뷰가 남습니다. 계획 옆에 작성되는 .gitignore가 .reviews 디렉터리를 사용자의 스테이징 영역에서 제외합니다. Momus 자체는 여전히 읽기 전용이며, 저장은 리뷰 결과가 반환된 후 오케스트레이터 쪽에서 전적으로 이루어집니다. (#11237, #3002 수정) 이 기여를 해주신 @surlymochan님께 감사드립니다. (#11525)
릴리즈 바이너리는 최대 200 MiB까지 허용되며, 5.1.49는 배포되지 않았습니다. omo 5.1.49의 Linux 바이너리가 182 MiB 크기 예산을 초과했습니다(linux-x64 200.0 MB, linux-arm64 198.2 MB). 이로 인해 해당 릴리즈는 아무것도 배포되기 전에 중단되었습니다. 증가 원인은 Bun 1.4.4 런타임 자체입니다. 빈 컴파일된 Bun 프로그램은 Bun 1.4.3에서 1.4.4 사이에 90.8 MB에서 109.1 MB로 커졌으며, 5.1.48 이후 omo가 추가한 모든 것은 약 0.46 MB입니다. 릴리즈가 CI에서 테스트하는 Bun 버전을 계속 배포할 수 있도록 예산을 182 MiB에서 200 MiB로 올립니다. (#11491) (#11525)
모든 omo.dev 페이지가 이제 자신의 언어와 다크 컬러 스킴을 선언하며, 건너뛰기 링크(skip link)로 시작합니다. 한국어, 일본어, 중국어 및 기타 로케일은 <html lang>을 해당 언어로 설정하고(이전에는 항상 영어였습니다), 폼 컨트롤과 스크롤바가 다크 테마로 렌더링됩니다. 처음 Tab을 누르면 "Skip to content"가 나타나며, 포커스된 컨트롤이 고정 헤더 아래에 가려지지 않습니다. 알 수 없는 페이지는 독자의 언어로 된 404를 표시합니다. (#11498)
omo.dev 문서 검색창에 뚜렷한 테두리와 실제 레이블이 생겼습니다. 테두리가 3:1 대비 기준을 충족하며(이전에는 1.2:1이었습니다), 스크린 리더는 플레이스홀더 대신 "Filter documentation sections"라고 안내합니다. 섹션 목록에도 별도의 이름이 붙었습니다. (#11492)
omo.dev의 아이콘 버튼은 키보드 포커스 시 레이블을 표시하며, Escape로 모바일 메뉴를 닫을 수 있습니다. 워크플로 그래프의 Fit 및 Center 버튼에 실제 툴팁이 생겼습니다(마우스 오버와 포커스 시 표시되고, Escape로 닫힙니다). Escape를 누르면 모바일 내비게이션 시트가 닫히고 포커스가 메뉴 버튼으로 돌아갑니다. (#11490)
omo.dev의 흐려진 그래프 노드와 약한 레이블을 다시 읽을 수 있습니다. 워크플로 그래프에서 강조된 경로에서 벗어난 노드는 20%로 흐려지는 대신 색상으로 물러나며(텍스트 대비가 1.1:1에서 5.8:1로 향상), 데모의 단계 번호와 수정된 단어는 더 이상 장식용 회색을 사용하지 않습니다. (#11488)
opencode 에디션의 스킬 도구가 OpenCode가 이미 나열한 스킬 설명을 반복하지 않습니다. OpenCode 코어 자체의 스킬 목록에 같은 스킬(같은 이름, 같은 파일)이 설명과 함께 있을 때에만 스킬 도구의 항목 목록에서 제외되므로, 설명은 요청당 두 번이 아니라 한 번만 전송됩니다. 코어가 나열하지 않는 스킬(평면 .md 스킬, 이름이나 설명이 없는 스킬, 비활성화 플래그나 사용자 지정 Claude 설정 디렉터리 때문에 코어가 건너뛰는 스킬, OMO 번들 스킬)은 스킬 도구 목록에 그대로 남습니다. 코어의 목록을 읽을 수 없는 경우에는 아무것도 제외되지 않습니다. (#11456)
provider 로그인 페이지에 OmO 로고가 표시됩니다. 모든 omo 실행 경로(npm, 컴파일된 바이너리, 로컬 런처)가 브랜드가 포함된 OmO 아이콘을 엔진에 전달하므로, provider 로그인 후 브라우저에 표시되는 페이지에 이름만이 아니라 OmO 마크도 나타날 수 있습니다. 로고는 omo가 senpi#4432와 #4434를 포함하는 senpi 릴리즈를 고정(pin)한 후에만 나타납니다. 현재 고정된 senpi(2026.10.27-1)는 이를 무시합니다. (#11445, #11444 수정)
릴리즈 준비 과정이 자체 테스트에서 더 이상 실패하지 않습니다. changelog 스탬프 일치 테스트가 changes/unreleased를 무조건 읽었는데, 릴리즈 상태의 트리는 모든 프래그먼트를 소비하고 해당 디렉터리가 없으므로 모든 릴리즈 PR에서 테스트가 충돌했습니다. 이제 디렉터리가 존재할 때에만 실제 프래그먼트를 읽습니다. (#11443)
LazyCodex 버그 수정 스킬이 이제 소스를 소유한 저장소로 수정 사항을 보냅니다. lcx-contribute-bug-fix는 에이전트에게 LazyCodex 소유 결함을 code-yeongyu/lazycodex 미러에 패치가 포함된 검증된 수정 이슈로 만들도록 안내했습니다. 그래서 여기에 이미 열린 리드 PR로 존재하던 수정이 미러에 전체 diff로 다시 등록되었습니다. 이제 스킬은 먼저 작성자의 열린 PR을 여러 저장소에서 검색한 뒤, code-yeongyu/oh-my-openagent(base dev, packages/omo-codex/plugin/... 경로, changelog 프래그먼트)에 대해 포크 PR을 엽니다. 미러에는 PR이 생성되지 않으며, 필요하다면 이를 링크하는 짧은 이슈만 생성합니다. lcx-report-bug도 같은 방식으로 수정 사항을 라우팅합니다. 업스트림 openai/codex 라우팅은 변경되지 않습니다. (#11410)
연구 사실 위치 지정자(fact locator)가 이제 원본 스냅샷 바이트에 연결됩니다. 소스 스냅샷은 가져온 바이트를 raw.bin으로 보관합니다. --text 파일만 있는 경우 변환 전용 소스가 되어 경고가 붙은 인용은 지원하지만 측정된 행은 지원하지 않습니다. --raw <bytes> --text <extraction>은 선언된 추출 결과 옆에 원본을 유지합니다. 페이지 위치 지정자는 독자에게 보이는 텍스트 노드만 읽고(속성, 스크립트, 스타일, 숨겨진 요소는 제외), 소스 자체 인코딩 기준의 바이트 오프셋을 기록합니다. 인용된 스냅샷을 읽을 수 없으면 fact verify가 안전하게 실패(fail closed)합니다. 새 source refresh 명령은 다시 가져온 소스를 다시 고정(repin)하고, 인용문과 문맥을 기준으로 해당 행을 다시 연결합니다. 새로고침된 소스의 레거시 행은 다시 연결되지 않은 것으로 나열되며, 검사되지 않은 채 통과하는 대신 검증을 차단합니다. (#11287)
연구 수집 과정이 이제 텍스트 변환으로 바뀐 숫자를 찾아내며, 이를 등록하지 않습니다. source probe-conversion은 하나의 그룹 숫자 문법으로 숫자 다중집합(multiset)을 비교합니다(각주 숫자가 12,345에 붙은 경우 보고하며, 단독 1.234는 소수로 처리합니다). 표 셀, 행, 목록 항목, 줄바꿈을 가로질러 숫자를 묶지 않으며, 링크 대상, 이미지 소스, 대체 텍스트, 제목에서 복사된 숫자는 Markdown 링크나 이미지 문법 안의 숫자만 대응시킵니다. 변환기의 순서 목록 마커(원본에 해당 <ol> 항목이 있는 경우에만, 느슨한 1. 1. 1. 번호 매기기 포함)와 숫자형 참조 링크 레이블, 각주 정의 레이블, 줄바꿈으로 나뉜 숫자 그룹은 숫자가 아니라 변환 문법으로 취급합니다. 변환기가 추가하는 강조, 코드, 제목 있는 링크, 이미지, 이스케이프 마크업을 거쳐 부호를 읽습니다(**2019**-2023은 범위입니다). 이름 있는 참조는 양쪽에서 하나의 표로 디코딩합니다(−,  ). 변환기가 유지하는 원시 인라인 HTML(10<sup>-5</sup>, 크기가 지정된 <img>)은 원본 자체의 태그로 읽습니다. 참조 제목이 다음 줄에 있어도 허용하며, 한국어 텍스트, 단일 문자, 지수에 붙은 마이너스나 en dash로 쓰인 마이너스도 계산합니다. source snapshot은 변경된 숫자를 출력하며, fact add는 소스의 변환이 값을 바꾼 경우 conversion_altered_number와 함께 그 값을 거부합니다. 복구 방법은 source snapshot --id S<n> --text <verified.txt> --replace이며, 활성 행이 소스를 인용하는 동안에는 거부됩니다. fact-ledger 참조 문서는 프로브가 보장하는 범위를 명시하고, 범위 밖 항목(쇼트코드, LaTeX, CommonMark가 아닌 표)을 나열합니다. 이 항목들은 항상 변경된 것으로 보고됩니다. 두 연구 에디션 모두 이 흐름을 설명하며, 기존 단계별 지침은 이제 집중된 참조 문서에 있습니다. (#11286)
Skill MCP 클라이언트가 MCP 2026-07-28 서버를 사용할 수 있습니다. 최신 서버는 초기화 핸드셰이크 없이 탐색 정보와 요청별 프로토콜 메타데이터를 받습니다. Skill MCP는 elicitation을 지원하지 않으므로, 입력이 필요한 작업은 명확한 오류와 함께 중단됩니다. 레거시 서버는 기존 초기화 협상 전에 탐색 프로브를 받습니다. 시간 초과된 프로브는 fallback을 로그에 남기며, 서버당 프로세스당 한 번만 비용이 듭니다. 이후 해당 서버에 대한 연결은 바로 레거시 초기화로 진행합니다(레거시 초기화가 실패하면 이 기억은 지워집니다). 지원되지 않는 버전으로 fallback할 때는 레거시 서버의 기능과 신원이 유지됩니다. (#11243, #11205의 일부)
데스크톱 엔진 MCP 서버도 MCP 2026-07-28 클라이언트를 지원합니다. 탐색과 요청별 프로토콜 메타데이터가 초기화 없이 작동합니다. 최신 결과는 서버와 완전한 결과 타입을 식별하며, 도구 목록에는 캐시 힌트가 포함됩니다. 지원되지 않는 요청 버전은 데몬에 접근하기 전에 거부되고, 알림에는 응답하지 않으며, 레거시 초기화는 기존 지원 버전 협상을 그대로 유지합니다. (#11239, #11205의 일부)
skill_mcp는 세션 abort 신호를 MCP 요청에 전달하며, 요청은 abort 사유와 함께 즉시 거부됩니다. HTTP MCP 서버의 요청과 SSE 스트림도 연결이 끊어질 때까지 열려 있는 대신 닫힙니다. (#11592)/와 \ 모두 물리적 경로 탐색을 나누므로, link/.. 표기는 어휘적으로 접히지 않고 링크를 따라갑니다(심볼릭 링크 탈출이 허용되던 문제를 수정). .omo -> docs\plans 같은 심볼릭 링크 또는 정션 계획 디렉터리는 다시 인식되며, 8.3 짧은 이름, 드라이브 문자 대소문자, 디렉터리 대소문자가 모두 하나의 정규 경로로 해석됩니다. 계획 내부 여부 확인은 정규 경로를 정확히 비교하므로, 대소문자 구분 디렉터리에서 대소문자만 다른 항목은 서로 구별된 상태를 유지합니다. (#11548)omo logout은 이제 작은 로그아웃 메모를 남깁니다(자격 증명은 없고 기기와 시간만 포함). 이를 통해 OmO Desktop은 의도적인 로그아웃과 아직 응답하지 않는 자격 증명 저장소를 구별할 수 있습니다. omo account token과 export는 이를 종료 코드 10으로 보고하며, 종료 코드 4는 여전히 아무것도 읽을 수 없었음을 뜻합니다. 다시 로그인하면 메모가 제거됩니다. 메모는 자격 증명을 제거하기 전에 기록되므로, 기록에 실패하면 로그인 상태가 유지되고 omo logout이 오류를 보고합니다. 손상된 메모는 무시되며(종료 코드 4), omo account show를 절대 깨뜨리지 않습니다. (#11441, #11434 수정) (#11525)task 자식이 받는 마지막 단계와 같습니다. 모델은 workflow가 시작될 때 캡처되어 실행에 보관되므로, 재시도되거나 복구된 노드도 이를 유지합니다. (#11439) (#11525).. 경로, 별칭이 지정된 프로젝트 루트, hashline 이름 변경, 패치 이동이 포함됩니다. 패치 헤더는 인가된 작업이나 대상을 바꾸지 않고, 지원되는 실행기 파서를 통해 왕복(round-trip)해야 합니다. 이름 변경과 삭제는 명명된 최종 링크를 유지하며, 내용 쓰기는 허용된 대상만 따릅니다. 물리적 계획 디렉터리는 사용자가 선택한 어떤 이름이든 가질 수 있습니다(예: .omo -> docs/plans). 단, 실제 프로젝트 루트 내부에 엄격히 있어야 하며, 루트 자체나 상위 디렉터리일 수 없습니다. .omo 경로 세그먼트는 파일시스템 고유의 대소문자로 일치합니다. 모든 거부는 구체적인 사유와 함께 기록됩니다. 중첩 계획과 상위 폴더 Windows 경로는 계속 지원됩니다. 필수 인수 재작성은 호스트가 보관한 인수에 적용할 수 없으면 안전하게 실패합니다. (#11424)__tests__ 또는 *_test 폴더를 더 이상 포함하지 않습니다. 스킬 최상위의 test/와 tests/ 폴더만 테스트 폴더 필터에서 제외되며, 이전에는 최상위 폴더 이름이라면 무엇이든 필터를 빠져나갔습니다. (#11398, #11393 수정)apply_patch Add, Update, Delete, Move 대상을 확인합니다. 비어 있거나 분류할 수 없는 헤더는 안전하게 실패합니다. (#11392)OPENCODE_SERVER_PASSWORD가 설정되지 않은 경우 omo run은 실행마다 다른 비밀번호로 OpenCode 서버를 시작합니다. 따라서 다른 localhost 포트의 웹 페이지가 이를 조작할 수 없습니다. 실행 외부에서 해당 서버에 연결하려면 이제 비밀번호가 필요합니다. (#11370)data-fact-mode 속성 삭제도 여전히 차단됩니다. 값 뒤에 오는 가장 긴 단위가 확인 대상이 되므로, 행의 단위로 시작하는 더 긴 단위("12% 포인트", %행의 "12 percent points")는 차단되고, 다른 통화 기호 옆의 일반 단위 단어("$320 pounds")도 차단됩니다. (#11301)<out>.polished.fill-map.json에 유지합니다. 다듬기 이전의 fill 맵은 다시 쓰이지 않으므로(따라서 같은 자리에서 다듬은 뒤에도 fact pairs --changed-since는 변경된 모든 문장을 다시 확인합니다), 보고서와 맞지 않는 fill 맵은 거부되고, fill 맵이 없는 에디션은 변경된 브리프를 우회할 수 없습니다. (#11290)fact derive --now)이 필요합니다. 이것이 없으면 명령은 missing_now와 함께 거부합니다. 원장 검증 오류는 그대로 보존됩니다. 정확한 인용 규칙, 음의 0, 원본 값 렌더링, 자리표시자 식별자, 리터럴 중괄호 안내가 수정되었습니다. (#11290)bun run knip:check, knip 6.43.0). dev에 이미 있는 발견 사항은 knip.jsonc에 각각의 이유와 함께 범위가 지정된 ignore로 등록됩니다. (#11481, #11433 수정)<hash>.N 이름을 따라가고 첫 실패에서 멈춥니다. 따라서 고아 파일, 잘못된 이름의 파일, 간격 뒤의 파일은 절대 신뢰되지 않습니다. 아직 아무것도 이를 사용하지 않습니다. (#11430, #10762의 일부)os-release에서 배포판이 생성한 TLS 번들 하나만 선택합니다(Debian, Fedora, SUSE 계열. 계열 간 대체는 없음). 8 MiB 상한과 대체 문자 검사로 읽습니다. 아직 아무것도 이를 사용하지 않습니다. (#11407, #10762의 일부)NODE_USE_SYSTEM_CA를 통해 OS 저장소를 신뢰합니다. (#11405, #10762의 일부).omo 아래에 이미 있는 하드 링크가 .omo 밖의 파일과 inode를 공유할 수 있습니다. realpath는 inode 격리를 제공하지 않습니다. (#11424)tool.execute.before와 도구의 open 사이에 TOCTOU가 존재합니다. 이 경쟁 상태를 해결하려면 도구 측의 O_NOFOLLOW와 디렉터리 핸들 기반 제한이 필요합니다. (#11424)분량 관계로 이후 내용은 번역에서 제외했습니다. 전체 내용은 위 원문 링크에서 확인하세요.