History

  • [2026-03-07 Sat 13:18] botlog로 이동, 오픈소스 수렴 에세이 추가
  • [2026-03-07 Sat 13:00] upstream이 lockSync retry 자체 구현 (v0.56.3) — 우리 패치 미션 완료
  • [2026-02-26 Thu 12:30] v0.55.1 rebase, Emacs 패키지 방향 점검
  • [2026-02-23 Mon 18:00] v0.54.2 rebase, 병렬 에이전트 방향 추가
  • [2026-02-20 Fri 11:37] 문서 생성

pi-mono lockSync 멀티인스턴스 경합 수정 타임라인

[2026-02-20 Fri 11:37]

요약

pi v0.53.0 (2026-02-17)에서 도입된 lockfile.lockSync() 호출이 재시도 없이 즉시 실패하여, 여러 pi 인스턴스를 동시에 시작하면 ELOCKED 에러로 크래시하는 문제를 발견하고 수정한 기록.

  • 영향 범위: pi를 여러 인스턴스로 동시 실행하는 모든 클라이언트 (Emacs, Neovim 등)
  • 근본 원인: proper-lockfilelockSync() 는 기본 retries: 0 (즉시 실패)
  • 수정: 수동 retry loop (5회, 100ms 간격)
  • 포크: junghan0611/pi-mono#fix/lockSync-retries

배경: 사용 환경

Emacs에서 pi-coding-agent 패키지를 사용하여 pi를 --mode rpc 로 실행. 원저자는 Emacs에서 pi 세션을 1개만 사용하지만, 나는 프로젝트별로 여러 세션을 동시에 운영한다.

[Emacs]
  ├─ pi-coding-agent session #1 (project-A) → pi --mode rpc
  ├─ pi-coding-agent session #2 (project-B) → pi --mode rpc
  └─ pi-coding-agent session #3 (project-C) → pi --mode rpc
       ↓ 동시 시작 시 모두 ~/.pi/agent/settings.json 에 lockSync 시도
       → 첫 번째만 성공, 나머지 ELOCKED 즉시 실패

타임라인

2026-02-17: upstream에 lockSync 도입

커밋 de2736ba (“refactor: improve settings storage semantics and error handling”)에서 FileSettingsStorage.withLock()lockfile.lockSync() 추가.

// packages/coding-agent/src/core/settings-manager.ts (v0.53.0)
release = lockfile.lockSync(path, { realpath: false });

동일 패턴이 auth-storage.tsFileAuthStorageBackend.withLock() 에도 적용됨.

proper-lockfilelockSync() 기본값은 retries: 0 → 락 경합 시 즉시 ELOCKED throw. 단일 인스턴스에서는 문제 없지만, 복수 인스턴스 동시 시작 시 확정적으로 실패.

2026-02-19: 문제 발견 및 Emacs 측 우회 시도

pi-coding-agent v1.3.2 환경에서 여러 세션을 동시에 시작하면 일부 세션이 설정 파일 락 획득 실패로 크래시하는 것을 확인.

Emacs 측(pi-coding-agent)에서 락 파일 대기 로직을 추가하여 우회 시도:

;; pi-coding-agent-core.el — Emacs 측 락 대기 (Phase 1)
(defun pi-coding-agent--wait-for-settings-lock ()
  "Wait for settings.json lock files to be released."
  (let ((lock-dirs (pi-coding-agent--settings-lock-dirs)))
    (dolist (dir lock-dirs)
      (pi-coding-agent--wait-for-lock dir "settings.json" 5.0 0.1))))

커밋 7d89147 on pi-coding-agent (“fix: wait for settings lock before starting pi process”)

이 방식의 한계:

  • Emacs 측에서 pi 프로세스 시작 전에 락을 기다리지만, pi가 시작 후 락을 잡는 시점은 제어 불가
  • 근본 원인(pi 바이너리의 retry 부재)을 해결하지 못함
  • 다른 클라이언트(Neovim, Web UI 등)에는 적용 안 됨

2026-02-19: upstream pi-coding-agent rebase

upstream pi-coding-agent에 3개 새 커밋이 추가됨 (v1.3.3):

  • 05f916b feat(ui): semantic header phases with fresher stats (#121)
  • 4c8171b fix: make pi session display frame-local (#133)
  • 2044f8f chore: bump version to 1.3.3

포크를 rebase하여 upstream 반영. 충돌 없음. 619/619 테스트 통과.

2026-02-20: 근본 원인 분석 (pi-mono)

pi-mono 소스를 분석하여 근본 원인을 특정:

  1. settings-manager.ts L156: lockfile.lockSync(path, { realpath: false }) — 재시도 없음
  2. auth-storage.ts L74: 동일 패턴
  3. proper-lockfilelockSync()retries 옵션을 지원하지 않음 (sync API 제한)

Cannot use retries with the sync api — proper-lockfile 에러 메시지. async lock() 만 retries를 지원하고, lockSync() 는 지원하지 않는다.

따라서 lockSync()retries 옵션을 전달하면 *런타임 에러*가 발생한다. 수동 retry loop가 유일한 해결 방법.

2026-02-20: 수정 구현 (pi-mono fork)

junghan0611/pi-mono 포크에 fix/lockSync-retries 브랜치 생성.

수정 내용 — 두 파일에 동일 패턴 적용:

// 수동 retry loop (lockSync는 retries 옵션 미지원)
const maxRetries = 5;
const retryDelayMs = 100;
let release: (() => void) | undefined;
 
for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
        release = lockfile.lockSync(path, { realpath: false });
        break;
    } catch (err: unknown) {
        const lockErr = err as { code?: string };
        if (lockErr.code === "ELOCKED" && attempt < maxRetries) {
            const until = Date.now() + retryDelayMs;
            while (Date.now() < until) {
                /* sync wait for lock release */
            }
            continue;
        }
        throw err;
    }
}

변경 파일:

  • packages/coding-agent/src/core/settings-manager.tsFileSettingsStorage.withLock()
  • packages/coding-agent/src/core/auth-storage.tsFileAuthStorageBackend.withLock()

설계 원칙:

  • 최소 침습: lockSync() 호출부만 retry loop로 교체, 락 후 읽기/쓰기/해제 로직은 미변경
  • ELOCKED 에러만 재시도, 다른 에러는 즉시 throw (원래 동작 보존)
  • 최대 대기 시간: 5 * 100ms = 500ms (합리적 범위)

커밋: 870945a7 (“fix(coding-agent): add retry loop for lockSync to prevent multi-instance failures”) pre-commit 통과: biome lint + tsc

2026-02-20: 실사용 검증

로컬 빌드를 ~/.local/bin/pi 에 링크하여 실사용 테스트:

# 동시 3개 인스턴스 실행 — 모두 성공
pi --version & pi --version & pi --version & wait
# → 모두 v0.54.0 출력, ELOCKED 에러 없음

Emacs에서 pi-coding-agent 세션 복수 동시 시작 — 크래시 없이 정상 동작 확인.

2026-02-20: 테스트 코드 추가

4개 테스트 케이스를 test/settings-manager.test.ts 에 추가:

테스트방법검증 내용
retry and succeed when lock is held brieflyvi.spyOn mockELOCKED 2회 후 성공, retry 동작
throw after exhausting retries실제 lockfile영구 락 → 재시도 소진 후 throw
work without contention실제 lockfile정상 경로 (경합 없음)
concurrent SettingsManager.create실제 코드동시 생성 성공

“retry and succeed” 테스트가 vi.spyOn 모킹인 이유: Node.js는 single-threaded이므로 동기 busy-wait 중 setTimeout 콜백이 실행되지 않는다. 실제 락 경합은 *프로세스 간*에서 발생하므로, 단일 프로세스 테스트에서는 모킹이 정확한 접근이다.

커밋: bba4a720 (“test(coding-agent): add lockSync retry contention tests”) pre-commit 통과: biome lint + tsc. 15/15 테스트 통과.

2026-02-20: Emacs 멀티세션 실사용 검증 (Emacs 측 우회 제거 후)

pi-mono lockSync retry만으로 충분한지 확인하기 위해, Emacs 측 우회 코드를 완전히 제거하고 테스트:

  1. pi-coding-agent 로컬 fork(lock-wait 우회 포함) → upstream MELPA 버전으로 복귀
  2. ai-pi-agent.el 에서 load-path 직접 추가 제거
  3. packages.el 에서 upstream pi-coding-agent 패키지 활성화
  4. doom sync 후 Emacs 재시작

테스트: Emacs에서 여러 프로젝트의 pi 세션을 동시에 시작

결과: 멀티 세션 정상 동작 확인!
- Emacs 측 lock-wait 우회 없이, pi-mono의 lockSync retry만으로 경합 해결
- 여러 프로젝트에서 동시 pi 세션 시작 → ELOCKED 에러 없음
- 설정 파일 정상 로드, 모델 응답 정상

이로써 *서버측 수정만으로 충분*하다는 것이 실사용 환경에서 검증됨. Emacs 측 우회(7d89147)는 더 이상 불필요.

2026-02-20: 전체 테스트 검증 (./test.sh)

upstream의 test.sh (API 키 없이 전체 테스트) 실행 결과:

  • 실패: test/git-update.test.ts 8개 — 원본 main에서도 동일 실패 (NixOS 로컬 환경 차이)
  • 나머지: 680+ 테스트 통과
  • 우리 변경으로 인한 regression: 0건

영향 범위 분석: Emacs 전용인가?

아니다. 이 문제는 pi를 여러 인스턴스로 동시 실행하는 모든 환경에서 발생한다:

  • Emacs (pi-coding-agent): 프로젝트별 세션 → 동시 시작 시 경합
  • Neovim (pi.nvim 등): 동일 구조라면 동일 문제
  • tmux에서 수동으로 여러 pi 실행: 동시 시작 시 경합
  • CI/CD에서 병렬 pi 실행: 경합 가능

단일 인스턴스만 사용하면 발생하지 않으므로, 원저자 환경에서는 재현되지 않았을 것이다.

커밋 로그

날짜리포커밋내용
2026-02-17pi-mono (upstream)de2736balockSync 도입 (retries 없음)
2026-02-19pi-coding-agent (fork)7d89147Emacs 측 락 대기 우회
2026-02-20pi-mono (fork)870945a7lockSync retry loop 수정
2026-02-20pi-mono (fork)bba4a720retry 테스트 4개 추가

PR 준비 상태

항목상태
구현 완료O
테스트 추가O (4개)
npm run check 통과O
regression 0건O
CHANGELOG.md 미수정O (CONTRIBUTING.md 준수)
APPROVED_CONTRIBUTORS 등록X (Issue 먼저 제출 필요)
관련 Issue 번호X (미생성)

다음 단계

  1. upstream에 Contribution Proposal Issue 제출
  2. 메인테이너 lgtm 대기 (23일 이후)
  3. PR 제출: fix/lockSync-retriesmain
  4. [완료] Emacs 측 우회 불필요 확인 — MELPA upstream 버전으로 복귀 완료

v0.54.2 rebase 및 병렬 에이전트 방향

[2026-02-23 Mon 18:00]

upstream v0.54.2 반영 (2026-02-23)

upstream main에 15커밋이 추가되어 v0.54.2 릴리스. fix/lockSync-retries 브랜치를 v0.54.2 위에 rebase 완료.

upstream 주요 변경 (v0.54.0 → v0.54.2)

커밋내용lockSync 관련
f1a2092b.pi 폴더 무조건 생성 방지 (#1588)직접 영향withLock() 구조 변경
6137de9cextension theme → session settings 동기화 (#1483)무관
0c61dd58streaming write tool call 점진적 하이라이트무관
7364696aprovider/model split 우선 매칭무관
316c2afegit-update 테스트 수정무관
8386a807tui: koffi 외부화 (bun binary)무관

settings-manager.ts 구조 변경과 retry 적응

upstream f1a2092bFileSettingsStorage.withLock() 을 리팩토링:

[기존 v0.54.0]
  lockSync(path)           ← 무조건 1회, 여기에 retry 추가했었음
  read → fn → write
  release
 
[v0.54.2 이후]
  if (fileExists)
    lockSync(path)         ← 읽기용 lock (파일 존재 시만)
  read → fn(current)
  if (next !== undefined)
    mkdirSync(...)         ← 쓰기 시에만 디렉토리 생성
    if (!release)
      lockSync(path)       ← 쓰기용 lock (새 파일 생성 시)
    write
  release

lockSync 호출이 1곳 → 2곳으로 증가. 두 곳 모두 retry 없이 ELOCKED 시 즉시 실패하는 문제는 동일.

rebase 충돌 해결

  • settings-manager.ts: retry 로직을 lockSyncWithRetry() private 메서드로 추출. 두 곳의 lockSync() 호출 모두에 적용.
  • auth-storage.ts: 동일 패턴으로 lockSyncWithRetry() 추출. 충돌 없음.
  • settings-manager.test.ts: upstream 테스트(project dir creation 2개) + 우리 테스트(lockSync retry 4개) 모두 유지.
  • run.sh: rebase에서 제외 후 재생성.

검증 결과

  • npm run check 통과 (biome lint + tsc)
  • settings-manager.test.ts 17/17 통과 (upstream 13 + 우리 4)
  • regression: 0건

결론: 문제는 여전히 존재

upstream v0.54.2에서 lockSync 구조가 바뀌었지만, retry 로직은 추가되지 않음. 멀티인스턴스 경합 시 ELOCKED 즉시 실패 문제는 그대로. 우리 수정(lockSyncWithRetry)이 v0.54.2에서도 유효.

병렬 에이전트 구동을 위한 관심 영역

목표: pi를 병렬 에이전트로 구동하여 에이전트 공장(Agent Factory) 을 구축한다. Gastown 등의 기존 에이전트 오케스트레이터와 유사하되, Emacs 기반 워크플로우에 맞춘 방식.

현재 확인된 병렬 실행 이슈

영역파일문제수정 상태
설정 파일 락settings-manager.tslockSync retry 부재수정 완료 (fork)
인증 파일 락auth-storage.tslockSync retry 부재수정 완료 (fork)
~/.pi/ 디렉토리settings-manager.ts동시 mkdirSync raceupstream f1a2092b 에서 완화

추가 점검이 필요한 영역

병렬 pi 인스턴스 운영 시 잠재적 경합 지점:

  1. 세션 파일: 각 pi 인스턴스의 세션 저장/로드 — 경로가 분리되는지 확인 필요
  2. 로그 파일: 동시 쓰기 시 interleave 가능성
  3. git 동시 접근: 같은 리포에서 여러 pi가 git 명령 실행 시 .git/index.lock 경합
  4. 임시 파일: 빌드/실행 중 임시 파일 경로 충돌
  5. OAuth 토큰 갱신: 여러 인스턴스가 동시에 토큰 refresh 시도 시 race condition
    • auth-storage.tswithLockAsync() 가 async lock으로 처리하지만, 검증 필요

운영 시나리오

[Emacs Orchestrator]
  ├─ pi session #1 (project-A, task: code review)
  ├─ pi session #2 (project-B, task: refactoring)
  ├─ pi session #3 (project-C, task: test writing)
  └─ pi session #4 (project-A, task: documentation)

  모두 ~/.pi/agent/settings.json, auth.json 공유
  → lockSyncWithRetry로 경합 해결

포크 관리 방침

  • upstream 추적: main 브랜치는 upstream/main에 fast-forward 유지
  • 수정 브랜치: fix/lockSync-retries 에 우리 패치 유지
  • upstream 업데이트 시: main ff → fix 브랜치 rebase → 빌드 → 실사용
  • upstream이 retry를 자체 구현하면: 우리 패치 드롭, main으로 복귀

v0.55.1 rebase 및 Emacs 패키지 방향 점검

[2026-02-26 Thu 12:30]

upstream v0.55.1 반영 (2026-02-26)

upstream main에 19커밋 추가 (v0.54.2 → v0.55.1). fix/lockSync-retries 브랜치를 v0.55.1 위에 rebase — 충돌 없음 (수정 파일 미변경).

upstream 주요 변경 (v0.54.2 → v0.55.1)

병렬 에이전트 관점에서 주목할 변경
커밋내용관련성
757d36a4offline startup 모드 + 네트워크 타임아웃 (#1631)병렬 시작 시 네트워크 의존 제거 가능
cf656c16Vertex ADC 자격증명 async import race 수정 (#1550)race condition 수정 — 병렬 실행 직접 관련
7390f830subagent: getAgentDir() 경로 수정 (#1559)subagent 아키텍처 개선
f0379384project 리소스 우선 로드 (global보다)멀티프로젝트 병렬 시 리소스 격리 개선
기타 변경
커밋내용
e9d0074fsonnet 4.6 adaptive thinking + xhigh effort clamp (#1548)
96cf7425gemini-3.1-pro-preview 추가 (#1599)
49394349Windows typebox alias 경로 구분자 수정
3db5715dWindows fd/rg bootstrap 강화
43c3c99d.gitattributes 줄바꿈 정규화

lockSync retry 상태: 변화 없음

v0.55.1에서도 lockSync() 에 retry 로직은 추가되지 않았다. 우리 파일(settings-manager.ts, auth-storage.ts)에 upstream 변경 없음. 우리 패치가 충돌 없이 적용됨.

검증

  • npm run check 통과
  • settings-manager.test.ts 17/17 통과
  • 빌드 성공, ~/.local/bin/pi v0.55.1 링크 완료

pi-coding-agent (Emacs 패키지) 현황

포크 상태

항목
upstreamdnouri/pi-coding-agent
포크junghan0611/pi-coding-agent
upstream 최신v1.3.5 (7311a02)
포크 최신6c58eac (lock wait)
포크와 upstream 차이우리 커밋 1개만 위에 (동기화 상태)

upstream v1.3.3 → v1.3.5 주요 변경

버전커밋내용관련성
v1.3.4c0a037dstreaming preview 성능 개선 (#136)UX
v1.3.415a4d8dRET tool navigation 정확도 수정 (#135)UX
v1.3.443667d9manual compaction queue-safe + 실패 복원 (#134)안정성 — 병렬 관련
v1.3.4b4ee915fork-at-point deep/large 세션 안정화 (#139)안정성
v1.3.5a6a3cc1버전 확인: 프로세스별 지연 프로브 (#140)멀티세션 개선
v1.3.599598f7input buffer 상속 completions 제거 (#141)UX
v1.3.57311a02built-in slash commands 클라이언트측 디스패치 (#143)기능

우리 lock wait 커밋의 방향성

6c58eac (“fix: wait for settings lock before starting pi process”)은 Emacs 측에서 pi 프로세스 시작 전에 .lock 디렉토리를 폴링하는 우회책이었다.

현재 상황:

  • pi-mono 포크에 lockSyncWithRetry() 적용 → 서버측에서 근본 해결
  • Emacs 측 우회는 이중 안전장치 역할 — 있어도 해는 없으나 필수는 아님
  • upstream pi-coding-agent에는 반영되지 않음 (PR 미제출)

방향:

  1. pi-mono 패치가 upstream에 반영되면: Emacs 측 lock wait 불필요 → 포크를 upstream에 맞춤
  2. pi-mono 패치가 반영되지 않으면: 이중 보호(서버 retry + 클라이언트 wait) 유지
  3. pi-coding-agent upstream에 lock wait PR은 보류 — pi-mono 쪽이 올바른 수정 지점

Emacs 멀티세션 아키텍처 메모

[현재 구조]
Emacs (pi-coding-agent v1.3.5)
  └─ per-project pi process (--mode rpc)
       └─ settings.json lock (lockSyncWithRetry)
       └─ auth.json lock (lockSyncWithRetry)
 
[목표 구조: Agent Factory]
Emacs Orchestrator
  ├─ Task Queue (org-mode 기반)
  ├─ pi pool (N개 동시 실행)
  │   ├─ pi #1 ← project-A, task from queue
  │   ├─ pi #2 ← project-B, task from queue
  │   └─ pi #N ← ...
  ├─ Result Aggregator (org-mode로 수집)
  └─ Feedback Loop (결과 → 새 태스크)

v0.55.1의 offline mode (--offline, PI_OFFLINE=1)는 병렬 시작 시 네트워크 의존을 제거하므로, Agent Factory 시나리오에서 활용 가치가 높다.

upstream lockSync retry 반영 — 미션 완료

[2026-03-07 Sat 13:00]

upstream 자체 수정 확인

커밋 58f8fcd8 (2026-03-06, Mario Zechner): fix(coding-agent): retry sync lockfile acquisition to prevent false auth errors during parallel startup

upstream이 우리와 *동일한 문제를 독립적으로 발견하고 동일한 패턴으로 수정*했다. 관련 이슈: #1871

우리 수정 vs upstream 수정 비교

항목우리 (2/20)upstream (3/6)
메서드명lockSyncWithRetry()acquireLockSyncWithRetry()
최대 재시도5회10회
대기 간격100ms20ms
총 대기 시간500ms200ms
busy-wait 패턴while (Date.now() < until)while (Date.now() - start < delayMs)
ELOCKED 체크lockErr.code == “ELOCKED”=String(error.code) != “ELOCKED”=
적용 파일auth-storage.ts, settings-manager.tsauth-storage.ts, settings-manager.ts

접근 방식이 본질적으로 동일하다:

  • lockSync()retries 옵션을 지원하지 않으므로 수동 retry loop
  • ELOCKED 에러만 재시도, 다른 에러는 즉시 throw
  • sync busy-wait (Node.js single-thread 제약)

upstream이 더 짧은 간격(20ms)으로 더 많이(10회) 재시도하는 차이만 있음.

조치

  • fix/lockSync-retries 브랜치: 더 이상 불필요 — upstream main으로 전환
  • main 브랜치를 upstream v0.56.3으로 fast-forward
  • v0.56.3 빌드 + ~/.local/bin/pi 링크 완료
  • 우리 포크 패치 드롭 (포크 관리 방침대로)

포크 상태

리포이전현재
pi-monofix/lockSync-retries 브랜치 사용main (upstream v0.56.3) 사용
pi-coding-agent포크 master (lock wait 포함)변경 없음 (이중 안전장치 유지)
pi 바이너리v0.55.1 (우리 패치)v0.56.3 (upstream 패치)

타임라인 요약

2/17  upstream에 lockSync 도입 (retries 없음)
2/19  문제 발견, Emacs 측 우회 시도
2/20  pi-mono 포크에 lockSyncWithRetry 구현 + 테스트
2/23  v0.54.2 rebase (충돌 해결, 헬퍼 메서드 추출)
2/26  v0.55.1 rebase (충돌 없음)
3/06  *upstream이 동일 수정을 독립적으로 구현* (58f8fcd8, #1871)
3/07  upstream v0.56.3으로 전환, 우리 패치 드롭

우리가 2주 앞서 같은 문제를 발견하고 같은 해법을 구현했다. PR을 제출하지 않았지만, upstream이 결국 같은 결론에 도달. 멀티인스턴스 lockSync 경합 문제는 완전히 해결됨.

기여 아닌 기여 — 오픈소스 생태계의 자연스러운 수렴

[2026-03-07 Sat 13:18]

기다림이라는 기여

이 기록에는 PR도 없고, 이슈도 없고, 메인테이너와의 대화도 없다.

2주 동안 한 일은 이것이다:

  • 문제를 발견하고, 원인을 분석하고, 해법을 구현하고, 테스트를 작성하고, upstream이 업데이트될 때마다 rebase하며 지켜봤다.
  • 그리고 3월 6일, upstream 메인테이너(Mario Zechner)가 독립적으로 같은 문제를 발견하고, 같은 패턴으로 수정했다.

이슈 #1871의 제목이 말해준다: “retry sync lockfile acquisition to prevent false auth errors during parallel startup”

우리가 2월 20일에 작성한 커밋 메시지와 본질적으로 같은 문장이다.

굳이 번거롭게 하지 않아도

오픈소스에서 기여는 보통 이런 절차를 밟는다: 이슈 등록 → 메인테이너 확인 → 토론 → PR 제출 → 리뷰 → 수정 → 머지.

이 과정이 가치 있는 경우도 많다. 하지만 이번 건은 달랐다:

  • 문제의 원인이 명확했다. lockSync() 에 retry가 없는 것.
  • 해법도 자명했다. 수동 retry loop. proper-lockfile 문서에 답이 있었다.
  • 메인테이너는 단일 인스턴스 사용자라 아직 겪지 않았을 뿐이었다.

이런 종류의 버그는 시간이 해결한다. 사용자가 늘면 누군가 보고하고, 메인테이너도 결국 같은 곳을 보게 된다. 우리가 이슈를 등록해서 그의 유한한 시간을 번거롭게 할 필요가 있었을까?

수렴은 증거다

두 사람이 같은 코드를 보고, 같은 제약(lockSyncretries 미지원)을 만나고, 같은 패턴(busy-wait retry loop)으로 해결했다. 메서드 이름만 다르다:

  • 우리: lockSyncWithRetry()
  • 그: acquireLockSyncWithRetry()

이 수렴이 말해주는 것은 — 올바른 해법은 하나였다는 것이다. 그리고 올바른 해법은, 결국 누군가 구현하게 되어 있다.

인간의 유한한 시간

오픈소스 메인테이너는 대부분 소수의 인간이다. 그들의 시간은 유한하고, 이슈 트래커에는 이미 수백 개의 요청이 쌓여 있다.

우리가 할 수 있는 가장 좋은 기여 중 하나는 — *기다리는 것*이다. 포크에서 조용히 해결하고, 실사용하고, 검증하고, 지켜본다. upstream이 같은 결론에 도달하면 포크를 드롭하고 돌아온다.

이것은 게으름이 아니다. 존중이다.

그래서 이 문서는

기여 아닌 기여의 기록이다.

  • PR을 제출하지 않았지만, 문제를 정확히 이해했다.
  • 이슈를 등록하지 않았지만, 해법을 검증했다.
  • 메인테이너에게 알리지 않았지만, 2주 뒤 같은 결론에 도달했다.

오픈소스 생태계에서, 같은 방향으로 걸어가는 사람들은 만나지 않아도 결국 같은 곳에 도착한다.

“여기있다. 일일일생이로다.”