Skip to content

feat(session-mcp): git_clone 을 표면에 세운다 (등재 3→2) - #140

Merged
dlddu-k3s-homelab-k3s-mcp[bot] merged 3 commits into
mainfrom
reconcile/rct_20260913-0002-opus-5-1m
Sep 14, 2026
Merged

dlddu-k3s-homelab-k3s-mcp[bot] merged 3 commits into
mainfrom
reconcile/rct_20260913-0002-opus-5-1m

Conversation

@dlddu-k3s-homelab-k3s-mcp

Copy link
Copy Markdown
Contributor

정합성 task rct_20260913-0002 (모델 tbm_session-platform-mcp-tool-roadmap) 의 계획 산출물이다.
자동 머지하지 않는다 — 검토를 거쳐 사람이 머지한다.

gap

모델의 to-be 는 docs/session-mcp-tool-surface.md 의 「다음에 구현할 도구」 절이 비어 있는
상태
(등재된 모든 항목이 표면에 착지했거나 근거와 함께 철회된 상태)다. 실측 등재는 3건이고
표면에 착지한 것은 0건이라 판정 기준 1(미착지 등재)이 3건 열려 있었다. 정의가 「선행 조건이
걸려 있어도 drift 가 아닌 것이 아니다 — 선행 해소가 그 항목 계획의 첫 단계이지 면제 사유가
아니다」로 못박으므로, 2·3 이 R9 앞에 서 있다는 사실은 gap 을 줄이지 않는다.

이 PR 의 범위 — 등재 1번 하나

1번만 지금 착수 가능하다. 남은 둘은 R9(MCP 컨테이너에 게이트웨이 3종 밖의 자격 증명을
요구 = AC-F6 자격 증명 배치 개정)가 선행이고, 3번은 추가로 이 레포 밖의 R4 승인 화면 설계가
필요하다. 그래서 1번만 완주해 등재를 3 → 2 로 줄인다. 남은 2·3 의 번호와 그 사이의
근거(2 → 3 순서)는 한 자도 건드리지 않았다
— 번호를 고정으로 둔 설계가 두 번째로 값을 낸 자리다.

착수 가능성의 근거를 산문으로 믿지 않고 코드에서 재측정했다:

전제 실측
git 이 MCP 컨테이너에 있다 data-plane/Dockerfile 런타임 스테이지가 git 을 설치하고 git --version 으로 빌드를 실패시킨다 — 새 이미지 재료 0
헬퍼 파드가 github.com 으로 나갈 수 있다 network_policy.go 의 정책 쌍은 워크로드 egress 와 헬퍼 ingress 둘뿐이라 MCP 컨테이너의 목적지는 L3/L4 에서 제한되지 않는다(R12) — AC-F2 축의 새 선행 0
새 Secret 이 없다 공개 레포 한정이라 R9 에 걸리지 않는다 — helperPodSpec 의 env 6개는 그대로

무엇을 했나

모양은 참조 구현에서, 게이트와 경로는 이 레포가 새로 씌운다. 참조 구현
dlddu/pure-agentmcp-server/src/tools/git-clone.ts 를 읽어 이름(git_clone)·인자
(url·branch)·응답 모양·5분 타임아웃을 따랐다. 참조 구현의 git_clonegatekeeper 를
부르지 않으므로
(그 레포에서 게이트를 지나는 것은 web_fetch_get 하나뿐) R1 에 따라 게이트를
새로 씌웠다.

의도적으로 벗어난 세 지점 — 셋 다 이 문서의 규칙이 시킨 것이고, 그 근거를 문서에 함께 적었다
(「도구 추가 규칙」의 「어긴다면 그 이유를 이 문서에 함께 적는다」):

  1. 대상 디렉터리 인자를 두지 않는다. 참조 구현은 디렉터리 이름을 호출자가 정하게 하는데,
    R11(「파일명은 MCP 가 정한다 — 인자에서 파생한 이름은 경로 한 조각을 호출자 손에 쥐여 준다」)과
    1번 항목 자신의 판정(「경로는 MCP 가 정하고 결과로 알려주는 쪽이 맞다」)이 정확히 그것을
    금지한다. 경로는 <공유볼륨>/git_clone/<요청id> — 모든 조각이 상수 아니면 서버가 만든 요청
    id 다. 이 항목이 미리 세워 둔 물음(「한 도구가 세운 파일 관례를 둘째가 따를 수 있는가」)의
    답은 「따를 수 있었다」
    — 관례는 바뀌지 않았고 이 도구는 그 옆에 서브트리 하나를 가졌다.
  2. 원격은 http·https 만 받는다. 참조 구현이 함께 받는 SSH 형태는 키를 요구해 곧 R9 이고,
    승인자가 읽는 것도 URL 이 아니게 된다(R4). validateFetchTarget 이 그은 선과 같은 선이다.
  3. URL 에 자격 증명이 실려 있으면 거부한다 — 참조 구현에 없는 추가 제약이고 근거는
    R8 이다: https://사용자:토큰@… 을 통과시키면 토큰이 사람이 읽는 승인 컨텍스트와 로그에 실린다.

게이트·실패 처리는 기존 도구와 한 형태다: 인자 오류와 「공유 볼륨 미구성」은 승인 요청을
만들기 전에 isError 로 끊고(R3), 대기 마커를 먼저 낸 뒤 대기에 들어가고(R6), 거절·만료·
타임아웃·게이트웨이 장애는 전부 isError 도구 결과다(R7). 도구 정의는 toolDefinitions()
if !c.gated() 안쪽이다(R2).

「공개 레포 한정」을 배포 설정이 아니라 코드가 들고 있게 했다. 클론은 credential helper
목록을 비우고(-c credential.helper=) 프롬프트를 끈 채(GIT_TERMINAL_PROMPT=0,
GIT_CONFIG_NOSYSTEM=1) 돈다. 이것은 초안 단계에서 실측이 고친 부분이다 — 프롬프트만 끈
초안을 credential helper 가 구성된 환경에서 실제 git 으로 돌려 보니 private 레포 클론이
성공했다(helper 는 프롬프트 없이 답한다). helper 목록을 비운 뒤 같은 프로브가 0.21초에
fatal: could not read Username for 'https://github.com': terminal prompts disabled 로 끊긴다.

검증 (전부 로컬 재현)

검사 base 99c2166 이 브랜치
check-fidelity-allowlist.py rc=0 rc=0 (seam 집합 불변 — 새 코드가 스캔 토큰을 만들지 않는다)
check-render-fidelity.py rc=0 rc=0
check-scenario-mapping.sh rc=0 rc=0
check_comment_policy.py rc=0 rc=0 (아래 증분 재판정 후)
data-plane go vet · gofmt -l · go test ./... rc=0 rc=0
control-plane go vet · go vet -tags=e2e · gofmt -l · go test ./... rc=0 rc=0

모델 지문 3지점(트리거 시점 / 현재 main / 이 브랜치 = 머지 후 기대값):

트리거 e70d6e4 현재 main 99c2166 이 브랜치
as-is (toolDefinitions) tools:2 ping,web_fetch_get 같음 tools:3 git_clone,ping,web_fetch_get
to-be (등재 절) roadmap:3 1. git_clone|2. K3s MCP 재노출|3. gh CLI 같음 roadmap:2 2. K3s MCP 재노출|3. gh CLI

양쪽이 다 움직이므로 이 슬라이스의 완결은 반드시 재감지되고, 잔여 2건은 그 후속 task 가 잇는다.

음성 대조군: toolDefinitions() 에서 git_clone 정의만 빼면 go test 가 rc=1 로
want exactly the three listed tools 를 정확히 지목하고, 복원하면 인덱스와 바이트 동일이다.

단위 테스트가 단언하는 것 (session_mcp_git_test.go, 실 네트워크·실 git 없이):
승인 후에만 클론(대기 2회를 지나 정확히 1회) · 거절/만료/게이트웨이 장애에서 클론 0회 ·
인자 11종(빈 값·SSH 단축형·ssh://·file://·호스트 없음·선행 대시·제어문자·URL 자격 증명·
브랜치 3종)에서 승인 요청 0건 + 클론 0회 · 볼륨 미구성에서 승인 요청 0건 · 경로가 요청
id 로만 지어지고 두 호출이 다른 경로를 받음 · 승인 컨텍스트가 URL 과 대상 경로를 함께 실음 ·
실패한 클론이 볼륨에 잔재를 남기지 않음 · git 인자에 -c credential.helper=-- 가 올바른
자리에 들어감 · 원격 stderr 가 상한에서 잘리고 버린 바이트 수를 말함.

주석 원장

같은 PR 에서 증분 재판정했다 — 96줄 판정 · 제거 23 · 유지 73, 행 931 → 1004, 합계
3014 → 3087. 신규 2파일을 data-plane 행에 편입했다. 지배 형태는 직전 ping 슬라이스와 같은
② 사본이고 원본도 같았다(같은 PR 이 고친 session-mcp-tool-surface.md).

충돌면 — 대조군 병합으로 귀속을 갈랐다

열린 PR 4건을 main 단독과 main + 이 브랜치 두 번 시험 병합해 충돌 집합을 비교했다:

PR main 단독 main + 이 브랜치 내가 더한 것
#139 충돌 0 docs/comment-policy/ledger.md 1파일
#130 충돌 0 충돌 0 없음
#127 충돌 0 docs/comment-policy/ledger.md 1파일
#106 충돌 8 충돌 8 (같은 집합) 없음

⇒ 이 브랜치가 새로 만드는 충돌 표면은 원장 한 파일이고, 대상은 #139·#127 이다. 셋 다 같은
합계 마커와 (#127 은) 같은 data-plane 행을 움직이므로 그 파일은 설계상 직렬화 지점이다 —
나중에 머지되는 쪽이 행 합계를 재측정해 맞춘다. #106 의 8파일 충돌은 이 브랜치 이전부터
있던 것
이고(2026-09-12T05:33Z 이후 갱신 없음 · base 336bb4b · 등재 4건 시절 문면 ·
이미 없는 경로 docs/comment-policy.md 를 고친다) docs/session-mcp-tool-surface.md 는 세
지점 모두에서 이미 충돌하고 있었다.

범위 밖 (후속)

  • 등재 2번(K3s MCP 재노출)·3번(gh CLI) — R9 가 선행이다. 1번이 빠진 지금 이 로드맵에
    남은 것은 전부 그 문 뒤
    이므로, 다음 작업은 도구 코드가 아니라 AC-F6 개정이다.
  • private 레포 클론 — 2번이 열어 줄 단명 GitHub App 토큰을 기다리는 편이 자격 증명을 하나
    덜 만든다(문서의 근거).
  • 전용 e2e 파일과 docs/test/e2e.md 등재tbm_session-platform-scenario-e2e 소관.
  • 새 코드 주석의 판정 자체tbm_session-platform-comment-redundancy 소관. 이 PR 은 CI
    게이트가 요구하는 증분 재판정만 원장에 적었다.
  • 클론 크기 상한 — 이 도구는 결과물 크기를 미리 재지 않는다. 상한은 코드가 아니라 승인자이고,
    볼륨이 차도 걸리는 것은 그 세션 자신뿐이며 볼륨은 세션과 함께 회수된다. 그 판정을 문서에 적어
    두었으니, 뒤집으려면 그 문장을 먼저 뒤집어야 한다.

🤖 Generated with Claude Code

reconciler-bot and others added 2 commits September 13, 2026 14:36
`docs/session-mcp-tool-surface.md` 의 「다음에 구현할 도구」 1번을 착지시킨다. 남은
2·3 은 R9(AC-F6 자격 증명 배치 개정)이 선행이라 손대지 않았고, 그 번호와 2 → 3
순서의 근거도 한 자도 건드리지 않았다.

이름·인자(`url`·`branch`)·응답 모양·5분 타임아웃은 참조 구현 `dlddu/pure-agent` 의
`git_clone` 을 따르고, 게이트와 대상 경로는 이 레포가 새로 씌운다. 참조 구현에서
의도적으로 벗어난 세 지점(대상 디렉터리 인자 없음 / http·https 만 / URL 자격 증명
거부)의 근거는 표면 문서의 「지금 있는 것」 절에 적었다.

- 경로는 `<공유볼륨>/git_clone/<요청id>` — 모든 조각이 서버의 것이다(R11).
- 공유 볼륨이 없으면 인자 오류와 같은 자리에서 거절한다(R3) — 성공할 수 없는
  호출로 사람을 깨우지 않는다.
- 「공개 레포 한정」은 자격 증명의 부재가 아니라 명령이 강제한다: credential
  helper 목록을 비우고 프롬프트를 끈다(R9).
- 주석 원장은 같은 PR 에서 증분 재판정했다(931 → 1004, 합계 3014 → 3087).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「경계값은 전부 코드가 갖는다」가 세 파일을 가리키는데 이 슬라이스가 5분 타임아웃·
256자 브랜치 상한·4 KiB stderr 상한을 새 파일에 들였다. 포인터 목록이 불완전한
채로 남으면 이 문서가 스스로 경고하는 형태(사본·포인터가 조용히 낡는다)가 된다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
base 신선화 — main 이 99c2166283ec0e 로 4커밋 전진했다.
충돌은 docs/comment-policy/ledger.md 합계 마커 한 줄뿐(main 3054 vs 브랜치 3087).
이 브랜치의 증분 +73(데이터플레인 행 931 → 1004)을 main 값 위에 얹어 3127 로 재측정했다.
check_comment_policy.py 의 R4 양방향 미러가 rc=0 으로 확인한다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants