diff --git a/cmd/rune-mcp/main.go b/cmd/rune-mcp/main.go index c2afa0b0..5f3f2f9d 100644 --- a/cmd/rune-mcp/main.go +++ b/cmd/rune-mcp/main.go @@ -4,7 +4,8 @@ // Spawn model: Claude Code launches one instance per session via stdio. // Lifecycle: starting → waiting_for_vault → active ↔ dormant. // Tools: 8 MCP tools (capture, recall, batch_capture, capture_history, -// delete_capture, vault_status, diagnostics, reload_pipelines). +// +// delete_capture, vault_status, diagnostics, reload_pipelines). // // Wiring: Deps holds a State manager + 3 services. Adapter clients (vault / // envector / embedder) are populated on the services by the boot loop after diff --git a/internal/adapters/config/dormant.go b/internal/adapters/config/dormant.go index 7860bd90..4efd0be2 100644 --- a/internal/adapters/config/dormant.go +++ b/internal/adapters/config/dormant.go @@ -59,7 +59,7 @@ func SaveToPath(cfg *Config, path string) error { // - "not_configured" — config.json missing, fresh install // - "vault_unconfigured" — config exists but Vault.Endpoint/Token empty // - "user_deactivated" — already-dormant config picked up by boot -// (idempotent path, just refreshes timestamp) +// (idempotent path, just refreshes timestamp) func MarkDormant(reason string) error { cfg, err := Load() if err != nil { diff --git a/internal/adapters/config/loader.go b/internal/adapters/config/loader.go index d26025a6..d3c1fc72 100644 --- a/internal/adapters/config/loader.go +++ b/internal/adapters/config/loader.go @@ -3,8 +3,9 @@ // Python: agents/common/config.py (365 LoC) — Go reduced from 7 sections to 3. // // Dropped sections (per scope SOT — docs/v04/overview/architecture.md): -// envector / embedding / llm / scribe / retriever — moved to Vault bundle -// (memory only) or external embedder process. +// +// envector / embedding / llm / scribe / retriever — moved to Vault bundle +// (memory only) or external embedder process. package config import ( @@ -33,8 +34,9 @@ type VaultConfig struct { } // FilePerms — per rune-mcp.md §Config: -// ~/.rune/ 0700 -// ~/.rune/config.json 0600 +// +// ~/.rune/ 0700 +// ~/.rune/config.json 0600 const ( DirPerm = 0700 FilePerm = 0600 diff --git a/internal/adapters/embedder/client_test.go b/internal/adapters/embedder/client_test.go index f62e8012..c9016c63 100644 --- a/internal/adapters/embedder/client_test.go +++ b/internal/adapters/embedder/client_test.go @@ -29,8 +29,8 @@ type fakeRuned struct { infoFn func(*runedv1.InfoRequest) (*runedv1.InfoResponse, error) healthFn func(*runedv1.HealthRequest) (*runedv1.HealthResponse, error) - infoCalls int32 // atomic — Info should be invoked exactly once across the lifetime of an infoCache - embedCalls int32 // atomic — used by retry test to count attempts + infoCalls int32 // atomic — Info should be invoked exactly once across the lifetime of an infoCache + embedCalls int32 // atomic — used by retry test to count attempts embedBatchCalls int32 // atomic — used by batch-split test } diff --git a/internal/adapters/envector/client.go b/internal/adapters/envector/client.go index 33edf1b0..557d3d6c 100644 --- a/internal/adapters/envector/client.go +++ b/internal/adapters/envector/client.go @@ -47,7 +47,7 @@ type Client interface { Insert(ctx context.Context, req InsertRequest) (*InsertResult, error) Score(ctx context.Context, vec []float32) ([][]byte, error) GetMetadata(ctx context.Context, refs []MetadataRef, fields []string) ([]MetadataEntry, error) - OpenIndex(ctx context.Context) error // opens (or creates) the server-side index + OpenIndex(ctx context.Context) error // opens (or creates) the server-side index GetIndexList(ctx context.Context) ([]string, error) // used by diagnostics + warmup Close() error } @@ -65,7 +65,7 @@ type ClientConfig struct { } type client struct { - sdk *envector.Client + sdk *envector.Client keys *envector.Keys idx *envector.Index cfg ClientConfig diff --git a/internal/adapters/envector/errors_test.go b/internal/adapters/envector/errors_test.go index e2666003..a2723c0b 100644 --- a/internal/adapters/envector/errors_test.go +++ b/internal/adapters/envector/errors_test.go @@ -18,45 +18,45 @@ func TestMapSDKError_Nil(t *testing.T) { func TestMapSDKError_SDKSentinels(t *testing.T) { tests := []struct { - name string - err error - wantCode string + name string + err error + wantCode string wantRetry bool }{ { - name: "ErrKeysNotForEncrypt", - err: envector.ErrKeysNotForEncrypt, - wantCode: "DECRYPTOR_UNAVAILABLE", + name: "ErrKeysNotForEncrypt", + err: envector.ErrKeysNotForEncrypt, + wantCode: "DECRYPTOR_UNAVAILABLE", wantRetry: false, }, { - name: "ErrKeysNotForDecrypt", - err: envector.ErrKeysNotForDecrypt, - wantCode: "DECRYPTOR_UNAVAILABLE", + name: "ErrKeysNotForDecrypt", + err: envector.ErrKeysNotForDecrypt, + wantCode: "DECRYPTOR_UNAVAILABLE", wantRetry: false, }, { - name: "ErrKeysNotForRegister", - err: envector.ErrKeysNotForRegister, - wantCode: "KEY_NOT_FOR_REGISTER", + name: "ErrKeysNotForRegister", + err: envector.ErrKeysNotForRegister, + wantCode: "KEY_NOT_FOR_REGISTER", wantRetry: false, }, { - name: "ErrClientClosed", - err: envector.ErrClientClosed, - wantCode: "ENVECTOR_CONNECTION_LOST", + name: "ErrClientClosed", + err: envector.ErrClientClosed, + wantCode: "ENVECTOR_CONNECTION_LOST", wantRetry: true, }, { - name: "ErrKeysNotFound", - err: envector.ErrKeysNotFound, - wantCode: "ENVECTOR_KEYS_NOT_FOUND", + name: "ErrKeysNotFound", + err: envector.ErrKeysNotFound, + wantCode: "ENVECTOR_KEYS_NOT_FOUND", wantRetry: false, }, { - name: "ErrKeysRequired", - err: envector.ErrKeysRequired, - wantCode: "ENVECTOR_KEYS_REQUIRED", + name: "ErrKeysRequired", + err: envector.ErrKeysRequired, + wantCode: "ENVECTOR_KEYS_REQUIRED", wantRetry: false, }, } @@ -142,7 +142,7 @@ func TestMapSDKError_GenericError(t *testing.T) { } } -//--- Error types ---// +// --- Error types ---// func TestError_ErrorString(t *testing.T) { tests := []struct { name string diff --git a/internal/domain/errors.go b/internal/domain/errors.go index f3e73fa7..d10961a2 100644 --- a/internal/domain/errors.go +++ b/internal/domain/errors.go @@ -8,16 +8,16 @@ import "errors" // Code enum — 8 codes. const ( - CodeInternal = "INTERNAL_ERROR" - CodeVaultConnection = "VAULT_CONNECTION_ERROR" - CodeVaultDecryption = "VAULT_DECRYPTION_ERROR" - CodeEnvectorConnection = "ENVECTOR_CONNECTION_ERROR" - CodeEnvectorInsert = "ENVECTOR_INSERT_ERROR" - CodePipelineNotReady = "PIPELINE_NOT_READY" - CodeInvalidInput = "INVALID_INPUT" - CodeEmbedderUnreachable = "EMBEDDER_UNREACHABLE" // Go-specific (D30) - CodeEmptyEmbedText = "EMPTY_EMBED_TEXT" // D5 — dedicated code for missing embed text - CodeExtractionMissing = "EXTRACTION_MISSING" // D14 — agent must provide pre_extraction + CodeInternal = "INTERNAL_ERROR" + CodeVaultConnection = "VAULT_CONNECTION_ERROR" + CodeVaultDecryption = "VAULT_DECRYPTION_ERROR" + CodeEnvectorConnection = "ENVECTOR_CONNECTION_ERROR" + CodeEnvectorInsert = "ENVECTOR_INSERT_ERROR" + CodePipelineNotReady = "PIPELINE_NOT_READY" + CodeInvalidInput = "INVALID_INPUT" + CodeEmbedderUnreachable = "EMBEDDER_UNREACHABLE" // Go-specific (D30) + CodeEmptyEmbedText = "EMPTY_EMBED_TEXT" // D5 — dedicated code for missing embed text + CodeExtractionMissing = "EXTRACTION_MISSING" // D14 — agent must provide pre_extraction ) // RuneError — MCP error response body (Python make_error equivalent). diff --git a/internal/domain/extraction.go b/internal/domain/extraction.go index aad202f2..6e3e6576 100644 --- a/internal/domain/extraction.go +++ b/internal/domain/extraction.go @@ -61,7 +61,6 @@ func (r *ExtractionResult) IsBundle() bool { return r.GroupType == "bundle" && len(r.Phases) > 1 } - // ParseExtractionFromAgent builds Detection + ExtractionResult from the flat // CaptureRequest.Extracted dict sent by the agent. Wire → internal conversion. // diff --git a/internal/domain/schema.go b/internal/domain/schema.go index ffbccf8b..ae2f4cdf 100644 --- a/internal/domain/schema.go +++ b/internal/domain/schema.go @@ -210,9 +210,9 @@ type Payload struct { // DecisionRecord — §3. Python: decision_record.py:L166-213. // envector.Insert metadata의 decrypted payload. type DecisionRecord struct { - SchemaVersion string `json:"schema_version"` // fixed "2.1" - ID string `json:"id"` - Type string `json:"type"` // fixed "decision_record" + SchemaVersion string `json:"schema_version"` // fixed "2.1" + ID string `json:"id"` + Type string `json:"type"` // fixed "decision_record" Domain Domain `json:"domain"` Sensitivity Sensitivity `json:"sensitivity"` diff --git a/internal/lifecycle/boot.go b/internal/lifecycle/boot.go index c18e398f..8b02af02 100644 --- a/internal/lifecycle/boot.go +++ b/internal/lifecycle/boot.go @@ -187,7 +187,7 @@ const ( // - vault endpoint/token empty → terminal Dormant (await /rune:configure) // - vault dial / GetAgentManifest → state=WaitingForVault, exp backoff retry // - keymanager / embedder / envector init → exp backoff retry (might be -// transient — daemon down, etc.) +// transient — daemon down, etc.) // - other config error (parse fail) → exp backoff retry (user might be editing) // - ctx cancellation → return immediately // diff --git a/internal/mcp/tools.go b/internal/mcp/tools.go index 09f484c0..c8c2e733 100644 --- a/internal/mcp/tools.go +++ b/internal/mcp/tools.go @@ -2,8 +2,9 @@ // owns Deps injection + state-aware response shaping. // // Spec: -// docs/v04/spec/components/rune-mcp.md (MCP server 구현) -// docs/v04/spec/flows/{capture,recall,lifecycle}.md +// +// docs/v04/spec/components/rune-mcp.md (MCP server 구현) +// docs/v04/spec/flows/{capture,recall,lifecycle}.md // // SDK: github.com/modelcontextprotocol/go-sdk v1.5.0+ (D2). Stdio transport. // Input schema is auto-inferred from the Go input struct (jsonschema tags @@ -200,4 +201,3 @@ func isValidToolName(name string) bool { } return true } - diff --git a/internal/policy/record_builder.go b/internal/policy/record_builder.go index 5cdf200d..839c39f5 100644 --- a/internal/policy/record_builder.go +++ b/internal/policy/record_builder.go @@ -17,7 +17,7 @@ import ( // MAX_INPUT_CHARS — Python L227. Truncate cleanText before extraction. const MaxInputChars = 12_000 -// QuotePatterns — 4 regex (Python L72-77): double "", single '', Japanese 「」, +// QuotePatterns — 4 regex (Python L72-77): double "", single ”, Japanese 「」, // French «». Min 10 chars. var QuotePatterns = []*regexp.Regexp{ regexp.MustCompile(`"([^"]{10,})"`), diff --git a/internal/policy/rerank.go b/internal/policy/rerank.go index ffb77f52..511c75c9 100644 --- a/internal/policy/rerank.go +++ b/internal/policy/rerank.go @@ -41,7 +41,6 @@ var TimeRanges = map[domain.TimeScope]time.Duration{ // // BIT-IDENTICAL REQUIREMENT: Python timedelta.days is integer floor. // Go Hours()/24 is float — must math.Floor to match. -// func ApplyRecencyWeighting(hits []domain.SearchHit, now time.Time) []domain.SearchHit { for i := range hits { r := &hits[i] diff --git a/internal/service/capture.go b/internal/service/capture.go index 91118c17..2ee35fc5 100644 --- a/internal/service/capture.go +++ b/internal/service/capture.go @@ -3,9 +3,10 @@ // delegate to these services; business logic lives here, not in handlers. // // Spec: -// docs/v04/spec/flows/capture.md (7-phase) -// docs/v04/spec/flows/recall.md (7-phase) -// docs/v04/spec/flows/lifecycle.md (6 tools) +// +// docs/v04/spec/flows/capture.md (7-phase) +// docs/v04/spec/flows/recall.md (7-phase) +// docs/v04/spec/flows/lifecycle.md (6 tools) package service import ( diff --git a/internal/service/lifecycle.go b/internal/service/lifecycle.go index 0504ad4b..e07f2c8d 100644 --- a/internal/service/lifecycle.go +++ b/internal/service/lifecycle.go @@ -112,10 +112,10 @@ type DiagnosticsResult struct { // EnvInfo — OS, Go runtime version, cwd. type EnvInfo struct { - OS string `json:"os"` - Runtime string `json:"runtime"` - CWD string `json:"cwd"` - GOArch string `json:"goarch"` + OS string `json:"os"` + Runtime string `json:"runtime"` + CWD string `json:"cwd"` + GOArch string `json:"goarch"` } // VaultInfo — subset exposed in diagnostics. @@ -168,10 +168,10 @@ func (s *LifecycleService) Diagnostics(ctx context.Context) *DiagnosticsResult { // Environment cwd, _ := os.Getwd() r.Environment = EnvInfo{ - OS: runtime.GOOS, - Runtime: runtime.Version(), - CWD: cwd, - GOArch: runtime.GOARCH, + OS: runtime.GOOS, + Runtime: runtime.Version(), + CWD: cwd, + GOArch: runtime.GOARCH, } // Config state @@ -490,11 +490,12 @@ const WarmupTimeout = 60 * time.Second // // TODO: currently a no-op for state recovery — only envector warmup probe runs. // Full re-init requires: -// 1. internal/lifecycle/boot.go::RunBootLoop body (Vault.GetAgentManifest + bundle setup -// + envector.NewClient + state=Active transition) -// 2. wiring here to re-trigger boot logic on call (state.SetState(Starting) + -// RunBootLoop re-invoke, or a shared _init_pipelines helper called from both -// startup and this function) +// 1. internal/lifecycle/boot.go::RunBootLoop body (Vault.GetAgentManifest + bundle setup +// + envector.NewClient + state=Active transition) +// 2. wiring here to re-trigger boot logic on call (state.SetState(Starting) + +// RunBootLoop re-invoke, or a shared _init_pipelines helper called from both +// startup and this function) +// // Until both land, /rune:activate cannot recover from dormant or trigger first-time // pipeline init. func (s *LifecycleService) ReloadPipelines(ctx context.Context) (*ReloadPipelinesResult, error) { diff --git a/internal/service/recall.go b/internal/service/recall.go index 3a644646..bff67af3 100644 --- a/internal/service/recall.go +++ b/internal/service/recall.go @@ -635,9 +635,9 @@ func calculateConfidence(results []domain.SearchHit) float64 { } certaintyWeights := map[string]float64{ - "supported": 1.0, - "partially_supported": 0.6, - "unknown": 0.3, + "supported": 1.0, + "partially_supported": 0.6, + "unknown": 0.3, } totalScore := 0.0