feat: replace Python MCP plugin with Go runtime (v0.4.0)#155
Open
esifea wants to merge 226 commits into
Open
Conversation
…edder' architecture
…28 bit-identical) — P1 #7
5-agent 외부 독립검증(mcp/ + agents/ 전수 스캔)에서 발견한 scope 경계 모호성 해소. P0 (scope 명확화): - architecture.md: 최상단에 Scope (SOT) 박스 신설. Python v0.3.x agent-delegated 경로만 canonical 선언 + scope 밖 8항목 표 (legacy 3-tier, synthesizer, _parse_multilingual, auto-provider, local embedder 등). Python도 같은 방향으로 수렴 명시 - types.md: §3a Agent extraction types 추가. ExtractedFields / PhaseExtractedFields / ExtractionResult Go struct + IsMultiPhase/IsBundle + phase_chain 7 / bundle 5 상한 + wire↔internal 매핑 표 (CaptureRequest의 flat JSON이 Detection + ExtractionResult로 split되는 규칙) - envector.md / vault.md / rune-mcp.md: 3-레이어 복호화 경계 통일. envector SDK 는 opaque string만 취급 / service 레이어(Python searcher.py:L444,L455 ↔ Go recall.go Phase 5)가 Vault.DecryptMetadata 직접 호출 P1 (divergence 명시): - vault.md: agent_dek 32B 검증 — Python (envector_sdk.py:L139)에 없는 보안 gap을 Go가 fail-fast로 막음 (의도적 개선) - recall.md: _calculate_confidence의 "/2.0" 의도 주석 — top-5 position_weight 합(≈2.283)의 근사 정규화 상수 - rune-mcp.md: capture_log flock — Python은 O_APPEND만(kernel atomic), Go는 보수적 flock 추가 (multi-session 대비) - python-parity-final.md: get_related 전역 grep 0 caller 확정 (2026-04-22) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rune-mcp Go port skeleton. No internal logic — types, signatures, TODOs,
and Python references only. Builds with `go build ./...` using stdlib only;
no external dependencies (MCP SDK, gRPC, envector-go SDK) yet.
Package layout (follows spec/components/rune-mcp.md + each flow's "Package
layout" section):
cmd/rune-mcp/main.go # stdio entry + signal handling
go.mod # module github.com/envector/rune-go (go 1.24)
internal/domain/ (7) # types.md §1-6 1:1
schema.go # 6 schema enums + 9 sub-models + DecisionRecord v2.1 + GenerateRecordID/GroupID (word-level slug, unicode.IsLetter/Digit) + §7 helpers
extraction.go # §3a ExtractionResult hierarchy (3 structs + IsMultiPhase/IsBundle)
capture.go # §4.1 CaptureRequest/Response + RawEvent
query.go # §1.7-8, §4.2, §5.1-3 (RecallArgs/Result, SearchHit, ParsedQuery, Detection, ExtractPayloadText strict v2.1)
novelty.go # §5.4 NoveltyInfo (inverted score, 4 classes)
errors.go # 10 error codes (Python 7 + EMBEDDER_UNREACHABLE + EMPTY_EMBED_TEXT + EXTRACTION_MISSING)
logio.go # §6 CaptureLogEntry (NoveltyScore *float64 for omitempty)
internal/policy/ (6) # pure functions, no I/O
novelty.go # ClassifyNovelty + D11 thresholds 0.3/0.7/0.95
rerank.go # HalfLifeDays=90, (0.7xraw + 0.3xdecay) x status_mul, TimeRanges map
query.go # Parse stub + IntentRules/TimeRules/StopWords/TechPatterns placeholders (31+16+81+4 TODO)
record_builder.go # BuildPhases stub + MaxInputChars=12_000 + Quote/Rationale placeholders
payload_text.go # RenderPayloadText stub (D15 canonical ref + subtle behavior notes)
pii.go # RedactSensitive + 5 SENSITIVE_PATTERNS placeholder
internal/adapters/ (12)
config/loader.go # Config 3-section (vault/state/metadata) + DirPerm/FilePerm (0700/0600)
vault/client.go # Client interface (3 RPCs) + MaxMessageLength 256MB + ValidateAgentDEK (Go fail-fast)
vault/endpoint.go # NormalizeEndpoint 4-form URL parsing (tcp://, http(s)://, host:port, host)
vault/health.go # HealthFallback Tier 2 HTTP /health (strip /mcp /sse)
vault/errors.go # 5 sentinels + ErrNotHTTPScheme + MapGRPCError
envector/client.go # Client interface + InsertRequest/MetadataRef/Entry
envector/aes_ctr.go # Seal/Open stubs (AES-256-CTR envelope {"a","c"})
envector/errors.go # 4 sentinels + MapSDKError (Python 11 patterns NOT ported — intentional)
embedder/client.go # Client interface + RetryBackoffs [0, 500ms, 2s]
embedder/info_cache.go # infoCache sync.Once + Get/Snapshot
embedder/retry.go # retry[R any] generic helper + retryable(gRPC codes) stub
logio/capture_log.go # Append (flock) + Tail (reverse jsonl) stubs
internal/service/ (5) # 7-phase orchestration (business logic lives here, not in handlers)
capture.go # CaptureService.Handle/Batch + Phase 2-7 helpers + BatchCaptureArgs/Result
recall.go # RecallService.Handle + searchWithExpansions/searchSingle/resolveMetadata/classifyMetadata/toSearchHit/expandPhaseChains/assembleGroups/applyMetadataFilters/buildResult/calculateConfidence
lifecycle.go # LifecycleService.{VaultStatus,Diagnostics,CaptureHistory,DeleteCapture,ReloadPipelines} + 8 result types
search.go # SearchByID (shared by recall + delete_capture) — "ID: {id}" hack
diagnostics_classify.go # ClassifyEnvectorError (gRPC code-based, not Python string patterns)
internal/mcp/ (2)
tools.go # 8 MCP tool handler stubs + Deps + Register (SDK wiring)
state.go # CheckState + ValidateCaptureRequest/RecallArgs + TruncateTitle/ClampConfidence + state-specific recovery hints
internal/lifecycle/ (2)
boot.go # State enum (4 values, atomic) + Manager + BootBackoffs (1s->60s cap) + RunBootLoop stub
shutdown.go # GracefulShutdown 3-step (drain inflight 30s + adapter Close + DEK zeroize) + InflightTracker + ZeroizeDEK
internal/obs/ (1)
slog.go # SensitiveFilter 2 regex placeholder + request_id context
Every file includes:
- Python source file:line references
- docs/v04 spec section references
- Relevant decision numbers (D2/D3/D11/D13-17/D22-28/D30-32)
- TODO comments pointing to where real implementation lives
Next step (separate PR): add external deps (go-sdk, grpc, envector-go-sdk),
then fill in real implementation following the Phase 1-7 roadmap
(docs/v04/README.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README.md:
- Add §구현 로드맵 section — 7 phases (external deps → domain/policy →
record_builder/payload_text port → adapters → service orchestration →
MCP SDK wiring → verification) with scope notes and priority tips
- Add "Go skeleton ✅ 완료" row to §상태 table, referencing 2eb167d
notes/implementability-report.md:
- Update §Go 구현 진입 로드맵 — mark Phase 0 (docs P0/P1 + skeleton)
done; point to README §구현 로드맵 as single source for Phase 1+
Rationale: skeleton is now compile-clean and covers every doc section, so
the next actionable step is a documented phase-by-phase implementation
plan that contributors can pick up as separate PRs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Enable new developers to locate their first PR target within 10 minutes
without reading the entire docs/v04/ tree upfront.
New files:
internal/README.md
- Package dependency graph (domain → policy/adapters/lifecycle/obs →
service → mcp → cmd) with import rules
- Per-file table for every package: role · Python origin ·
spec doc · relevant Phase
- Working rules (Python as canonical · no ad-hoc decision changes ·
build baseline · TODO lifetime · dependency direction)
- Links to every relevant docs/v04/ document
docs/v04/onboarding.md
- 10-minute route (context → navigation → first target)
- Environment setup (Go toolchain · IDE · build/vet/lint/test commands)
- Reading order per Phase (only read what the current Phase needs)
- First-PR recommendations per Phase with concrete starter tasks:
* Phase 2: ParseDomain / ClassifyNovelty / GenerateRecordID tests /
MakeError
* Phase 3: RedactSensitive regex port
* Phase 4: NormalizeEndpoint edge-case tests
* Heavy: RenderPayloadText full canonical port
- Conventions (Python bit-identical · TODO format · test layout ·
directory boundaries · commit messages · PR size)
- FAQ (Python source · decision changes · external deps · float
precision · scope · agent contract · Python deviation detection)
Updated:
docs/v04/README.md
- Reading order "Go로 구현할 개발자" section: onboarding.md first,
then internal/README.md, then spec docs
- Status table: add row for "개발자 onboarding 가이드 ✅ 완료"
Rationale: the skeleton (2eb167d) covers every doc section, but new
developers still face a cold-start problem — 16 design docs + 37 Go files.
These two files are the navigation map that collapses that surface into
a predictable entry path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs/v04/notes/flow-matrix.md: - 10 플로우 (8 MCP tool + boot/shutdown) 인벤토리 - 플로우 × 파일 매트릭스 (Infra/MCP · Service · Adapter · Policy/Domain 4 분할) - Tier S/A/B 공통 모듈 분류 + 팀 분업 제안 - §0 TL;DR: 결론 4줄, I/O 한눈 요약, 핵심 인사이트 4개, 역할별 읽기 가이드 internal/mcp/tools.go: - ToolDeleteCapture 주석 Python line ref 정정 (L1113 → L1123). 실제 async def tool_delete_capture 시작 라인, service/lifecycle.go와 일관화. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cmd/rune-mcp/main.go: MCP server bootstrap (NewServer + Register +
StdioTransport.Run). Empty Deps, no boot loop / config.Load yet.
isNormalShutdown() drops exit 1 for stdin EOF · ctx cancel ·
jsonrpc2.ErrServerClosing (internal SDK error, matched by message).
internal/mcp/tools.go: Register binds all 8 tools via stubHandler[In, Out].
Input/output schema auto-inferred; tools/call returns IsError
"not yet implemented (skeleton phase A)". Phase 5 swaps the stub for
service-layer wrappers.
go.mod/go.sum: modelcontextprotocol/go-sdk v1.5.0 (D2). Go 1.24 → 1.25
per SDK requirement.
.gitignore: bin/ + *.test + coverage.out.
Smoke tests:
./bin/rune-mcp < /dev/null → exit 0
echo '{"method":"initialize",...}' | ./bin/rune-mcp
→ {"result":{"serverInfo":{"name":"rune-mcp","version":"0.4.0-alpha"},
"capabilities":{"tools":{"listChanged":true},...}}}, exit 0
다음: ~/.claude/mcp.json에 별도 entry로 등록 → Claude Code에서 8개 tool 인식 확인.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
새 디렉토리 docs/v04/progress/ 신설 — spec(How)·overview(Why)·notes (검증 로그)와 별개로 "실제 구현이 어디까지 동작하는가 + 어떻게 직접 검증하는가"를 vertical slice 단위로 추적. phase-a-mcp-boot.md (직전 커밋 19b7bf6과 한 쌍): - 동작하는 기능 6가지 (빌드 · initialize · tools/list · schema 자동 추론 · tools/call stub · 정상 종료) - 동작하지 않는 것 (Phase A 한계 표 — Vault·envector·embedder·service 레이어 전부 미구현) - 확인법 3 레벨: CLI 직접 / Claude Code 등록 / MCP Inspector 각 레벨마다 step + 기대 출력 + 합격 기준 - Troubleshooting + 코드 변경 요약 + 다음 마일스톤 후보 progress/README.md (인덱스): - 디렉토리 목적 · spec/notes와의 차이 - 문서 명명 규칙 + "Phase A vs Phase 1~7" 관계 - 현재까지 추적된 마일스톤 표 (Phase A only) + 예정 마일스톤 docs/v04/README.md: 디렉토리 구조 표에 progress/ + notes/flow-matrix.md 한 줄씩 추가. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dance The MCP server advertises recall's call signature and parameter types to the session, so the hand-written call block duplicated it. Replace with prose covering only what the schema omits: status enum, domain examples, since ISO format, and topk default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The MCP server advertises capture's `extracted` param as type=object (additionalProperties: true), so passing a JSON string fails schema validation. The "JSON string, not a JSON object" instruction was stale from when the server json.loads'd a string param. Note batch_capture's `items` is genuinely type=string and is left unchanged. Fixed across the claude, gemini, and codex agent docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cument refactor: remove deprecated v0.3 artifacts, fix dangling refs
runed and rune-mcp now name their release assets by build OS (runed-<ver>-ubuntu-2204-amd64.tar.gz / runed-<ver>-mac-14-arm64.tar.gz, rune-mcp-ubuntu-2204-amd64, ...) instead of GOOS, to encode the glibc baseline — see CryptoLabInc/runed#9 and the matching rune-mcp change. The manifest generator hardcoded the old runed-<ver>-<goos>-<arch>.tar.gz and rune-mcp-<goos>-<arch> names, so it would build dead URLs and fail to read the sha256 entries. Resolve each platform's asset from the downloaded sha256 / checksums.txt files instead: map the manifest platform's GOOS to the os-type the downstream repos emit (linux -> ubuntu, darwin -> mac) and glob the exact OS version from the filenames, so a downstream runner bump needs no change here. The manifest platform keys (linux-amd64, darwin-arm64, ...) — the GOOS-GOARCH keys the rune CLI looks up at runtime — are unchanged.
ci: resolve downstream asset names by build OS in manifest
chore: remove stale gemini-extension.json (v0.4 dropped contextFileName)
runed/rune-mcp now report an idle-suspended embedder as IDLE. Add a /rune:status rendering rule so IDLE shows a paused/ready marker and the resumes-on-next-request message instead of looking broken.
feat(status): render embedder IDLE as healthy, not an error
feat: bump up pinned releases
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replace Python MCP server with
runeCLI +rune-mcp+runedwritten in Go.rune-mcp: https://github.com/CryptoLabInc/rune-mcpruned: https://github.com/CryptoLabInc/runed