원격 큐

2026-10-14 현재 원격 큐(remote.py와 dira remote 명령)는 구현 중입니다. 이 장은 완성된 동작을 기준으로 씁니다. 터미널이 command not found: dira를 내면 셸이 dira를 찾지 못한 것이니 아래 연결하기의 PATH 안내를 보세요. dira remote: 클라이언트가 설치되지 않았습니다가 나오면 원격 큐가 아직 설치본에 들어오지 않은 것입니다.

웹 서비스에서 누른 작업을 내 컴퓨터의 dira가 받아서 돌립니다. 서버는 작업을 만들어 나눠 주기만 하고 모델을 돌리지 않습니다. 세션은 이 컴퓨터에서 돌고, 결과물과 온톨로지 원본도 이 컴퓨터의 큐에 남습니다. 온톨로지는 사본도 서버에 올리지 않습니다. 웹이 보여 달라고 할 때마다 이 컴퓨터가 읽어서 답합니다(웹에서 온톨로지를 볼 때).

연결은 프로젝트 하나씩 합니다. 연결하지 않은 프로젝트는 지금과 똑같이 돕니다. 큐 루트에 remote.json이 없으면 원격 동작은 아무것도 하지 않고 끝납니다.

서버는 이 컴퓨터를 런타임 단위로 봅니다. 런타임은 컴퓨터 하나와 워크스페이스 하나의 짝이고, 그 워크스페이스에 연결한 프로젝트는 모두 그 런타임 하나에 붙습니다. 같은 컴퓨터에서 프로젝트 셋을 같은 워크스페이스에 연결하면 서버에는 런타임 하나와 그 아래 프로젝트 셋이 보입니다.

연결하기

터미널에서 연결할 프로젝트의 큐 루트를 지정해 실행합니다. <server>는 웹 서비스가 알려 주는 주소입니다.

dira remote connect <server> --root ~/Projects/myproject/.dira
sh

dira 명령은 ~/.config/dira/bin에 있습니다. 셸이 zsh나 bash라면 dira 앱을 한 번 켜는 것으로 충분합니다. 앱은 켜질 때 이 디렉터리를 PATH에 더하는 블록(# >>> dira >>>로 시작합니다)을 zsh면 ~/.zshrc, bash면 ~/.bash_profile 끝에 한 번 덧붙입니다. 이미 열려 있던 터미널 창은 이 블록을 읽지 않았으니, 앱을 켠 뒤 새 창을 열어서 실행하세요. 파일에 .config/dira/bin이 이미 있으면 앱은 그 파일을 건드리지 않습니다.

앱 없이 엔진만 쓰거나 fish 같은 다른 셸을 쓰면 줄 하나를 직접 넣어야 합니다. 아래 명령은 줄이 이미 있으면 아무것도 하지 않으므로 두 번 실행해도 됩니다.

# zsh (bash라면 ~/.zshrc 대신 ~/.bash_profile)
grep -qs '.config/dira/bin' ~/.zshrc || echo 'export PATH="$HOME/.config/dira/bin:$PATH"' >> ~/.zshrc

# fish
fish_add_path ~/.config/dira/bin
sh

새 터미널 창에서 command -v dira를 실행해 /.config/dira/bin/dira로 끝나는 경로가 나오면 준비가 끝난 것입니다.

  1. 명령이 확인 코드(user_code)와 주소(verification_uri)를 찍습니다.
  2. 브라우저에서 그 주소를 열고 확인 코드를 넣어 승인합니다. 승인한 워크스페이스에 이 컴퓨터가 붙습니다.
  3. 명령은 그동안 서버에 승인 여부를 계속 묻다가, 승인되면 나머지를 알아서 합니다. 코드의 유효 시간이 지나면 rc 1로 끝나니 처음부터 다시 실행하세요.

승인된 뒤 명령이 하는 일은 넷입니다.

  • 자격 증명을 ~/.config/dira/remote/<workspace_id>/credentials.json(권한 0600)에, 연결 설정을 큐 루트의 remote.json에 씁니다. 자격 증명은 워크스페이스마다 하나입니다.
  • 이 컴퓨터를 그 워크스페이스의 런타임으로 등록하고, 런타임 id를 같은 디렉터리의 runtime.json에 적습니다. 등록할 때 ~/.config/dira/bin/engines/에 있는 AI 도구(claude codex agy grok)의 이름과 버전을 함께 알리고, 도구마다 로그인을 한 번 점검합니다.
  • 그 큐에 워커가 없으면 workers/w1.sh를 만들고 crontab 두 줄을 넣습니다. 이 컴퓨터에 시계 두 줄이 없으면 그것도 넣습니다.
  • 마지막에 안내 두 줄을 찍습니다. 전체 디스크 접근 권한을 주는 것, 그리고 claude setup-token으로 장기 토큰을 받는 것입니다. cron이 띄운 세션은 이 둘이 없으면 돌지 못합니다. 자세한 절차는 인증에 있습니다.

프로젝트 하나에는 워크스페이스 하나만 붙습니다. 이미 연결된 프로젝트를 다른 워크스페이스에 연결하면 이 프로젝트는 이미 다른 워크스페이스에 연결돼 있습니다로 거절하고 rc 2로 끝납니다. 워크스페이스를 바꾸려면 먼저 끊으세요.

둘째 프로젝트 연결하기

같은 워크스페이스에 프로젝트를 하나 더 붙일 때는 확인 코드를 다시 받지 않습니다. 이 컴퓨터가 그 워크스페이스의 자격 증명을 이미 갖고 있으니 --root만 바꿔 같은 명령을 실행합니다.

dira remote connect <server> --root ~/Projects/second/.dira
sh

명령은 브라우저 승인 없이 런타임의 프로젝트 목록에 이 프로젝트를 더하고 바로 끝납니다. 첫 줄은 이렇게 나옵니다.

이미 연결된 워크스페이스 <workspace_id>에 프로젝트를 더했습니다
text

같은 서버에 연결된 워크스페이스가 이 컴퓨터에 둘 이상이면 어느 쪽에 붙일지 정할 수 없어서, 명령이 후보 id 목록을 찍고 rc 2로 끝납니다. 그중 하나를 --workspace로 골라 다시 실행하세요.

dira remote connect <server> --root ~/Projects/second/.dira --workspace <workspace_id>
sh

확인 코드를 일부러 다시 받으려면 --new를 붙입니다. 쓰는 경우는 둘입니다.

  • 아직 연결하지 않은 다른 워크스페이스에 이 프로젝트를 붙일 때. --new가 없으면 이미 연결된 워크스페이스에 붙습니다.
  • 명령이 저장된 자격 증명을 서버가 거절했다며 rc 1로 끝나고 --new로 다시 연결하라고 할 때.

--new로 받은 워크스페이스에 이미 런타임이 있으면, 새 자격 증명으로 런타임을 등록한 뒤 옛 런타임은 서버에서 지웁니다. 그 워크스페이스의 다른 프로젝트들은 새 런타임으로 옮겨 가고, 따로 다시 연결할 필요는 없습니다.

한 워크스페이스 안에서 프로젝트 이름은 겹칠 수 없습니다. 프로젝트 이름은 큐 루트의 부모 디렉터리 이름이라, 서로 다른 경로의 myproject/.dira 둘을 같은 워크스페이스에 연결하면 둘째가 같은 이름의 프로젝트가 이 워크스페이스에 이미 연결돼 있습니다: <queue_root>로 거절되고 rc 2로 끝납니다.

큐 루트를 다른 경로로 옮기면 그 프로젝트를 찾지 못합니다. 새 경로에서 다시 연결하세요.

이미 프로젝트마다 따로 연결해 둔 경우

예전 dira는 프로젝트마다 자격 증명을 따로 받아 런타임도 프로젝트마다 하나씩 만들었습니다. 이렇게 연결해 둔 프로젝트는 다시 연결하지 않아도 됩니다. 새 엔진의 시계가 처음 돌 때, 워크스페이스마다 아직 살아 있는 자격 증명 하나를 골라 남기고 나머지 런타임은 서버에서 지웁니다. 그 뒤로 서버에는 그 워크스페이스의 런타임이 하나만 남고, 프로젝트는 모두 그 아래에 붙습니다.

자격 증명이 모두 서버에서 거절되면 아무것도 바꾸지 않고 sync.log에 REMOTE unauthorized <workspace_id> 한 줄을 남깁니다. 이때는 그 프로젝트 중 하나를 --new로 다시 연결하세요.

끊기

dira remote disconnect --root ~/Projects/myproject/.dira
sh

끊으면 그 프로젝트만 빠집니다. 명령은 그 큐 루트의 remote.json과, 워크스페이스 디렉터리에서 그 프로젝트가 쓰던 하위 디렉터리를 지웁니다. 같은 워크스페이스에 다른 프로젝트가 남아 있으면 서버는 부르지 않습니다. 다음 살아 있음 신호에 그 프로젝트가 빠진 목록이 가고, 남은 프로젝트들은 그 런타임으로 계속 sync합니다.

끊은 프로젝트가 그 워크스페이스의 마지막 프로젝트였으면 런타임도 해제됩니다. 서버에서 런타임을 지우고, 워크스페이스 디렉터리의 runtime.json과 credentials.json을 지웁니다. 이 컴퓨터에 연결된 워크스페이스가 하나도 남지 않으면 crontab에서 시계 두 줄을 빼고, 읽기 프로세스도 내립니다.

워커의 crontab 두 줄은 그대로 둡니다. 워커는 계속 돌지만 이제 로컬 티켓만 처리합니다. 워커까지 멈추려면 cron 장대로 그 두 줄을 지우세요.

컴퓨터 시계

원격 큐를 하나라도 연결하면 crontab에 워커 줄과 별개로 이런 줄 두 개가 생깁니다.

* * * * * python3 "<홈>/.config/dira/bin/engines/remote.py" sync-all >> "<홈>/.config/dira/remote/sync.log" 2>&1
* * * * * sleep 30; python3 "<홈>/.config/dira/bin/engines/remote.py" sync-all >> "<홈>/.config/dira/remote/sync.log" 2>&1
text

저장소의 엔진으로 연결했다면 remote.py 자리에 그 엔진의 경로가 적힙니다. 두 줄이 짝을 이뤄 30초마다 sync-all을 한 번 실행합니다. 이것이 이 컴퓨터의 시계입니다. 프로젝트를 몇 개 연결하든 시계 줄은 컴퓨터에 한 쌍뿐입니다.

sync-all은 한 번 돌 때 두 가지를 합니다. 먼저 워크스페이스마다 서버에 살아 있음 신호를 한 번 보내고, 그다음 연결된 프로젝트마다 sync를 따로 돌립니다. 한 프로젝트의 sync가 실패하거나 20초 안에 끝나지 않아도 신호는 이미 간 뒤이고 다른 프로젝트의 sync도 계속 돕니다. 실패한 프로젝트는 다음 신호에 사유 한 줄을 붙여 보냅니다.

신호가 워커와 떨어져 있으므로 어떤 큐의 워커가 티켓을 고르기 전에 멈추거나 아예 돌지 않아도 웹 화면에서 이 컴퓨터가 끊긴 것으로 보이지 않습니다. 반대로 웹 화면에서 이 컴퓨터의 신호가 끊겼으면 시계부터 봅니다.

crontab -l | grep sync-all
tail -n 50 ~/.config/dira/remote/sync.log
sh

sync-all 줄이 없으면 원격에 연결된 프로젝트의 워커가 한 번 돌 때 다시 들어갑니다. 줄이 있는데 신호가 없으면 sync.log의 마지막 줄들이 이유를 말해 줍니다. 이 로그는 1 MB를 넘으면 sync.log.1로 옮겨지고 새로 시작합니다.

늘 떠 있는 읽기 프로세스

macOS에서는 시계와 별도로 프로세스 하나가 늘 떠 있습니다. 이름은 dev.dira.remote-reads이고, launchd가 띄우며 죽으면 다시 띄웁니다. 이 프로세스는 서버와 연결을 끊지 않고 열어 둔 채 웹에서 온 온톨로지 읽기 요청과 깨우기를 받습니다. 신호, 프로젝트 sync, 작업 받아 오기는 그대로 시계가 합니다.

원격 큐를 연결할 때 시계 두 줄과 함께 설치됩니다. 빠져 있으면 원격에 연결된 프로젝트의 워커가 한 번 돌 때 다시 들어갑니다. 살아 있는지는 이렇게 봅니다.

launchctl print gui/$(id -u)/dev.dira.remote-reads
tail -n 50 ~/.config/dira/remote/reads.log
sh

launchctl print가 서비스를 찾지 못하거나 출력에 state = running이 없으면 이 프로세스가 돌지 않는 것입니다. 그동안은 시계가 대신 받으므로 읽기와 깨우기가 멈추지는 않습니다. 다만 30초마다 약 1초씩 받지 못하는 틈이 생깁니다. macOS가 아닌 컴퓨터에는 이 프로세스가 설치되지 않고 늘 시계가 받습니다.

로그는 ~/.config/dira/remote/reads.log에 남고, 1 MB를 넘으면 reads.log.1로 옮겨집니다. 프로세스가 시작하기도 전에 실패하면 그 사유는 같은 디렉터리의 reads.launchd.log에 남습니다.

이 프로세스만 따로 끄는 명령은 없습니다. 이 컴퓨터의 마지막 원격 연결을 끊으면 시계 두 줄과 함께 내려갑니다.

웹에서 누른 작업이 늦게 시작하는 이유

서버와 주고받는 일은 대부분 cron이 30초마다 띄우는 프로세스가 합니다. 이것을 sync라고 부릅니다. sync는 두 곳에서 일어납니다. 위의 시계가 모든 프로젝트를 차례로 sync하고, 각 큐의 워커도 티켓을 고르기 직전에 자기 프로젝트를 한 번 sync합니다. 웹에서 누른 작업은 sync 때 이 컴퓨터로 내려오고, 시계가 받았든 워커가 받았든 같은 sync에서 바로 세션이 시작됩니다.

서버와 연결을 열어 둔 채 요청을 기다리는 것을 긴 대기라고 부릅니다. macOS에서는 읽기 프로세스가 긴 대기를 끊지 않고 이어 갑니다. 그 프로세스가 없으면 시계가 신호를 보낸 직후부터 다음 시계 시각 1초 전까지 긴 대기를 하고, 30초 중 약 29초가 여기에 들어갑니다. 프로젝트 sync는 긴 대기와 따로 돌기 때문에, sync가 오래 걸려도 긴 대기는 그것을 기다리지 않습니다. 긴 대기 중에 웹에서 작업을 누르면 서버가 이 컴퓨터를 깨우고, dira는 그 프로젝트를 바로 sync합니다. 이 sync가 도는 동안에도 긴 대기는 다음 요청을 계속 받습니다. 작업은 3초 안에 내려와 시작됩니다. 웹에서 쓴 질문의 답과 온톨로지 편집도 같은 방식으로 3초 안에 내려옵니다.

긴 대기 밖에서 누른 작업은 다음 시계를 기다립니다. 읽기 프로세스가 돌면 긴 대기에 빈 시간이 없고, 서버와 연결이 끊겨 다시 잇는 동안만 밖이 됩니다. 시계가 긴 대기를 할 때는 시계와 시계 사이의 약 1초 틈이 밖이고, 긴 대기가 끝나기 3초 전부터는 깨워도 새 sync를 띄우지 않으므로 이때도 다음 시계를 기다립니다. 다음 시계가 몇 초 뒤라 오래 걸리지는 않습니다. 네트워크 오류로 긴 대기가 서버와 연결되지 못하면 깨우기가 오지 않으므로, 작업은 다음 sync 때 내려오고 길게는 30초쯤 걸립니다.

로컬 워커가 모두 바빠도 원격 작업은 기다리지 않습니다. 받아 온 작업은 워커가 아니라 원격 슬롯에서 시작하기 때문입니다. 원격 슬롯은 워커와 따로 있는 실행 자리이고 remote1, remote2처럼 이름이 붙습니다. 그래서 로컬 티켓이 워커를 다 차지하고 있어도 작업은 위에서 설명한 대로 다음 시계에, 길게는 30초쯤 뒤에 시작합니다.

동시에 도는 원격 작업 수는 큐 루트의 remote.json에 적힌 slots가 정하고, 기본값은 2입니다. 슬롯이 모두 차 있으면 작업은 하나가 끝날 때까지 서버에 남아 있습니다. 수를 바꾸려면 remote.json에서 "slots": 3처럼 정수를 고칩니다. sync마다 이 파일을 새로 읽으므로 다음 sync부터 적용됩니다.

slots를 0으로 두면 원격 슬롯이 꺼지고 종전처럼 동작합니다. 한 번에 받아 오는 작업 수가 그 큐의 빈 워커 수가 되어, 워커가 모두 다른 티켓을 쥐고 있으면 하나가 끝날 때까지 작업은 서버에 남아 있습니다.

시계는 신호마다 프로젝트별로 다음에 작업을 받아 올 시각, 워커의 다음 실행 시각, 지금 쥔 티켓을 서버에 알립니다. 웹 화면은 이 값을 받아 작업이 언제 시작될지 보여 줄 수 있습니다.

받아 온 작업은 큐에 보통 티켓으로 생깁니다. frontmatter에 remote_job: <job_id>가 붙는 것만 다릅니다. 앱 화면에서 다른 티켓처럼 보이고, 같은 규칙으로 가져가고 끝납니다.

원격 작업이 답을 기다릴 때

원격 작업도 로컬 티켓처럼 세션이 사람에게 물을 것이 생기면 답변 대기로 들어갑니다. 그러면 같은 질문이 dira 앱과 웹 화면 양쪽에 뜹니다. 답은 웹과 dira 앱 어느 쪽에서 해도 됩니다. 먼저 들어온 답이 tickets/<질문 티켓 해시>.done.md로 쓰이고, 다음 디스패치에서 세션이 그 답을 읽어 같은 작업을 이어 갑니다.

긴 대기 중에는 양쪽이 3초 안에 오갑니다. 웹에서 쓴 답은 서버가 이 컴퓨터를 깨워 바로 내려받고, 세션이 질문을 남기면 그 질문도 바로 웹에 올라갑니다. 긴 대기 밖이면 다음 시계를 기다립니다.

답을 기다리는 동안 웹에는 이 작업의 상태가 awaiting으로 보입니다. 작업 토큰도 그대로 남아 있어서, 답을 받고 다시 뜬 세션이 같은 토큰으로 서버와 이야기합니다.

무엇이 서버로 가고, 무엇이 안 가나

서버로 가는 것은 아래가 전부입니다.

무엇언제
컴퓨터 이름, 연결한 프로젝트 이름과 큐 루트 경로연결할 때
AI 도구 이름-버전-로그인 상태연결할 때와 살아 있음 신호마다
프로젝트별 워커의 다음 실행 시각과 지금 쥔 티켓 해시살아 있음 신호마다(30초)
그 프로젝트의 직전 sync가 실패한 사유 한 줄(500 B 이하)실패한 뒤의 살아 있음 신호마다
원격 작업의 상태(running awaiting done failed)바뀌었을 때. 긴 대기 중이면 3초 안, 그 밖에는 다음 sync
진행 기록 - 단계 이름과 세션이 실행한 셸 명령원격 작업이 도는 동안. 긴 대기 중이면 5초에 한 번까지, 그 밖에는 다음 sync
사람에게 묻는 ## 질문 n 절원격 작업이 답을 기다릴 때. 긴 대기 중이면 3초 안, 그 밖에는 다음 sync
웹이 요청한 온톨로지 조회의 답요청이 올 때마다

진행 기록의 단계는 넷입니다. 파일을 처음 읽었을 때(read), 처음 고쳤을 때(wrote), 새 티켓을 만들었을 때(handoff), 답을 기다리기 시작했을 때(awaiting)입니다. 셸 명령은 한 줄에 2,000 바이트에서 자릅니다.

긴 대기 중에는 1초마다 원격 작업 티켓 파일을 살펴봅니다. 작업이 시작되거나 끝나거나 질문을 남겨 티켓 파일이 바뀌면 상태와 질문을 바로 올립니다. 진행 기록은 세션이 도는 동안 쉬지 않고 쌓이므로 5초에 한 번까지만 올립니다.

서버로 가지 않는 것:

  • 구독 로그인 토큰. claude setup-token으로 받은 토큰은 읽지도 보내지도 않습니다.
  • 세션 전문. 모델이 쓴 글, 도구가 돌려준 결과, 사고 과정은 보내지 않습니다.
  • 원격 작업이 아닌 로컬 티켓의 상태와 진행 기록.

서버에서 받는 런타임 토큰은 ~/.config/dira/remote/ 아래에만 둡니다. 큐 루트, 티켓, 로그에는 쓰지 않습니다. 작업마다 따로 받는 작업 토큰도 ~/.config/dira/run/remote-jobs/에 두었다가 그 작업 세션의 환경변수(DIRA_REMOTE_URL DIRA_REMOTE_TOKEN)로만 넘깁니다. 이 파일은 작업이 끝나거나 서버가 작업을 돌려받았을 때만 지웁니다. 답을 기다리는 동안에는 남겨 둡니다.

서버에서 받아 오는 것

  • 작업. 위에서 말한 대로 티켓이 됩니다.
  • 질문의 답. tickets/<질문 티켓 해시>.done.md로 씁니다. 같은 파일이 이미 있으면 덮지 않습니다. 로컬에서 사람이 먼저 답한 것으로 봅니다.
  • 페르소나 묶음. 서버가 정한 페르소나를 personas/<이름>/에 설치하고, 서버에서 온 것이라는 표시로 .remote 파일을 둡니다. 같은 이름의 내 페르소나가 이미 있으면 덮지 않고 그 이름만 건너뜁니다.
  • 온톨로지 스키마 묶음. 타입 정의를 _ontology/ 아래에 더합니다. 같은 경로에 내용이 다른 파일이 있으면 묶음 전체를 거절합니다.
  • 온톨로지 편집. 웹에서 고친 객체를 objects/와 versions/ 아래에 씁니다. 쓰기 직전에 파일이 웹이 본 판과 같은지 확인하고, 그사이 이 컴퓨터에서 고쳐졌으면 쓰지 않고 충돌로 알립니다.

페르소나와 스키마 묶음은 10분마다 새 판이 있는지 확인합니다.

웹에서 온톨로지를 볼 때

온톨로지는 서버에 사본으로 올리지 않습니다. 웹 화면에서 온톨로지를 열면 서버가 이 컴퓨터에 읽기 요청을 보내고, 이 컴퓨터의 dira가 그때 파일을 읽어서 답합니다. 요청마다 파일을 새로 읽으므로 웹에는 지금 이 컴퓨터에 있는 내용이 그대로 보입니다.

macOS에서는 읽기 요청을 늘 떠 있는 읽기 프로세스가 받습니다. 서버와 연결을 열어 둔 채 기다리다가 요청이 오면 바로 답하고, 답을 보내는 동안에도 다음 요청을 받습니다. 그 프로세스가 없거나 macOS가 아니면 컴퓨터 시계가 대신 받습니다. 이때는 sync-all이 신호를 보낸 직후부터 다음 시계 시각 1초 전까지 기다리므로, 30초마다 약 1초는 요청을 받지 못합니다. 어느 쪽이 받든 프로젝트 sync가 길어지거나 깨우기로 sync가 도는 중이어도 읽기는 그것을 기다리지 않습니다. 아래 경우에는 웹에서 온톨로지가 보이지 않습니다.

  • 이 컴퓨터가 꺼져 있거나 잠자기 상태일 때
  • 네트워크가 끊겼을 때
  • 읽기 프로세스가 돌지 않고 crontab에 시계 두 줄도 없을 때

다시 연결되면 길게는 30초 안에 보입니다.

읽는 자리는 프로젝트에 정한 온톨로지 위치 아래 세 폴더뿐입니다.

폴더웹에서 보는 것
objects/객체 목록, 객체 하나의 본문과 관계, 검색
versions/객체의 지난 판 목록과 그 판의 내용
_ontology/객체 타입과 관계 타입 정의

이 세 폴더 아래의 .md 파일만 읽고, 심링크는 따라가지 않습니다. 온톨로지 위치 바로 아래에 둔 파일이나 다른 폴더는 웹에 나오지 않습니다.

frontmatter를 해석하지 못한 파일은 객체 목록에서 빠집니다. 조용히 건너뛰지는 않고, 그 파일의 경로와 아래 사유를 답에 함께 싣습니다. 웹에 객체가 안 보이면 그 파일이 이 사유 중 하나에 걸리지 않았는지 보세요.

사유뜻
not-utf8파일을 UTF-8로 읽지 못했습니다
no-frontmatter첫 줄이 ---가 아닙니다
unclosed-frontmatterfrontmatter를 닫는 ---가 없습니다
duplicate-name같은 name의 파일이 다른 경로에 또 있습니다. 경로 순으로 첫 파일만 객체가 됩니다
read-failed그 밖의 이유로 읽지 못했습니다

예전 판의 dira는 objects/와 versions/ 파일을 바뀔 때마다 서버에 올렸습니다. 지금은 올리지 않습니다. 그때 서버에 올라간 사본은 dira가 지우지 않고 원격 서비스가 따로 정리합니다. 웹에서 고친 객체를 이 컴퓨터에 쓰는 일은 위의 온톨로지 편집대로 그대로 합니다.

막혔을 때

원격 동작이 실패해도 워커는 멈추지 않습니다. 로컬 티켓은 그대로 돌고, 워커가 부른 sync는 워커 로그에, 시계가 부른 sync는 ~/.config/dira/remote/sync.log에 REMOTE <사유> 한 줄을 남깁니다. 프로젝트 하나의 sync가 실패했으면 그 사유는 그 프로젝트 하위 디렉터리의 last-error에도 남고, 다음 sync가 성공하면 지워집니다.

로그-상태뜻과 할 일
REMOTE unauthorized서버가 런타임 토큰을 거절했습니다. 그 워크스페이스의 sync를 멈춘 상태이니 프로젝트 하나를 --new로 다시 연결하세요
웹 화면에서 이 컴퓨터의 신호가 끊김시계가 돌지 않습니다. 컴퓨터 시계대로 crontab과 sync.log를 보세요
도구가 needs_check로 보고됨그 AI 도구의 로그인 점검이 실패했습니다. 그 도구로는 작업을 받지 않습니다. 그 도구에 다시 로그인하세요(인증)
티켓 fm에 remote_revoked: true이 컴퓨터가 오래 응답하지 않아 서버가 작업을 돌려받았습니다. 그 티켓의 상태는 더 올리지 않습니다
티켓 fm에 remote_failed: no-token이 작업의 작업 토큰 파일이 없어서 세션을 띄우지 않고 티켓을 닫았습니다. 티켓은 .done이지만 완료된 것이 아니고, 서버에는 failed로 보고됩니다. 이 컴퓨터에서는 토큰을 다시 만들 수 없으니 원격 서비스에서 그 작업을 다시 발행하세요
REMOTE persona-skip <이름>같은 이름의 내 페르소나가 있어 서버 페르소나를 설치하지 않았습니다
launchctl print gui/$(id -u)/dev.dira.remote-reads가 서비스를 찾지 못함읽기 프로세스가 없어 시계가 대신 받고 있습니다. 원격에 연결된 프로젝트의 워커가 한 번 돌면 다시 설치됩니다. 설치된 뒤에도 돌지 않으면 ~/.config/dira/remote/reads.launchd.log를 보세요
sync.log에 reads <워크스페이스> <사유>서버가 읽기 요청을 모르거나 네트워크 오류가 나서 이번 시계 동안 그 워크스페이스의 읽기 요청을 받지 않습니다. 다음 시계 때 다시 시도합니다

로그인 점검은 연결할 때, 6시간마다, 그리고 그 도구로 돈 세션이 인증 오류로 끝난 직후에 합니다.

다음은 트러블슈팅입니다.