agent-sync — 하나의 프로젝트, 여러 에이전트, 충돌 없음
두 개의 평면과 그 사이의 하나의 규칙:
Git은 기록 평면입니다. 클라우드는 조정 평면입니다. 유지되어야 하는 사실은 먼저 Git에 기록되고 클라우드에서 참조됩니다. 누가 지금 무엇을 하고 있는지에 대한 사실은 클라우드에 존재하며 만료됩니다.
어떤 클라우드 객체도 내구성 있는 사실의 유일한 저장소가 아닙니다. 아래의 모든 것은 여러 에이전트가 동시에 쓰는 동안 이 사실을 유지하기 위해 존재합니다.
네 가지 함정 — 다른 것을 읽기 전에 이것을 먼저 읽으십시오
1. 지식 베이스는 절대 임대(lease)를 결정하지 않습니다. 그럴 수 없습니다: 하나의 Outline 문서에 대한 12개의 동시 추가 작업은 12개의 성공을 반환했지만 세 줄만 남겼습니다. 배제는 실제 비교-및-교환(compare-and-swap)이 있는 무언가에서 비롯됩니다. 평면은 기록과 다른 것은 전달하지 않습니다. 전체 측정값은 references/lease-protocol.md에 있습니다.
2. 어떤 임대를 가지고 있는지 알고, 그렇게 말하십시오. leaseBackend: "local"은 원자적 파일 생성입니다 — 하나의 파일 시스템에서 프로세스 간에 배타적이며, 머신 간에는 권고적입니다. leaseBackend: "git"은 참조(ref)를 푸시하고, 원격의 비-빨리-감기 거부가 비교-및-교환 역할을 합니다 — 머신 간에 배타적입니다. acquire는 어떤 것인지 출력합니다. 가짜 임대는 임대가 없는 것보다 더 나쁩니다: 다른 에이전트가 확인을 중단합니다.
acquire는 또한 클레임을 로드맵에 기록하며, release는 정확히 원래 있던 것을 복원합니다 — 하나의 행, 하나의 셀, 모호함 시 거부, 왕복 후 git diff 비어 있음. claimTags를 구성하거나 작업을 닫기 전에 references/roadmap.md를 읽으십시오; 닫기는 작업에 대한 진술이며 귀하의 것으로 남습니다.
브랜치에서 작업하십시오; 통합 브랜치는 다른 사람의 안정적인 베이스입니다. acquire는 클레임을 오직 거기에만 기록합니다; 다른 브랜치에서는 보유자가 조정 평면에 남아 있으며, status는 아무도 브랜치를 가져오지 않고 모든 에이전트에게 이를 표시합니다. 브랜치에 커밋된 클레임은 병합될 때까지 보이지 않으며 공유 로드맵을 두 브랜치가 모두 편집하는 파일로 만듭니다. merge로 작업을 랜딩하십시오: 충돌은 아무것도 건드리기 전에 git merge-tree에 의해 계산되고, 충돌이 있으면 이름이 지정되고 거부되며, 병합은 docs/MERGES.md에 기록되고(최근 일수는 전체, 오래된 것은 쓰기 시 압축됨), --key 임대가 해제됩니다. merges는 다음 에이전트에게 떠나 있는 동안 무엇이 랜딩되었는지 알려줍니다. 병합 전에 references/branching.md를 읽으십시오.
3. 훅은 Claude Code에만 존재합니다. 다른 곳에서는 보호된 편집을 차단하는 것이 없습니다: guard를 직접 실행하고 실행을 ungated로 기록하십시오. 프로젝트가 보호되지 않을 때 보호된다고 설명하지 마십시오.
4. 관대하게 파싱하고, 읽을 수 없는 로그를 경쟁 손실이라고 부르지 마십시오. 저장소는 당신이 쓴 것을 다시 씁니다 — Outline은 - 불릿을 * 로 바꿉니다. - 를 내보내고, -/*/+를 수용하며, 항목 모양의 모든 것을 파싱에 실패하면 세고, 2% 이상 파싱 불가능하면 크게 실패하십시오. 진실이 읽을 수 없음일 때 lost라고 보고하면 존재하지 않는 보유자의 이름을 지정합니다. 조용한 사전 필터를 조심하십시오: 정규식 전의 continue는 그것들을 노출하도록 만들어진 카운터에서 잘못된 줄을 숨깁니다.
이것을 어떤 프로젝트에도 가져오기 — 전체 체인
scaffold → 문서 아키텍처 생성, 없는 곳에만
adopt → 리포지토리 읽기, 설정 제안, 아무것도 쓰지 않음
init → 승인된 설정 + gitignore된 환경 파일 쓰기
(운영자가 토큰을 붙여넣습니다 — 절대 당신이 하지 마십시오)
reconcile --set-baseline → 기록을 카운트된 백로그로 만들기, 한 번
setup → 이 프로젝트의 배선을 설명하는 스냅샷 생성
check → 전체 검증; 건강하지 않으면 0이 아님
check는 스킬을 자급자족하게 만듭니다. 아무것도 보호하지 않는 규칙(존재하지 않는 것을 가리키는 레지스터, 가드 글로브, 클레임 패턴, 게이트 또는 미러 소스), 누락된 자격 증명, git이 추적하는 환경 파일(여기서 유일하게 복구 불가능한 실수), 오래되었거나 연결되지 않은 스냅샷, 그리고 기준선이 없는 레지스터에 대해 설정이 건강하다고 부르는 것을 거부합니다. 각각을 이름을 지정합니다; 이 도구 자체의 채택 중에 모든 것이 실제로 실패했습니다.
adopt 후, 설정 변경 후, 그리고 CI에서 check를 실행하십시오.
scaffold는 절대 덮어쓰지 않습니다. 할당 라인과 스냅샷을 가리키는 AGENTS.md로 결정 레지스터를 시드하고, 기존 파일은 모두 건드리지 않은 채로 둡니다 — 채택 시 프로젝트의 자체 규칙을 다시 쓰는 도구는 아무것도 하지 않는 것보다 나쁩니다.
기존 프로젝트: adopt로 시작
init 전에 adopt를 실행하십시오. 리포지토리를 읽고 찾은 것(ID 레지스터, 레지스트리 파일, 게이트)과 당신을 위해 결정을 내리지 않을 사항을 출력한 다음 설정을 제안합니다.
python3 "$SKILL_DIR/scripts/agent_sync.py" adopt
먼저 운영자와 함께 레지스터와 보호된 파일을 확인하십시오: 잘못된 파일을 가리키는 레지스터는 이후의 모든 검사를 자신 있게 틀리게 만들고, 공유 파일을 놓친 보호 목록은 충돌이 발생하는 유일한 장소를 보호하지 않은 채로 둡니다. 서브모듈에서는 레지스터를 선언하지 않습니다: 결정은 상위 리포지토리에 속합니다. 그런 다음 init부터 위의 체인을 따르십시오.
프로젝트의 첫 번째 명령: init
초기화되지 않은 프로젝트에 대해 다른 어떤 것도 실행하지 마십시오. init은 저장소 질문이 한 번 묻고 답변되고 기록되는 곳입니다.
채팅에서 운영자에게 이 두 가지를 물어보십시오 — 추측하지 말고, 기본값을 선택하지 마십시오:
-
조정 상태는 어디에 저장되어야 합니까?
- 지식 클라우드(
outline) — 머신 간의 공유 기록, 인식 및 보드. 임대를 결정하지 않습니다; 그 안에 있는 어떤 것도 결정할 수 없습니다(함정 1); - 또는 로컬 파일(
fs) — 자격 증명이 없으며, 다른 머신의 에이전트에게 보이지 않음: 공유 인식 없음, 교차 리포지토리 신호 없음, 공유 보드 없음.
임대는
leaseBackend에 의해 별도로 결정되며(함정 2),gated는 기록 평면이 아닌 그 선택을 따릅니다. 실제로 가지고 있는 보장을 보고하십시오, 기록 평면이 암시하는 더 강력한 보장이 아닙니다. - 지식 클라우드(
-
클라우드인 경우: 인스턴스 URL. URL은 설정이지 비밀이 아니므로 작성할 수 있습니다. 토큰은 비밀이 아닙니다 — 채팅에서 절대 묻지 말고, 다시 읽지 말고, 직접 배치하지 마십시오.
그런 다음 그들의 답변으로 실행하십시오:
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend outline --url https://<their-instance>
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend fs
init은 .claude/agent-sync.json(형태, 커밋됨)을 쓰고, 키와 빈 토큰 줄(identity, 모드 600)로 .env.agent-sync를 쓰고, .env.agent-sync와 .agent-sync/를 .gitignore에 추가한 다음, 운영자가 직접 해야 할 일을 정확히 출력합니다 — 자신의 인스턴스에서 토큰을 만들고 그 한 줄에 붙여넣습니다. --force 없이는 기존 설정이나 환경 파일을 절대 덮어쓰지 않습니다.
이 마무리 지침을 운영자에게 그대로 전달하십시오. 파일에 토큰을 넣는 것은 그들의 단계이며, 설계는 그것이 그들의 것이라는 사실에 의존합니다.
그런 다음, 모든 세션 전에
python3 "$SKILL_DIR/scripts/agent_sync.py" status
멱등적임. 검사, 수리, 보고, 정확히 하나의 다음 동작을 이름을 지정하고 — check의 판결을 전달하므로, 모든 세션이 실행하는 명령과 설정을 검증하는 명령이 하나의 프로젝트에 대해 두 가지 답변을 줄 수 없습니다.
출력하는 두 가지 인식 섹션을 읽으십시오 — 그것들은 장식이 아니라 핵심입니다.
- 지금 이 프로젝트에서 작업 중인 다른 실행. 누가 무엇을 보유하고 있는지, 이 순간. 그것들을 맡지 말고, 그들이 다루는 파일을 "그냥 보지" 마십시오. 볼 수 없는 임대는 당신을 차단합니다; 볼 수 있는 임대는 당신을 조정하게 만듭니다.
- 당신이 마지막으로 본 이후 새로운 것. 당신이 떠나 있는 동안 랜딩된 교차 리포지토리 의존성 이동. 이동된 의존성은 당신이 계획한 것을 차단 해제하거나 무효화할 수 있습니다. 이 목록은 실행당 워터마크가 찍혀 있으므로, 실제로 무언가 변경될 때까지 조용히 유지됩니다; 말할 때는 중요합니다.
이 블록을 건너뛰는 에이전트는 다른 사람이 하고 있는 작업을 재파생하고 한 시간 전에 변경된 의존성 상태에 따라 행동할 것입니다.
status가 결정하는 다른 것: 자격 증명 없음 → 저하된 모드, 보고됨, 계속됨(오류가 아닌 더 작은 모드); task-pipeline 없음 → 설치 라인을 출력하고 중지합니다. 대체 흐름을 즉흥적으로 만들지 마십시오 — 해당 단계 없이는 바인딩할 것이 없습니다.
npx sshlg-skills install
명령어
| 명령어 | 기능 |
|---|---|
init | 먼저 실행하십시오. 상태가 어디에 저장될지 묻고, 설정 + gitignore된 환경 파일을 쓰고, 운영자의 단계를 출력합니다 |
status | 검사, 수리, 보고, 하나의 다음 동작 이름 지정 |
bootstrap | 클라우드 컨테이너를 만들고 환경 파일에 붙여넣을 ID를 출력합니다 |
acquire <KEY> | 작업 ID에 대한 임대를 취득합니다. won 또는 lost <holder>를 출력합니다 |
renew <KEY> | 임대를 연장합니다. PostToolUse 훅이 자동으로 수행합니다 |
release <KEY> | 임대를 반환합니다. 실패 시에도 항상 수행하십시오 |
reserve <REG> | 레지스터에서 다음 ID를 예약합니다(DEC, OQ, DEP, …). ID를 출력합니다 |
release-id <REG> <ID> | git에 쓰지 않은 ID를 반환합니다 |
journal <text> | 이 실행의 저널에 한 줄을 추가합니다 |
record <text> | 실제로 구축한 것을 추가합니다 — --decision DEC-…, --files a,b |
reconcile | 의도(git) 대 실제 구축(클라우드). 프로젝트당 한 번 --set-baseline |
signal <DEP-ID> <state> | 교차 리포지토리 의존성을 이동합니다: filed/accepted/delivered/closed/refused |
guard <path> | 이 실행이 해당 경로에 쓸 수 있는지 여부를 답변합니다. 종료 0 = 예, 2 = 아니요 |
board | 공유 보드와 이 리포지토리의 페이지를 재생성합니다. --mirror는 또한 구성된 git 문서를 평면으로 렌더링합니다 |
whoami | 이 실행의 ID와 보유한 임대를 출력합니다 |
setup | 이 프로젝트가 어떻게 배선되었는지에 대한 생성된 스냅샷을 에이전트가 읽을 수 있도록 씁니다 |
adopt | 기존 프로젝트를 검사하고 설정을 제안합니다 — 아무것도 쓰지 않음 |
merge | 이 브랜치를 랜딩합니다: 로컬 대상 빠르게 감기, 충돌은 아무것도 건드리기 전에 확인됨, 병합 로그 기록, --key 임대 해제. --summary, --dry-run, --push |
merges | 브랜치에 있는 동안 랜딩된 것. --all은 압축된 꼬리를 포함합니다 |
check | 전체 설정을 종단 간 검증합니다. 건강하지 않으면 0이 아님 |
scaffold [--full] | 누락된 것만 생성하고, 존재하는 것 위에는 절대 한 줄도 쓰지 않습니다. --full은 또한 질문 레지스터, 인덱스, 의존성 보드, 엔터티 레지스터가 있는 데이터 모델, 문서 게이트를 시드합니다 |
finish [--gates] | 작업이 완료되었습니까 — 모든 리포지토리가 깨끗하고, 푸시되고, 가리켜지고, 남아 있는 임대가 없습니다. check는 프로젝트가 올바르게 배선되었는지 답변합니다; 이것은 당신이 끝났는지 답변합니다 |
$SKILL_DIR은 이 스킬의 자체 디렉토리입니다: Claude Code 플러그인 아래 $ {CLAUDE_PLUGIN_ROOT}/skills/agent-sync, 다른 곳에서는 ~/.agents/skills/agent-sync. 세션당 한 번 해결하고 재사용하십시오 — 경로를 추측하지 마십시오. 모든 명령은 프로젝트 루트에서 .claude/agent-sync.json을 읽고 나열된 것 외에는 인수가 필요하지 않습니다.
세션당 하나의 ID 및 결정 방법
임대는 두 에이전트가 두 개의 ID를 얻을 때만 임대입니다. 여기서 순서가 중요하며 양쪽 끝이 문제를 겪었습니다: CLAUDE_SESSION_ID에서만 ID를 파생하면 하나의 세션이 두 개의 ID를 얻었습니다 — 하나로 획득하고 다른 하나로 자체 가드에 의해 거부되었습니다 — 그리고 체크아웃당 하나의 ID를 유지하면 두 세션이 하나의 ID를 얻었으며, 이는 더 나쁩니다. 두 번째는 조용합니다: 두 세션이 모두 획득하고, 둘 다 보호되며, release는 호출자가 가져본 적 없는 임대를 취합니다.
순서는 다음과 같습니다: AGENT_SYNC_RUN_ID · CLAUDE_SESSION_ID · 이 셸을 시작한 세션 · 공유.
세 번째는 일반 셸 명령에는 세션 ID가 없고 훅에는 있기 때문에 중요합니다. 따라서 SessionStart는 .agent-sync/sessions/<CLI pid>를 그것이 알고 있는 세션으로 스탬프하고, 이후 명령은 자체 프로세스 조상을 스탬프된 pid로 걸어서 자신을 찾습니다. 명령줄 파싱이 아닌 이유: references/earned-rules.md.
네 가지 모두 설정할 수 없을 때 실행은 "이 ID는 이 체크아웃의 다른 세션과 공유됩니다"라고 말하며 공유된 항목을 분리로 제시하지 않습니다.
클레임 — 중요한 형태
acquire → 작업 수행 → release
실패 시에도 절대 release를 건너뛰지 마십시오: 버려진 임대는 TTL이 만료될 때까지 작업을 차단하고, 다음 에이전트는 "진행 중"과 "한 시간 전에 충돌"을 구분할 수 없습니다.
임대는 클레임이 아닙니다. 임대는 누가 지금 보유하고 있는지 말하고 만료됩니다; 내구성 있는 클레임은 git의 태그이며, acquire에 의해 기록되고 release에 의해 지워집니다. 하나의 사실, 하나의 집 — 소유권을 기록하는 세 번째 장소를 발명하지 마십시오.
획득, 만료, 도용 또는 ID 할당을 변경하기 전에 references/lease-protocol.md를 읽으십시오.
보호된 파일
설정은 여러 에이전트가 쓰는 레지스트리 파일을 나열합니다. 편집하기 전에:
python3 "$SKILL_DIR/scripts/agent_sync.py" guard docs/DECISIONS.md
종료 2는 이 실행에 관한 것입니다: 임대를 보유하지 않습니다 — 누군가 다른 사람이 그 파일을 보유하고 있다는 것이 아닙니다. 하나의 임대는 모든 보호된 파일을 다룹니다; 하나를 보유하거나 아무것도 쓰지 마십시오. 거부는 다른 실행 과 그 키를 이름을 지정합니다. 왜냐하면 "r-x가 임대를 보유함"이 경로 옆에 있으면 "r-x가 이 파일을 보유함"으로 반복되기 때문입니다. 어쨌든 편집하지 말고, "한 줄만 고치지" 마십시오 — 덮어쓰여진 결정은 정확히 결정처럼 보입니다.
Claude Code의 PreToolUse 훅이 자동으로 이것을 실행합니다. 다른 곳에서는 아무것도 하지 않습니다.
ID 예약
"다음 사용 가능한 ID" 줄을 읽는 것은 예약이 아닙니다 — 두 에이전트가 같은 번호를 읽고 둘 다 사용합니다.
python3 "$SKILL_DIR/scripts/agent_sync.py" reserve DEC # → DEC-0216
할당은 병합된 로그에 대해 위치적입니다 — 모든 샤드, 이 실행의 것만이 아닙니다 — 따라서 모든 에이전트가 동일한 답변을 계산합니다. 예약되었지만 git에 기록되지 않았습니까? release-id로 반환하거나, 번호는 보드가 누수로 보고하는 구멍입니다.
로그의 어떤 것도 편집되거나 삭제되지 않습니다
로그는 순서대로 재생되므로, 편집은 다른 에이전트가 이미 행동한 결론을 조용히 다시 씁니다. 추가하여 수정하십시오: 임대 해제, 사용하지 않은 ID release-id, 잘못된 as-built 항목을 나중의 것으로 대체. 생성된 페이지는 유일한 예외이며, agent-sync:generated 마크를 잃은 페이지는…
[잘림]