From ef7a62c42516975fc22c7f339e813e177cc287ce Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Fri, 26 Jun 2026 06:24:48 +0530 Subject: [PATCH 1/2] ci: add CODEOWNERS and dependabot.yml; test: add t.Parallel() to unit tests --- .github/CODEOWNERS | 26 ++++++++++++++ .github/dependabot.yml | 16 +++++++++ browse/browse_test.go | 9 +++++ compact/compact_test.go | 10 ++++++ config/config_test.go | 4 +++ config/validation_test.go | 10 ++++++ conflict/resolver_test.go | 13 +++++++ conflict/validity_test.go | 1 + dedup/window_test.go | 6 ++++ embeddings/defaults_test.go | 3 ++ embeddings/memo_test.go | 7 ++++ embeddings/ratelimit_test.go | 6 ++++ engine/addonly_test.go | 1 + engine/bloom_test.go | 6 ++++ engine/boundary_test.go | 5 +++ engine/branch_test.go | 3 ++ engine/cognitive/boundary_test.go | 9 +++++ engine/cognitive/cognitive_engines_test.go | 8 +++++ engine/cognitive/procedural_test.go | 11 ++++++ engine/community_test.go | 4 +++ engine/consolidation_test.go | 4 +++ engine/context_pack_test.go | 8 +++++ engine/engine_test.go | 17 +++++++++ engine/entity_boost_test.go | 4 +++ engine/events_test.go | 2 ++ engine/feedback_test.go | 14 ++++++++ engine/fused_recall_test.go | 10 ++++++ engine/hierarchy_test.go | 3 ++ engine/hnsw_test.go | 6 ++++ engine/integrity_test.go | 4 +++ engine/llm_consolidation_test.go | 12 +++++++ engine/llm_entities_test.go | 3 ++ engine/lsh_test.go | 7 ++++ engine/memory_file_test.go | 3 ++ engine/multifactor_rank_test.go | 10 ++++++ engine/pagerank_test.go | 1 + engine/profile_test.go | 4 +++ engine/query_keygen_test.go | 6 ++++ engine/query_test.go | 15 ++++++++ engine/rules_test.go | 4 +++ engine/scoring_test.go | 6 ++++ engine/search_decay_test.go | 12 +++++++ engine/sparsify_test.go | 3 ++ engine/topic_consolidation_test.go | 5 +++ exportimport/export_test.go | 10 ++++++ exportimport/langgraph_test.go | 7 ++++ git/watcher_test.go | 8 +++++ graph/community_test.go | 14 ++++++++ graph/graph_test.go | 7 ++++ hooks/conversation_test.go | 12 +++++++ hooks/relevance_test.go | 11 ++++++ hooks/runner_test.go | 13 +++++++ ingest/chunker_test.go | 28 +++++++++++++++ ingest/dual_stream_test.go | 6 ++++ intent/intent_test.go | 29 +++++++++++---- internal/daemon/daemon_test.go | 3 ++ internal/proactive/preload_test.go | 10 ++++++ internal/search/intent_test.go | 4 +++ internal/server/dashboard_test.go | 5 +++ internal/server/handlers_extra_test.go | 9 +++++ internal/server/mcp_concurrency_rest_test.go | 16 +++++++++ internal/server/mcp_graph_test.go | 23 ++++++++++++ internal/server/mcp_test.go | 15 ++++++++ internal/server/rest_test.go | 8 +++++ internal/server/streaming_test.go | 2 ++ internal/telemetry/metrics_test.go | 3 ++ internal/temporal/temporal_test.go | 10 ++++++ internal/tls/tls_test.go | 6 ++++ internal/tui/tui_test.go | 14 ++++++++ internal/version/version_test.go | 5 +++ memory_export_test.go | 7 ++++ mental/model_test.go | 15 ++++++-- privacy/filter_test.go | 24 +++++++++++++ profile/profile_test.go | 10 ++++++ skill/skill_test.go | 20 ++++++++--- spatial_memory_test.go | 38 ++++++++++++++++++++ temporal/backbone_test.go | 9 +++++ utils/utils_test.go | 13 ++++--- yaad_test.go | 27 ++++++++++++++ 79 files changed, 744 insertions(+), 18 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f5b6901 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,26 @@ +# CODEOWNERS for yaad (memory & knowledge-graph engine) +* @GrayCodeAI/maintainers + +# Engine core +/engine/ @GrayCodeAI/core-team +/embeddings/ @GrayCodeAI/core-team +/graph/ @GrayCodeAI/core-team +/compact/ @GrayCodeAI/core-team +/dedup/ @GrayCodeAI/core-team +/conflict/ @GrayCodeAI/core-team +/browse/ @GrayCodeAI/core-team +/config/ @GrayCodeAI/core-team +/hooks/ @GrayCodeAI/core-team + +# API surface +/api/ @GrayCodeAI/core-team + +# CI / release / build tooling +/.github/ @GrayCodeAI/devops-team +/Makefile @GrayCodeAI/devops-team +/lefthook.yml @GrayCodeAI/devops-team +/scripts/ @GrayCodeAI/devops-team + +# Documentation +*.md @GrayCodeAI/docs-team +/docs/ @GrayCodeAI/docs-team diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..1b614bb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: weekly + groups: + go-deps: + patterns: ["*"] + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + groups: + actions: + patterns: ["*"] diff --git a/browse/browse_test.go b/browse/browse_test.go index 815f640..668fbba 100644 --- a/browse/browse_test.go +++ b/browse/browse_test.go @@ -21,6 +21,7 @@ func sampleMemories() []MemoryItem { } func TestBuildFromMemories(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -30,6 +31,7 @@ func TestBuildFromMemories(t *testing.T) { } func TestList(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -58,6 +60,7 @@ func TestList(t *testing.T) { } func TestGet(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -83,6 +86,7 @@ func TestGet(t *testing.T) { } func TestTree(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -106,6 +110,7 @@ func TestTree(t *testing.T) { } func TestSearch(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -125,6 +130,7 @@ func TestSearch(t *testing.T) { } func TestAdd(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -167,6 +173,7 @@ func TestAdd(t *testing.T) { } func TestRemove(t *testing.T) { + t.Parallel() fs := NewMemoryFS() fs.BuildFromMemories(sampleMemories()) @@ -194,6 +201,7 @@ func TestRemove(t *testing.T) { } func TestBuildFromMemoriesWithTypes(t *testing.T) { + t.Parallel() now := time.Now() memories := []MemoryItem{ {ID: "item1", Content: "content1", Category: "cat", Type: "subtype", CreatedAt: now}, @@ -211,6 +219,7 @@ func TestBuildFromMemoriesWithTypes(t *testing.T) { } func TestEmptyFS(t *testing.T) { + t.Parallel() fs := NewMemoryFS() root := fs.List("/") diff --git a/compact/compact_test.go b/compact/compact_test.go index 7444c28..48e6c42 100644 --- a/compact/compact_test.go +++ b/compact/compact_test.go @@ -21,6 +21,7 @@ func setupStore(t *testing.T) storage.Storage { } func TestNeedsCompaction_EmptyProject(t *testing.T) { + t.Parallel() store := setupStore(t) c := New(store, 100) ctx := context.Background() @@ -35,6 +36,7 @@ func TestNeedsCompaction_EmptyProject(t *testing.T) { } func TestNeedsCompaction_OverBudget(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -68,6 +70,7 @@ func TestNeedsCompaction_OverBudget(t *testing.T) { } func TestCompact_NoNodesNoError(t *testing.T) { + t.Parallel() store := setupStore(t) c := New(store, 100) ctx := context.Background() @@ -82,6 +85,7 @@ func TestCompact_NoNodesNoError(t *testing.T) { } func TestCompact_SkipsHighConfidenceNodes(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -111,6 +115,7 @@ func TestCompact_SkipsHighConfidenceNodes(t *testing.T) { } func TestCompact_CompactsLowConfidenceNodes(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -151,6 +156,7 @@ func TestCompact_CompactsLowConfidenceNodes(t *testing.T) { } func TestCompact_SkipsAnchorTypes(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -180,6 +186,7 @@ func TestCompact_SkipsAnchorTypes(t *testing.T) { } func TestCompact_CancelledContext(t *testing.T) { + t.Parallel() store := setupStore(t) c := New(store, 100) ctx, cancel := context.WithCancel(context.Background()) @@ -192,6 +199,7 @@ func TestCompact_CancelledContext(t *testing.T) { } func TestDefaultSummarizer(t *testing.T) { + t.Parallel() s := DefaultSummarizer{} ctx := context.Background() @@ -209,6 +217,7 @@ func TestDefaultSummarizer(t *testing.T) { } func TestNew_DefaultMaxTokens(t *testing.T) { + t.Parallel() store := setupStore(t) c := New(store, 0) if c.maxTokens != 50000 { @@ -217,6 +226,7 @@ func TestNew_DefaultMaxTokens(t *testing.T) { } func TestNew_NegativeMaxTokens(t *testing.T) { + t.Parallel() store := setupStore(t) c := New(store, -10) if c.maxTokens != 50000 { diff --git a/config/config_test.go b/config/config_test.go index c25405b..96976d0 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -7,6 +7,7 @@ import ( ) func TestDefault(t *testing.T) { + t.Parallel() cfg := Default() if cfg.Server.Port != 3456 { @@ -30,6 +31,7 @@ func TestDefault(t *testing.T) { } func TestLoad_NoConfigFile(t *testing.T) { + t.Parallel() cfg, err := Load("/nonexistent/path") if err != nil { t.Fatalf("loading from nonexistent path should not error: %v", err) @@ -40,6 +42,7 @@ func TestLoad_NoConfigFile(t *testing.T) { } func TestLoad_ProjectConfig(t *testing.T) { + t.Parallel() dir := t.TempDir() yaadDir := filepath.Join(dir, ".yaad") os.MkdirAll(yaadDir, 0o755) @@ -75,6 +78,7 @@ half_life_days = 60 } func TestLoad_InvalidTOML(t *testing.T) { + t.Parallel() dir := t.TempDir() yaadDir := filepath.Join(dir, ".yaad") os.MkdirAll(yaadDir, 0o755) diff --git a/config/validation_test.go b/config/validation_test.go index db7ec2c..17c16ca 100644 --- a/config/validation_test.go +++ b/config/validation_test.go @@ -6,6 +6,7 @@ import ( ) func TestValidateConfig_DefaultIsValid(t *testing.T) { + t.Parallel() cfg := Default() errs := ValidateConfig(cfg) if len(errs) != 0 { @@ -14,6 +15,7 @@ func TestValidateConfig_DefaultIsValid(t *testing.T) { } func TestValidateConfig_TableDriven(t *testing.T) { + t.Parallel() tests := []struct { name string mutate func(*Config) @@ -196,7 +198,9 @@ func TestValidateConfig_TableDriven(t *testing.T) { } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() cfg := Default() tt.mutate(cfg) errs := ValidateConfig(cfg) @@ -229,6 +233,7 @@ func TestValidateConfig_TableDriven(t *testing.T) { } func TestConfigError_String(t *testing.T) { + t.Parallel() e := ConfigError{ Field: "server.port", Message: "port must be between 1 and 65535", @@ -255,6 +260,7 @@ func TestConfigError_String(t *testing.T) { } func TestValidationErrorType_String(t *testing.T) { + t.Parallel() cases := map[ValidationErrorType]string{ MissingRequired: "missing required", InvalidValue: "invalid value", @@ -271,6 +277,7 @@ func TestValidationErrorType_String(t *testing.T) { } func TestFormatErrors_Empty(t *testing.T) { + t.Parallel() if s := FormatErrors(nil); s != "" { t.Errorf("expected empty string for nil errors, got %q", s) } @@ -280,6 +287,7 @@ func TestFormatErrors_Empty(t *testing.T) { } func TestFormatErrors_Multiple(t *testing.T) { + t.Parallel() errs := []ConfigError{ {Field: "server.port", Message: "out of range", ErrType: OutOfRange}, {Field: "server.host", Message: "required", ErrType: MissingRequired}, @@ -294,6 +302,7 @@ func TestFormatErrors_Multiple(t *testing.T) { } func TestValidateConfig_BoundaryValues(t *testing.T) { + t.Parallel() cfg := Default() // Valid boundary values should pass. cfg.Server.Port = 1 @@ -314,6 +323,7 @@ func TestValidateConfig_BoundaryValues(t *testing.T) { } func TestValidateConfig_EmbeddingsEnabledWithProvider(t *testing.T) { + t.Parallel() cfg := Default() cfg.Embeddings.Enabled = true cfg.Embeddings.Provider = "openai" diff --git a/conflict/resolver_test.go b/conflict/resolver_test.go index 697bd75..96e4454 100644 --- a/conflict/resolver_test.go +++ b/conflict/resolver_test.go @@ -8,6 +8,7 @@ import ( ) func TestIsContradiction_ExplicitSignal(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "Use jose library instead of jsonwebtoken for JWT validation", Type: "convention", @@ -24,6 +25,7 @@ func TestIsContradiction_ExplicitSignal(t *testing.T) { } func TestIsContradiction_NoOverlap(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "Deploy using Docker containers", Type: "decision", @@ -40,6 +42,7 @@ func TestIsContradiction_NoOverlap(t *testing.T) { } func TestIsContradiction_SameDecisionUpdated(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "Authentication uses RS256 algorithm with rotating keys for token signing", Type: "decision", @@ -56,6 +59,7 @@ func TestIsContradiction_SameDecisionUpdated(t *testing.T) { } func TestIsContradiction_LowOverlap(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "The server runs on port 8080", Type: "spec", @@ -72,6 +76,7 @@ func TestIsContradiction_LowOverlap(t *testing.T) { } func TestExtractKeyTerms(t *testing.T) { + t.Parallel() terms := extractKeyTerms("Use the jose library for JWT validation") if !terms["jose"] { t.Error("expected 'jose' in key terms") @@ -88,6 +93,7 @@ func TestExtractKeyTerms(t *testing.T) { } func TestIsStopWord(t *testing.T) { + t.Parallel() if !isStopWord("the") { t.Error("'the' should be a stop word") } @@ -97,6 +103,7 @@ func TestIsStopWord(t *testing.T) { } func TestIsContradiction_ContradictoryAdjectives(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "The authentication service is fast and stable", Type: "decision", @@ -113,6 +120,7 @@ func TestIsContradiction_ContradictoryAdjectives(t *testing.T) { } func TestIsContradiction_VerbPatterns(t *testing.T) { + t.Parallel() newNode := &storage.Node{ Content: "Use React for the frontend components, prefer this framework", Type: "decision", @@ -129,6 +137,7 @@ func TestIsContradiction_VerbPatterns(t *testing.T) { } func TestDetectContradictionSignals(t *testing.T) { + t.Parallel() signals := detectContradictionSignals( "Use jose instead of jsonwebtoken", "Use jsonwebtoken for JWT validation", @@ -149,6 +158,7 @@ func TestDetectContradictionSignals(t *testing.T) { } func TestDetectContradictionSignals_Adjectives(t *testing.T) { + t.Parallel() signals := detectContradictionSignals( "The API response is fast and correct", "The API response is slow and incorrect", @@ -159,6 +169,7 @@ func TestDetectContradictionSignals_Adjectives(t *testing.T) { } func TestDetectContradictionSignals_NoSignals(t *testing.T) { + t.Parallel() signals := detectContradictionSignals( "Use Docker for deployment", "Use PostgreSQL for the database", @@ -169,6 +180,7 @@ func TestDetectContradictionSignals_NoSignals(t *testing.T) { } func TestHasNegationPattern(t *testing.T) { + t.Parallel() if !hasNegationPattern("prefer TypeScript", "avoid TypeScript") { t.Error("expected negation pattern: prefer vs avoid") } @@ -181,6 +193,7 @@ func TestHasNegationPattern(t *testing.T) { } func TestAnalyzeContradiction(t *testing.T) { + t.Parallel() newNode := &storage.Node{ ID: "new-1", Content: "Use jose library instead of jsonwebtoken for JWT validation", diff --git a/conflict/validity_test.go b/conflict/validity_test.go index a14c602..712de88 100644 --- a/conflict/validity_test.go +++ b/conflict/validity_test.go @@ -14,6 +14,7 @@ import ( // temporal validity window closed (invalid_at set), while the new "supersedes" // edge remains valid. func TestCheckAndResolve_InvalidatesSupersededEdges(t *testing.T) { + t.Parallel() store := storage.NewMockStorage() ctx := context.Background() r := New(store) diff --git a/dedup/window_test.go b/dedup/window_test.go index 91e4084..c94aabe 100644 --- a/dedup/window_test.go +++ b/dedup/window_test.go @@ -6,6 +6,7 @@ import ( ) func TestWindow_BasicDedup(t *testing.T) { + t.Parallel() w := New(5 * time.Minute) if w.IsDuplicate("hello world") { @@ -17,6 +18,7 @@ func TestWindow_BasicDedup(t *testing.T) { } func TestWindow_DifferentContent(t *testing.T) { + t.Parallel() w := New(5 * time.Minute) w.IsDuplicate("content A") @@ -26,6 +28,7 @@ func TestWindow_DifferentContent(t *testing.T) { } func TestWindow_WhitespaceNormalization(t *testing.T) { + t.Parallel() w := New(5 * time.Minute) w.IsDuplicate("hello world") @@ -35,6 +38,7 @@ func TestWindow_WhitespaceNormalization(t *testing.T) { } func TestWindow_Expiry(t *testing.T) { + t.Parallel() w := New(1 * time.Millisecond) w.IsDuplicate("expires fast") @@ -46,6 +50,7 @@ func TestWindow_Expiry(t *testing.T) { } func TestWindow_DefaultDuration(t *testing.T) { + t.Parallel() w := New(0) if w.duration != 5*time.Minute { t.Errorf("expected default 5m, got %v", w.duration) @@ -53,6 +58,7 @@ func TestWindow_DefaultDuration(t *testing.T) { } func TestWindow_ConcurrentAccess(t *testing.T) { + t.Parallel() w := New(5 * time.Minute) done := make(chan bool, 10) diff --git a/embeddings/defaults_test.go b/embeddings/defaults_test.go index a1269e3..ede1d76 100644 --- a/embeddings/defaults_test.go +++ b/embeddings/defaults_test.go @@ -3,6 +3,7 @@ package embeddings import "testing" func TestGetModelDefaults_KnownModel(t *testing.T) { + t.Parallel() d, ok := GetModelDefaults("voyage-code-3") if !ok { t.Fatal("expected voyage-code-3 to be in defaults table") @@ -19,6 +20,7 @@ func TestGetModelDefaults_KnownModel(t *testing.T) { } func TestGetModelDefaults_UnknownModel(t *testing.T) { + t.Parallel() _, ok := GetModelDefaults("nonexistent-model-xyz") if ok { t.Error("expected unknown model to return false") @@ -26,6 +28,7 @@ func TestGetModelDefaults_UnknownModel(t *testing.T) { } func TestGetInputType_AndBatchSize(t *testing.T) { + t.Parallel() // Test input type for asymmetric model idx := GetInputType("text-embedding-004", ModeDocument) if idx != "RETRIEVAL_DOCUMENT" { diff --git a/embeddings/memo_test.go b/embeddings/memo_test.go index 98985be..1c3f100 100644 --- a/embeddings/memo_test.go +++ b/embeddings/memo_test.go @@ -7,6 +7,7 @@ import ( ) func TestEmbeddingMemo_GetPut(t *testing.T) { + t.Parallel() m := NewEmbeddingMemo(10) if _, ok := m.Get("hello"); ok { t.Fatal("expected miss on empty cache") @@ -19,6 +20,7 @@ func TestEmbeddingMemo_GetPut(t *testing.T) { } func TestEmbeddingMemo_LRUEviction(t *testing.T) { + t.Parallel() m := NewEmbeddingMemo(3) m.Put("a", []float32{1}) m.Put("b", []float32{2}) @@ -59,6 +61,7 @@ func (c *countingProvider) EmbedWithMode(ctx context.Context, text string, mode } func TestMemoizedProvider_Embed(t *testing.T) { + t.Parallel() inner := &countingProvider{} p := NewMemoizedProvider(inner, 100) ctx := context.Background() @@ -77,6 +80,7 @@ func TestMemoizedProvider_Embed(t *testing.T) { } func TestMemoizedProvider_EmbedBatch(t *testing.T) { + t.Parallel() inner := &countingProvider{} p := NewMemoizedProvider(inner, 100) ctx := context.Background() @@ -116,6 +120,7 @@ func (p *namedProvider) Name() string { return p.name } // for one model must not serve its vectors to a different model. Since the memo // is namespaced by Name(), each model has its own key space. func TestMemoizedProvider_ModelSwapInvalidates(t *testing.T) { + t.Parallel() ctx := context.Background() old := NewMemoizedProvider(&namedProvider{name: "modelA"}, 100) v1, _ := old.Embed(ctx, "foo") @@ -135,6 +140,7 @@ func TestMemoizedProvider_ModelSwapInvalidates(t *testing.T) { // TestEmbeddingMemo_ModeIsolation pins the #2-supporting behavior: document- and // query-mode vectors for identical text occupy distinct keys. func TestEmbeddingMemo_ModeIsolation(t *testing.T) { + t.Parallel() m := NewEmbeddingMemoNS("model", 100) m.PutMode("q", ModeDocument, []float32{1, 0}) m.PutMode("q", ModeQuery, []float32{0, 1}) @@ -152,6 +158,7 @@ func TestEmbeddingMemo_ModeIsolation(t *testing.T) { // TestMemoizedProvider_EmbedWithModeMemoizes pins that mode-aware calls are now // cached (previously they bypassed the memo entirely). func TestMemoizedProvider_EmbedWithModeMemoizes(t *testing.T) { + t.Parallel() inner := &countingProvider{} p := NewMemoizedProvider(inner, 100) ctx := context.Background() diff --git a/embeddings/ratelimit_test.go b/embeddings/ratelimit_test.go index 3fb478d..547ab39 100644 --- a/embeddings/ratelimit_test.go +++ b/embeddings/ratelimit_test.go @@ -6,6 +6,7 @@ import ( ) func TestExtractRetryDelay_Seconds(t *testing.T) { + t.Parallel() d := ExtractRetryDelay("Rate limit exceeded. Please try again in 1.5s") want := 1500 * time.Millisecond if d != want { @@ -14,6 +15,7 @@ func TestExtractRetryDelay_Seconds(t *testing.T) { } func TestExtractRetryDelay_Milliseconds(t *testing.T) { + t.Parallel() d := ExtractRetryDelay("retry in 500ms before next request") want := 500 * time.Millisecond if d != want { @@ -22,6 +24,7 @@ func TestExtractRetryDelay_Milliseconds(t *testing.T) { } func TestExtractRetryDelay_FullWord(t *testing.T) { + t.Parallel() d := ExtractRetryDelay("Please try again in 2 seconds.") want := 2 * time.Second if d != want { @@ -30,6 +33,7 @@ func TestExtractRetryDelay_FullWord(t *testing.T) { } func TestExtractRetryDelay_NoMatch(t *testing.T) { + t.Parallel() d := ExtractRetryDelay("generic error with no timing info") if d != 0 { t.Errorf("expected 0 for non-matching message, got %v", d) @@ -37,6 +41,7 @@ func TestExtractRetryDelay_NoMatch(t *testing.T) { } func TestPacer_Wait(t *testing.T) { + t.Parallel() p := NewPacer(50 * time.Millisecond) start := time.Now() p.Wait() // first call should not block @@ -48,6 +53,7 @@ func TestPacer_Wait(t *testing.T) { } func TestPacer_SetInterval(t *testing.T) { + t.Parallel() p := NewPacer(1 * time.Hour) // Shrink the interval so the next Wait does not block for an hour p.SetInterval(10 * time.Millisecond) diff --git a/engine/addonly_test.go b/engine/addonly_test.go index c30fe59..89baf0e 100644 --- a/engine/addonly_test.go +++ b/engine/addonly_test.go @@ -40,6 +40,7 @@ func countSupersedesEdges(t *testing.T, e *Engine) (int, float64) { // path: contradictory memories both persist with no supersedes edge and no // confidence drop. With ADD-only off, the existing supersede behavior holds. func TestAddOnlyMode(t *testing.T) { + t.Parallel() // A contradicting pair of conventions: same topic (JWT library), opposite // recommendation. isContradiction fires on the "instead of" signal. const old = "Use jsonwebtoken library for JWT validation in the auth service" diff --git a/engine/bloom_test.go b/engine/bloom_test.go index c4756ee..cd23e62 100644 --- a/engine/bloom_test.go +++ b/engine/bloom_test.go @@ -5,6 +5,7 @@ import ( ) func TestBloomFilter_BasicOps(t *testing.T) { + t.Parallel() bf := NewBloomFilter(1000, 0.01) bf.Add("authentication") @@ -28,6 +29,7 @@ func TestBloomFilter_BasicOps(t *testing.T) { } func TestBloomFilter_MayContainAny(t *testing.T) { + t.Parallel() bf := NewBloomFilter(1000, 0.01) bf.Add("jose") bf.Add("jsonwebtoken") @@ -42,6 +44,7 @@ func TestBloomFilter_MayContainAny(t *testing.T) { } func TestBloomFilter_AddTerms(t *testing.T) { + t.Parallel() bf := NewBloomFilter(1000, 0.01) bf.AddTerms("Use jose library for JWT authentication in auth.ts") @@ -57,6 +60,7 @@ func TestBloomFilter_AddTerms(t *testing.T) { } func TestBloomFilter_FalsePositiveRate(t *testing.T) { + t.Parallel() bf := NewBloomFilter(1000, 0.01) // Add 100 items @@ -71,6 +75,7 @@ func TestBloomFilter_FalsePositiveRate(t *testing.T) { } func TestBloomFilter_EmptyFilter(t *testing.T) { + t.Parallel() bf := NewBloomFilter(100, 0.01) if bf.MayContain("anything") { @@ -82,6 +87,7 @@ func TestBloomFilter_EmptyFilter(t *testing.T) { } func TestTokenize(t *testing.T) { + t.Parallel() tests := []struct { input string want int // minimum number of tokens expected diff --git a/engine/boundary_test.go b/engine/boundary_test.go index 65fff9f..b44cca1 100644 --- a/engine/boundary_test.go +++ b/engine/boundary_test.go @@ -37,6 +37,7 @@ func (f *fakeProvider) Dims() int { return f.dims } func (f *fakeProvider) Name() string { return "fake" } func TestDetectBoundary_Lexical(t *testing.T) { + t.Parallel() det := NewBoundaryDetector(nil, DefaultBoundaryConfig()) tests := []struct { name string @@ -81,6 +82,7 @@ func TestDetectBoundary_Lexical(t *testing.T) { } func TestDetectBoundary_Embedding(t *testing.T) { + t.Parallel() // Two orthogonal-ish clusters: A vectors near (1,0,...), B near (0,1,...). prov := &fakeProvider{dims: 4, vecs: map[string][]float32{ "a1": {1, 0, 0, 0}, @@ -98,6 +100,7 @@ func TestDetectBoundary_Embedding(t *testing.T) { } func TestTracker_Lexical(t *testing.T) { + t.Parallel() tr := NewTracker(NewBoundaryDetector(nil, DefaultBoundaryConfig())) // Continuous same-topic stream: no boundaries after the baseline. @@ -119,6 +122,7 @@ func TestTracker_Lexical(t *testing.T) { } func TestTracker_Embedding(t *testing.T) { + t.Parallel() prov := &fakeProvider{dims: 4, vecs: map[string][]float32{ "a1": {1, 0, 0, 0}, "a2": {0.98, 0.05, 0, 0}, @@ -138,6 +142,7 @@ func TestTracker_Embedding(t *testing.T) { } func TestTracker_ResetAndEmptyInput(t *testing.T) { + t.Parallel() tr := NewTracker(NewBoundaryDetector(nil, DefaultBoundaryConfig())) if tr.Observe("") { t.Error("empty content should never be a boundary") diff --git a/engine/branch_test.go b/engine/branch_test.go index d1820e1..d8d44f6 100644 --- a/engine/branch_test.go +++ b/engine/branch_test.go @@ -10,6 +10,7 @@ import ( ) func TestBranch(t *testing.T) { + t.Parallel() store, err := storage.NewStore(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatal(err) @@ -70,6 +71,7 @@ func TestBranch(t *testing.T) { } func TestBranch_EmptyContent(t *testing.T) { + t.Parallel() store, err := storage.NewStore(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatal(err) @@ -98,6 +100,7 @@ func TestBranch_EmptyContent(t *testing.T) { } func TestBranch_ParentNotFound(t *testing.T) { + t.Parallel() store, err := storage.NewStore(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatal(err) diff --git a/engine/cognitive/boundary_test.go b/engine/cognitive/boundary_test.go index 984763c..5c2c4da 100644 --- a/engine/cognitive/boundary_test.go +++ b/engine/cognitive/boundary_test.go @@ -5,6 +5,7 @@ import ( ) func TestBoundaryDetector_DetectBoundaries(t *testing.T) { + t.Parallel() bd := NewBoundaryDetector(DefaultBoundaryConfig()) // Messages with a clear topic shift @@ -30,6 +31,7 @@ func TestBoundaryDetector_DetectBoundaries(t *testing.T) { } func TestBoundaryDetector_TooFewMessages(t *testing.T) { + t.Parallel() cfg := DefaultBoundaryConfig() cfg.MinMessages = 10 bd := NewBoundaryDetector(cfg) @@ -42,6 +44,7 @@ func TestBoundaryDetector_TooFewMessages(t *testing.T) { } func TestBoundaryDetector_Disabled(t *testing.T) { + t.Parallel() cfg := DefaultBoundaryConfig() cfg.Enabled = false bd := NewBoundaryDetector(cfg) @@ -54,6 +57,7 @@ func TestBoundaryDetector_Disabled(t *testing.T) { } func TestBoundaryDetector_SegmentByBoundaries(t *testing.T) { + t.Parallel() bd := NewBoundaryDetector(DefaultBoundaryConfig()) messages := []string{ @@ -80,6 +84,7 @@ func TestBoundaryDetector_SegmentByBoundaries(t *testing.T) { } func TestComputeShift_SameText(t *testing.T) { + t.Parallel() bd := NewBoundaryDetector(DefaultBoundaryConfig()) shift := bd.computeShift("hello world test", "hello world test") if shift != 0 { @@ -88,6 +93,7 @@ func TestComputeShift_SameText(t *testing.T) { } func TestComputeShift_DifferentText(t *testing.T) { + t.Parallel() bd := NewBoundaryDetector(DefaultBoundaryConfig()) shift := bd.computeShift("database schema design table", "react component frontend framework") if shift < 0.3 { @@ -96,6 +102,7 @@ func TestComputeShift_DifferentText(t *testing.T) { } func TestExtractSignificantTerms(t *testing.T) { + t.Parallel() terms := extractSignificantTerms("The database schema needs indexing") if len(terms) == 0 { t.Error("expected some terms") @@ -111,6 +118,7 @@ func TestExtractSignificantTerms(t *testing.T) { } func TestExtractBoundaryTopic(t *testing.T) { + t.Parallel() topic := extractBoundaryTopic("database schema design with tables and indexes") if topic == "general" { t.Error("expected non-general topic") @@ -118,6 +126,7 @@ func TestExtractBoundaryTopic(t *testing.T) { } func TestMergeWindow(t *testing.T) { + t.Parallel() merged := mergeWindow([]string{"hello", "world"}) if merged != "hello world" { t.Errorf("expected 'hello world', got %q", merged) diff --git a/engine/cognitive/cognitive_engines_test.go b/engine/cognitive/cognitive_engines_test.go index 904100c..5b145ec 100644 --- a/engine/cognitive/cognitive_engines_test.go +++ b/engine/cognitive/cognitive_engines_test.go @@ -10,6 +10,7 @@ import ( // --------------------------------------------------------------------------- func TestZeigarnikEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultZeigarnikConfig() if !cfg.Enabled { @@ -123,6 +124,7 @@ func TestZeigarnikEngine(t *testing.T) { } func TestDetectOpenLoop(t *testing.T) { + t.Parallel() tests := []struct { name string text string @@ -152,6 +154,7 @@ func TestDetectOpenLoop(t *testing.T) { } func TestDetectResolution(t *testing.T) { + t.Parallel() tests := []struct { text string want bool @@ -174,6 +177,7 @@ func TestDetectResolution(t *testing.T) { // --------------------------------------------------------------------------- func TestProspectiveEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultProspectiveConfig() if !cfg.Enabled { @@ -335,6 +339,7 @@ func TestProspectiveEngine(t *testing.T) { // --------------------------------------------------------------------------- func TestEpistemicEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultEpistemicConfig() if !cfg.Enabled { @@ -502,6 +507,7 @@ func TestEpistemicEngine(t *testing.T) { // --------------------------------------------------------------------------- func TestSomaticEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultSomaticConfig() if !cfg.Enabled { @@ -627,6 +633,7 @@ func TestSomaticEngine(t *testing.T) { // --------------------------------------------------------------------------- func TestCuriosityEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultCuriosityConfig() if !cfg.Enabled { @@ -787,6 +794,7 @@ func TestCuriosityEngine(t *testing.T) { // --------------------------------------------------------------------------- func TestReconsolidationEngine(t *testing.T) { + t.Parallel() t.Run("DefaultConfig", func(t *testing.T) { cfg := DefaultReconsolidationConfig() if !cfg.Enabled { diff --git a/engine/cognitive/procedural_test.go b/engine/cognitive/procedural_test.go index 830dd7a..5bcc469 100644 --- a/engine/cognitive/procedural_test.go +++ b/engine/cognitive/procedural_test.go @@ -5,6 +5,7 @@ import ( ) func TestProceduralEngine_ObserveSequence(t *testing.T) { + t.Parallel() e := NewProceduralEngine(DefaultProceduralConfig()) // Observe a sequence @@ -27,6 +28,7 @@ func TestProceduralEngine_ObserveSequence(t *testing.T) { } func TestProceduralEngine_ObserveSequence_TooShort(t *testing.T) { + t.Parallel() cfg := DefaultProceduralConfig() cfg.SequenceMinLen = 3 e := NewProceduralEngine(cfg) @@ -38,6 +40,7 @@ func TestProceduralEngine_ObserveSequence_TooShort(t *testing.T) { } func TestProceduralEngine_SuggestSteps(t *testing.T) { + t.Parallel() e := NewProceduralEngine(DefaultProceduralConfig()) // Build up a pattern @@ -56,6 +59,7 @@ func TestProceduralEngine_SuggestSteps(t *testing.T) { } func TestProceduralEngine_SuggestSteps_NoMatch(t *testing.T) { + t.Parallel() e := NewProceduralEngine(DefaultProceduralConfig()) suggestions := e.SuggestSteps([]string{"NonExistent"}, 3) @@ -65,6 +69,7 @@ func TestProceduralEngine_SuggestSteps_NoMatch(t *testing.T) { } func TestProceduralEngine_GetPatterns(t *testing.T) { + t.Parallel() e := NewProceduralEngine(DefaultProceduralConfig()) e.ObserveSequence([]string{"A", "B", "C"}, "test1", true) @@ -77,6 +82,7 @@ func TestProceduralEngine_GetPatterns(t *testing.T) { } func TestProceduralEngine_Disabled(t *testing.T) { + t.Parallel() cfg := DefaultProceduralConfig() cfg.Enabled = false e := NewProceduralEngine(cfg) @@ -88,6 +94,7 @@ func TestProceduralEngine_Disabled(t *testing.T) { } func TestProceduralEngine_Cleanup(t *testing.T) { + t.Parallel() cfg := DefaultProceduralConfig() cfg.MinFrequency = 100 // very high threshold e := NewProceduralEngine(cfg) @@ -100,6 +107,7 @@ func TestProceduralEngine_Cleanup(t *testing.T) { } func TestLongestCommonSubseq(t *testing.T) { + t.Parallel() tests := []struct { a, b []string want int @@ -118,6 +126,7 @@ func TestLongestCommonSubseq(t *testing.T) { } func TestSequenceSimilarity(t *testing.T) { + t.Parallel() sim := sequenceSimilarity([]string{"A", "B", "C"}, []string{"A", "B", "C"}) if sim != 1.0 { t.Errorf("expected 1.0, got %f", sim) @@ -130,6 +139,7 @@ func TestSequenceSimilarity(t *testing.T) { } func TestPrefixMatch(t *testing.T) { + t.Parallel() seq := []string{"Read", "Edit", "Bash", "Read"} idx := prefixMatch(seq, []string{"Edit", "Bash"}) if idx != 3 { @@ -148,6 +158,7 @@ func TestPrefixMatch(t *testing.T) { } func TestProceduralEngine_SuccessRate(t *testing.T) { + t.Parallel() e := NewProceduralEngine(DefaultProceduralConfig()) // Record successes diff --git a/engine/community_test.go b/engine/community_test.go index 74ff462..72da8d1 100644 --- a/engine/community_test.go +++ b/engine/community_test.go @@ -8,6 +8,7 @@ import ( ) func TestCommunityDetector_Empty(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -22,6 +23,7 @@ func TestCommunityDetector_Empty(t *testing.T) { } func TestCommunityDetector_ConnectedNodes(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -52,6 +54,7 @@ func TestCommunityDetector_ConnectedNodes(t *testing.T) { } func TestCommunityDetector_Summarize(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -72,6 +75,7 @@ func TestCommunityDetector_Summarize(t *testing.T) { } func TestFindCommunityForQuery(t *testing.T) { + t.Parallel() cd := &CommunityDetector{} communities := []Community{ {ID: 1, Summary: "Authentication using jose JWT RS256", Size: 5}, diff --git a/engine/consolidation_test.go b/engine/consolidation_test.go index 8ac070f..10e312d 100644 --- a/engine/consolidation_test.go +++ b/engine/consolidation_test.go @@ -38,6 +38,7 @@ func waitForCycles(t *testing.T, eng *Engine, min int64, timeout time.Duration) } func TestStartConsolidationRunsAndStops(t *testing.T) { + t.Parallel() eng := newConsolidationEngine(t) ctx := context.Background() @@ -74,6 +75,7 @@ func TestStartConsolidationRunsAndStops(t *testing.T) { } func TestStartConsolidationStopsOnContextCancel(t *testing.T) { + t.Parallel() eng := newConsolidationEngine(t) ctx, cancel := context.WithCancel(context.Background()) @@ -108,6 +110,7 @@ func TestStartConsolidationStopsOnContextCancel(t *testing.T) { } func TestStartConsolidationDoubleStartIsNoop(t *testing.T) { + t.Parallel() eng := newConsolidationEngine(t) ctx := context.Background() @@ -121,6 +124,7 @@ func TestStartConsolidationDoubleStartIsNoop(t *testing.T) { } func TestStopConsolidationWithoutStartIsSafe(t *testing.T) { + t.Parallel() eng := newConsolidationEngine(t) // Must not panic or block. eng.StopConsolidation() diff --git a/engine/context_pack_test.go b/engine/context_pack_test.go index 7bd369a..7aa9f79 100644 --- a/engine/context_pack_test.go +++ b/engine/context_pack_test.go @@ -19,6 +19,7 @@ func makeNode(id, content, nodeType string, confidence float64, accessCount int, } func TestContextPackerEmpty(t *testing.T) { + t.Parallel() cp := NewContextPacker(2000) result := cp.Pack(nil) if result.Content != "" { @@ -30,6 +31,7 @@ func TestContextPackerEmpty(t *testing.T) { } func TestContextPackerBudgetEnforcement(t *testing.T) { + t.Parallel() // Very small budget should limit output cp := NewContextPacker(20) nodes := []*storage.Node{ @@ -44,6 +46,7 @@ func TestContextPackerBudgetEnforcement(t *testing.T) { } func TestContextPackerDefaultBudget(t *testing.T) { + t.Parallel() cp := NewContextPacker(0) if cp.budget != 2000 { t.Errorf("expected default budget 2000, got %d", cp.budget) @@ -55,6 +58,7 @@ func TestContextPackerDefaultBudget(t *testing.T) { } func TestContextPackerTypeQuotas(t *testing.T) { + t.Parallel() cp := NewContextPacker(5000) // Create 12 conventions (quota is 8) nodes := make([]*storage.Node, 12) @@ -72,6 +76,7 @@ func TestContextPackerTypeQuotas(t *testing.T) { } func TestContextPackerPinnedFirst(t *testing.T) { + t.Parallel() cp := NewContextPacker(5000) nodes := []*storage.Node{ makeNode("np", "regular node with enough content", "convention", 0.9, 10, false), @@ -88,6 +93,7 @@ func TestContextPackerPinnedFirst(t *testing.T) { } func TestContextPackerDeduplication(t *testing.T) { + t.Parallel() cp := NewContextPacker(5000) // Two nodes with identical first 50 chars nodes := []*storage.Node{ @@ -101,6 +107,7 @@ func TestContextPackerDeduplication(t *testing.T) { } func TestContextPackerLongContentTruncation(t *testing.T) { + t.Parallel() cp := NewContextPacker(5000) longContent := strings.Repeat("x", 200) nodes := []*storage.Node{ @@ -116,6 +123,7 @@ func TestContextPackerLongContentTruncation(t *testing.T) { } func TestContextPackerPriority(t *testing.T) { + t.Parallel() cp := NewContextPacker(5000) // Convention gets +1.0 priority boost over "spec" (+0.6) conv := makeNode("conv", "convention content for priority test", "convention", 0.5, 0, false) diff --git a/engine/engine_test.go b/engine/engine_test.go index 85ba503..6ac3c5c 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -15,16 +15,19 @@ import ( // readability. This file keeps the engine behavior tests. func TestMockStorageCompiles(t *testing.T) { + t.Parallel() var _ storage.Storage = newMockStorage() } // TestMockGraphCompiles verifies mockGraph implements graph.Graph. func TestMockGraphCompiles(t *testing.T) { + t.Parallel() var _ graph.Graph = newMockGraph(newMockStorage()) } // TestEngineWithMocks verifies engine.New accepts mock implementations. func TestEngineWithMocks(t *testing.T) { + t.Parallel() eng := newTestEngine() if eng == nil { t.Fatal("expected non-nil engine") @@ -39,6 +42,7 @@ func TestEngineWithMocks(t *testing.T) { // TestRememberAndRecall creates a node and recalls it. func TestRememberAndRecall(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.Remember(context.Background(), RememberInput{ @@ -78,6 +82,7 @@ func TestRememberAndRecall(t *testing.T) { // TestRecallFilters verifies type/tier/project filtering. func TestRecallFilters(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{Type: "convention", Content: "conv1", Project: "p1"}) @@ -97,6 +102,7 @@ func TestRecallFilters(t *testing.T) { // TestContext verifies hot-tier + active tasks retrieval. func TestContext(t *testing.T) { + t.Parallel() eng := newTestEngine() // hot tier node @@ -122,6 +128,7 @@ func TestContext(t *testing.T) { // TestForget archives a node. func TestForget(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.Remember(context.Background(), RememberInput{Type: "decision", Content: "drop feature X", Project: "p1"}) @@ -144,6 +151,7 @@ func TestForget(t *testing.T) { // TestStatus verifies node/edge/session counting. func TestStatus(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{Type: "convention", Content: "c1", Project: "p1"}) @@ -164,6 +172,7 @@ func TestStatus(t *testing.T) { // TestFeedback verifies approve/edit/discard actions. func TestFeedback(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.Remember(context.Background(), RememberInput{Type: "bug", Content: "old bug desc", Project: "p1"}) @@ -201,6 +210,7 @@ func TestFeedback(t *testing.T) { // TestRollback restores a node to a previous version. func TestRollback(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.Remember(context.Background(), RememberInput{Type: "decision", Content: "v1 content", Project: "p1"}) @@ -226,6 +236,7 @@ func TestRollback(t *testing.T) { // TestPendingNodes returns low-confidence nodes. func TestPendingNodes(t *testing.T) { + t.Parallel() eng := newTestEngine() node, _ := eng.Remember(context.Background(), RememberInput{Type: "convention", Content: "low confidence", Project: "p1"}) @@ -252,6 +263,7 @@ func TestPendingNodes(t *testing.T) { // TestEmptyDatabase verifies operations on empty store return empty results, not errors. func TestEmptyDatabase(t *testing.T) { + t.Parallel() eng := newTestEngine() res, err := eng.Recall(context.Background(), RecallOpts{Query: "anything", Project: "empty"}) @@ -281,6 +293,7 @@ func TestEmptyDatabase(t *testing.T) { // TestNonexistentNode verifies Forget, GetNode, Link with bad IDs return errors. func TestNonexistentNode(t *testing.T) { + t.Parallel() eng := newTestEngine() if err := eng.Forget(context.Background(), "nonexistent-id"); err == nil { @@ -295,6 +308,7 @@ func TestNonexistentNode(t *testing.T) { // TestConcurrentRemember verifies multiple goroutines calling Remember is safe. func TestConcurrentRemember(t *testing.T) { + t.Parallel() eng := newTestEngine() var wg sync.WaitGroup @@ -325,6 +339,7 @@ func TestConcurrentRemember(t *testing.T) { // TestConcurrentReadWrite verifies Recall and Remember concurrently. func TestConcurrentReadWrite(t *testing.T) { + t.Parallel() eng := newTestEngine() // Seed some data @@ -358,6 +373,7 @@ func TestConcurrentReadWrite(t *testing.T) { // TestRememberEmptyContent verifies Remember with empty content is handled. func TestRememberEmptyContent(t *testing.T) { + t.Parallel() eng := newTestEngine() cases := []struct { @@ -394,6 +410,7 @@ func TestRememberEmptyContent(t *testing.T) { // TestSessionFlow verifies StartSession and CompressSession. func TestSessionFlow(t *testing.T) { + t.Parallel() eng := newTestEngine() sessID, err := eng.StartSession(context.Background(), "p1", "agent-a") diff --git a/engine/entity_boost_test.go b/engine/entity_boost_test.go index 2d455b4..4cfb12c 100644 --- a/engine/entity_boost_test.go +++ b/engine/entity_boost_test.go @@ -8,6 +8,7 @@ import ( ) func TestEntityIndex_IndexAndBoost(t *testing.T) { + t.Parallel() idx := NewEntityIndex() node1 := &storage.Node{ID: "n1", Content: "Use `jose` library for JWT in auth.ts"} @@ -39,6 +40,7 @@ func TestEntityIndex_IndexAndBoost(t *testing.T) { } func TestEntityIndex_RemoveNode(t *testing.T) { + t.Parallel() idx := NewEntityIndex() node := &storage.Node{ID: "n1", Content: "Use jose for JWT tokens"} @@ -58,6 +60,7 @@ func TestEntityIndex_RemoveNode(t *testing.T) { } func TestEntityIndex_EmptyContent(t *testing.T) { + t.Parallel() idx := NewEntityIndex() idx.IndexNode(nil) idx.IndexNode(&storage.Node{ID: "x", Content: ""}) @@ -67,6 +70,7 @@ func TestEntityIndex_EmptyContent(t *testing.T) { } func TestEntityIndex_LoadFromStore(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() diff --git a/engine/events_test.go b/engine/events_test.go index 82cb194..0d15d44 100644 --- a/engine/events_test.go +++ b/engine/events_test.go @@ -25,6 +25,7 @@ func newEventTestEngine(t *testing.T) (*Engine, func()) { } func TestMemoryEventBus(t *testing.T) { + t.Parallel() tests := []struct { name string wantKind MemoryEventKind @@ -116,6 +117,7 @@ func TestMemoryEventBus(t *testing.T) { } func TestSubscribeUnsubscribe(t *testing.T) { + t.Parallel() eng, cleanup := newEventTestEngine(t) defer cleanup() diff --git a/engine/feedback_test.go b/engine/feedback_test.go index 8d3ada9..6214f09 100644 --- a/engine/feedback_test.go +++ b/engine/feedback_test.go @@ -30,6 +30,7 @@ func seedNode(t *testing.T, eng *Engine, id, content string, confidence float64) // --- Feedback --- func TestFeedbackApprove(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "hello world", 0.3) @@ -44,6 +45,7 @@ func TestFeedbackApprove(t *testing.T) { } func TestFeedbackEdit(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "old content", 0.5) @@ -64,6 +66,7 @@ func TestFeedbackEdit(t *testing.T) { } func TestFeedbackEditEmptyContent(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "hello", 0.5) @@ -74,6 +77,7 @@ func TestFeedbackEditEmptyContent(t *testing.T) { } func TestFeedbackDiscard(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "to discard", 0.5) @@ -88,6 +92,7 @@ func TestFeedbackDiscard(t *testing.T) { } func TestFeedbackUnknownAction(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "hello", 0.5) @@ -98,6 +103,7 @@ func TestFeedbackUnknownAction(t *testing.T) { } func TestFeedbackContextCancelled(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -109,6 +115,7 @@ func TestFeedbackContextCancelled(t *testing.T) { } func TestFeedbackNodeNotFound(t *testing.T) { + t.Parallel() eng := newTestEngine() err := eng.Feedback(context.Background(), "nonexistent", FeedbackApprove, "") @@ -120,6 +127,7 @@ func TestFeedbackNodeNotFound(t *testing.T) { // --- Rollback --- func TestRollbackValidVersion(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "current content", 0.8) @@ -139,6 +147,7 @@ func TestRollbackValidVersion(t *testing.T) { } func TestRollbackVersionNotFound(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "n1", "current content", 0.8) @@ -149,6 +158,7 @@ func TestRollbackVersionNotFound(t *testing.T) { } func TestRollbackContextCancelled(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -162,6 +172,7 @@ func TestRollbackContextCancelled(t *testing.T) { // --- PendingNodes --- func TestPendingNodesFilters(t *testing.T) { + t.Parallel() eng := newTestEngine() seedNode(t, eng, "high", "high confidence", 0.9) seedNode(t, eng, "low", "low confidence", 0.2) @@ -178,6 +189,7 @@ func TestPendingNodesFilters(t *testing.T) { } func TestPendingNodesEmptyProject(t *testing.T) { + t.Parallel() eng := newTestEngine() pending, err := eng.PendingNodes(context.Background(), "empty", 0.5) @@ -190,6 +202,7 @@ func TestPendingNodesEmptyProject(t *testing.T) { } func TestPendingNodesCap(t *testing.T) { + t.Parallel() eng := newTestEngine() for i := 0; i < 1001; i++ { n := &storage.Node{ @@ -216,6 +229,7 @@ func TestPendingNodesCap(t *testing.T) { } func TestPendingNodesContextCancelled(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx, cancel := context.WithCancel(context.Background()) cancel() diff --git a/engine/fused_recall_test.go b/engine/fused_recall_test.go index 9745101..588d926 100644 --- a/engine/fused_recall_test.go +++ b/engine/fused_recall_test.go @@ -9,6 +9,7 @@ import ( // TestFusedRecallBasic creates nodes and verifies FusedRecall returns them // ranked by the combination of BM25, graph, and recency signals. func TestFusedRecallBasic(t *testing.T) { + t.Parallel() eng := newTestEngine() // Create several nodes with related content @@ -71,6 +72,7 @@ func TestFusedRecallBasic(t *testing.T) { // TestFusedRecallEmpty verifies FusedRecall on an empty store returns empty results. func TestFusedRecallEmpty(t *testing.T) { + t.Parallel() eng := newTestEngine() result, err := eng.FusedRecall(context.Background(), RecallOpts{ @@ -87,6 +89,7 @@ func TestFusedRecallEmpty(t *testing.T) { // TestFusedRecallTypeFilter verifies type filtering works. func TestFusedRecallTypeFilter(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -114,6 +117,7 @@ func TestFusedRecallTypeFilter(t *testing.T) { // TestFusedRecallLimit verifies the limit option is respected. func TestFusedRecallLimit(t *testing.T) { + t.Parallel() eng := newTestEngine() for i := 0; i < 20; i++ { @@ -139,6 +143,7 @@ func TestFusedRecallLimit(t *testing.T) { // TestFusedRecallBudget verifies the token budget is respected. func TestFusedRecallBudget(t *testing.T) { + t.Parallel() eng := newTestEngine() for i := 0; i < 10; i++ { @@ -167,6 +172,7 @@ func TestFusedRecallBudget(t *testing.T) { // TestFusedRecallSkipsArchived verifies that archived nodes (confidence=0) are excluded. func TestFusedRecallSkipsArchived(t *testing.T) { + t.Parallel() eng := newTestEngine() node, _ := eng.Remember(context.Background(), RememberInput{ @@ -194,6 +200,7 @@ func TestFusedRecallSkipsArchived(t *testing.T) { // TestFusedRecallCancelledContext verifies context cancellation is respected. func TestFusedRecallCancelledContext(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx, cancel := context.WithCancel(context.Background()) @@ -207,6 +214,7 @@ func TestFusedRecallCancelledContext(t *testing.T) { // TestFusedRecallReturnsEdges verifies that edges between result nodes are returned. func TestFusedRecallReturnsEdges(t *testing.T) { + t.Parallel() eng := newTestEngine() n1, _ := eng.Remember(context.Background(), RememberInput{ @@ -242,6 +250,7 @@ func TestFusedRecallReturnsEdges(t *testing.T) { // TestFusedRecallRecencySignal verifies that recently accessed nodes get boosted. func TestFusedRecallRecencySignal(t *testing.T) { + t.Parallel() eng := newTestEngine() // Create two nodes with similar content but different recency @@ -281,6 +290,7 @@ func TestFusedRecallRecencySignal(t *testing.T) { // TestFusedRRFScore verifies the RRF scoring function directly. func TestFusedRRFScore(t *testing.T) { + t.Parallel() // Item appearing in all three lists at rank 1 allRank1 := fusedRRFScore(1, 1, 1) // Item appearing in only one list at rank 1 diff --git a/engine/hierarchy_test.go b/engine/hierarchy_test.go index a72be0c..6c741d8 100644 --- a/engine/hierarchy_test.go +++ b/engine/hierarchy_test.go @@ -9,6 +9,7 @@ import ( ) func TestHierarchicalMemory_Build(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -36,6 +37,7 @@ func TestHierarchicalMemory_Build(t *testing.T) { } func TestHierarchicalMemory_RetrieveAdaptive(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -68,6 +70,7 @@ func TestHierarchicalMemory_RetrieveAdaptive(t *testing.T) { } func TestHierarchicalMemory_FormatLevel(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() diff --git a/engine/hnsw_test.go b/engine/hnsw_test.go index 4c639ff..9a1bf18 100644 --- a/engine/hnsw_test.go +++ b/engine/hnsw_test.go @@ -6,6 +6,7 @@ import ( ) func TestHNSW_InsertAndSearch(t *testing.T) { + t.Parallel() h := NewHNSW(4) // 4-dimensional for testing // Insert vectors @@ -36,6 +37,7 @@ func TestHNSW_InsertAndSearch(t *testing.T) { } func TestHNSW_SearchEmpty(t *testing.T) { + t.Parallel() h := NewHNSW(4) ids, dists := h.Search([]float32{1, 0, 0, 0}, 5) if ids != nil || dists != nil { @@ -44,6 +46,7 @@ func TestHNSW_SearchEmpty(t *testing.T) { } func TestHNSW_DuplicateInsert(t *testing.T) { + t.Parallel() h := NewHNSW(4) h.Insert("x", []float32{1, 0, 0, 0}) h.Insert("x", []float32{0, 1, 0, 0}) // duplicate ID @@ -53,6 +56,7 @@ func TestHNSW_DuplicateInsert(t *testing.T) { } func TestHNSW_Remove(t *testing.T) { + t.Parallel() h := NewHNSW(4) h.Insert("a", []float32{1, 0, 0, 0}) h.Insert("b", []float32{0, 1, 0, 0}) @@ -67,6 +71,7 @@ func TestHNSW_Remove(t *testing.T) { } func TestHNSW_LargeIndex(t *testing.T) { + t.Parallel() h := NewHNSW(32) dim := 32 @@ -101,6 +106,7 @@ func TestHNSW_LargeIndex(t *testing.T) { } func TestHNSW_WrongDimension(t *testing.T) { + t.Parallel() h := NewHNSW(4) h.Insert("a", []float32{1, 0, 0}) // wrong dim, should be ignored if h.Size() != 0 { diff --git a/engine/integrity_test.go b/engine/integrity_test.go index 0f56e04..7b99e91 100644 --- a/engine/integrity_test.go +++ b/engine/integrity_test.go @@ -9,6 +9,7 @@ import ( ) func TestMemoryIntegrity_SignAndVerify(t *testing.T) { + t.Parallel() dir := t.TempDir() mi, err := NewMemoryIntegrity(dir) if err != nil { @@ -47,6 +48,7 @@ func TestMemoryIntegrity_SignAndVerify(t *testing.T) { } func TestMemoryIntegrity_VerifyBatch(t *testing.T) { + t.Parallel() dir := t.TempDir() mi, err := NewMemoryIntegrity(dir) if err != nil { @@ -79,6 +81,7 @@ func TestMemoryIntegrity_VerifyBatch(t *testing.T) { } func TestMemoryIntegrity_KeyPersistence(t *testing.T) { + t.Parallel() dir := t.TempDir() // First instance generates key @@ -108,6 +111,7 @@ func TestMemoryIntegrity_KeyPersistence(t *testing.T) { } func TestMemoryIntegrity_TamperDetectionWithStore(t *testing.T) { + t.Parallel() // This test verifies the full tamper detection flow: // 1. Create a node → signature is stored // 2. Modify content directly (simulating SQLite tampering) diff --git a/engine/llm_consolidation_test.go b/engine/llm_consolidation_test.go index 3b129aa..ecfa8db 100644 --- a/engine/llm_consolidation_test.go +++ b/engine/llm_consolidation_test.go @@ -47,6 +47,7 @@ func (m *mockConsolidationLLM) Summarize(ctx context.Context, nodes []*storage.N // --- Tests --- func TestLevenshtein(t *testing.T) { + t.Parallel() tests := []struct { a, b string want int @@ -67,6 +68,7 @@ func TestLevenshtein(t *testing.T) { } func TestTokenJaccard(t *testing.T) { + t.Parallel() tests := []struct { a, b string min float64 @@ -86,6 +88,7 @@ func TestTokenJaccard(t *testing.T) { } func TestExtractKeywords(t *testing.T) { + t.Parallel() kw := extractKeywords("The database connection pool configuration settings") if kw["database"] != true { t.Error("expected 'database' in keywords") @@ -99,6 +102,7 @@ func TestExtractKeywords(t *testing.T) { } func TestFindCandidateClusters_EmptyProject(t *testing.T) { + t.Parallel() store := newMockStorage() llm := &mockConsolidationLLM{} cfg := DefaultLLMConsolidationConfig() @@ -114,6 +118,7 @@ func TestFindCandidateClusters_EmptyProject(t *testing.T) { } func TestFindCandidateClusters_Disabled(t *testing.T) { + t.Parallel() store := newMockStorage() llm := &mockConsolidationLLM{} cfg := DefaultLLMConsolidationConfig() @@ -130,6 +135,7 @@ func TestFindCandidateClusters_Disabled(t *testing.T) { } func TestFindCandidateClusters_SimilarNodes(t *testing.T) { + t.Parallel() store := newMockStorage() store.nodes["n1"] = &storage.Node{ ID: "n1", @@ -179,6 +185,7 @@ func TestFindCandidateClusters_SimilarNodes(t *testing.T) { } func TestConsolidate_DryRun(t *testing.T) { + t.Parallel() store := newMockStorage() store.nodes["n1"] = &storage.Node{ ID: "n1", @@ -218,6 +225,7 @@ func TestConsolidate_DryRun(t *testing.T) { } func TestConsolidate_AppliesPlan(t *testing.T) { + t.Parallel() store := newMockStorage() store.nodes["n1"] = &storage.Node{ ID: "n1", @@ -253,6 +261,7 @@ func TestConsolidate_AppliesPlan(t *testing.T) { } func TestConsolidate_SkipsOnLLMError(t *testing.T) { + t.Parallel() store := newMockStorage() store.nodes["n1"] = &storage.Node{ ID: "n1", @@ -291,6 +300,7 @@ func TestConsolidate_SkipsOnLLMError(t *testing.T) { } func TestConsolidate_SkipsNilPlan(t *testing.T) { + t.Parallel() store := newMockStorage() store.nodes["n1"] = &storage.Node{ ID: "n1", @@ -329,6 +339,7 @@ func TestConsolidate_SkipsNilPlan(t *testing.T) { } func TestTokenJaccard_TokenOverlap(t *testing.T) { + t.Parallel() got := tokenJaccard("go error handling", "go error style") if got < 0.49 || got > 0.51 { t.Errorf("tokenJaccard = %f, want ~0.5", got) @@ -336,6 +347,7 @@ func TestTokenJaccard_TokenOverlap(t *testing.T) { } func TestDefaultLLMConsolidationConfig(t *testing.T) { + t.Parallel() cfg := DefaultLLMConsolidationConfig() if !cfg.Enabled { t.Error("expected Enabled=true") diff --git a/engine/llm_entities_test.go b/engine/llm_entities_test.go index e6fc0f2..dfb887d 100644 --- a/engine/llm_entities_test.go +++ b/engine/llm_entities_test.go @@ -39,6 +39,7 @@ func countEntity(ents []Entity, normName, typ string) int { } func TestExtractEntitiesWithLLM_NilExtractorFallsBackToRegex(t *testing.T) { + t.Parallel() content := "Edit server.go to fix the bug" got := ExtractEntitiesWithLLM(context.Background(), content, nil) want := ExtractEntities(content) @@ -51,6 +52,7 @@ func TestExtractEntitiesWithLLM_NilExtractorFallsBackToRegex(t *testing.T) { } func TestExtractEntitiesWithLLM_Merge(t *testing.T) { + t.Parallel() content := "Edit server.go to fix the bug" tests := []struct { @@ -154,6 +156,7 @@ func TestExtractEntitiesWithLLM_Merge(t *testing.T) { } func TestMergeEntities(t *testing.T) { + t.Parallel() primary := []Entity{ {Name: "auth.go", Type: "file"}, {Name: "Postgres", Type: "technology"}, diff --git a/engine/lsh_test.go b/engine/lsh_test.go index a618de6..0cdf343 100644 --- a/engine/lsh_test.go +++ b/engine/lsh_test.go @@ -7,6 +7,7 @@ import ( ) func TestMinHashLSH_NearDuplicateDetection(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) // Insert documents with known similarities. @@ -35,6 +36,7 @@ func TestMinHashLSH_NearDuplicateDetection(t *testing.T) { } func TestMinHashLSH_IdenticalDocuments(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) terms := map[string]bool{"hello": true, "world": true, "test": true} @@ -48,6 +50,7 @@ func TestMinHashLSH_IdenticalDocuments(t *testing.T) { } func TestMinHashLSH_EmptyTerms(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) empty := map[string]bool{} @@ -62,6 +65,7 @@ func TestMinHashLSH_EmptyTerms(t *testing.T) { } func TestMinHashLSH_Size(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) for i := 0; i < 100; i++ { @@ -75,6 +79,7 @@ func TestMinHashLSH_Size(t *testing.T) { } func TestMinHashLSH_ConcurrentSafety(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) var wg sync.WaitGroup @@ -106,6 +111,7 @@ func TestMinHashLSH_ConcurrentSafety(t *testing.T) { } func TestMinHashLSH_NoCrossTypeLeakage(t *testing.T) { + t.Parallel() // The sparsify code creates separate LSH per type. // This test verifies that the LSH itself does not filter by type // (type filtering happens in mergeNearDuplicates, not in LSH). @@ -122,6 +128,7 @@ func TestMinHashLSH_NoCrossTypeLeakage(t *testing.T) { } func TestMinHashLSH_HighSimilarityDetection(t *testing.T) { + t.Parallel() lsh := NewMinHashLSH(0.85) // Generate 20 near-duplicate documents (Jaccard > 0.85 with base). diff --git a/engine/memory_file_test.go b/engine/memory_file_test.go index b06ceaf..8ab73c8 100644 --- a/engine/memory_file_test.go +++ b/engine/memory_file_test.go @@ -9,6 +9,7 @@ import ( ) func TestWithMemoryFile_WritesOnRemember(t *testing.T) { + t.Parallel() dir := t.TempDir() memPath := filepath.Join(dir, "MEMORY.md") @@ -38,6 +39,7 @@ func TestWithMemoryFile_WritesOnRemember(t *testing.T) { } func TestWithMemoryFile_EmptyPath(t *testing.T) { + t.Parallel() // No memory file configured: Remember must not error. eng := newTestEngine() _, err := eng.Remember(context.Background(), RememberInput{ @@ -52,6 +54,7 @@ func TestWithMemoryFile_EmptyPath(t *testing.T) { } func TestWithMemoryFile_UpdatesAfterForget(t *testing.T) { + t.Parallel() dir := t.TempDir() memPath := filepath.Join(dir, "MEMORY.md") eng := newTestEngine().WithMemoryFile(memPath) diff --git a/engine/multifactor_rank_test.go b/engine/multifactor_rank_test.go index 8bafae1..a0288d2 100644 --- a/engine/multifactor_rank_test.go +++ b/engine/multifactor_rank_test.go @@ -9,6 +9,7 @@ import ( ) func TestMultiFactorRanker_Rank(t *testing.T) { + t.Parallel() store := setupTestStore(t) ctx := context.Background() @@ -84,6 +85,7 @@ func TestMultiFactorRanker_Rank(t *testing.T) { } func TestMultiFactorRanker_Empty(t *testing.T) { + t.Parallel() store := setupTestStore(t) ranker := NewMultiFactorRanker(DefaultRankingWeights()) ranked := ranker.Rank(context.Background(), nil, nil, store) @@ -93,6 +95,7 @@ func TestMultiFactorRanker_Empty(t *testing.T) { } func TestDefaultRankingWeights(t *testing.T) { + t.Parallel() w := DefaultRankingWeights() total := w.Recency + w.Relevance + w.Frequency + w.Confidence + w.Tier + w.Centrality + w.Pinned if total < 0.99 || total > 1.01 { @@ -101,6 +104,7 @@ func TestDefaultRankingWeights(t *testing.T) { } func TestNormalizeWeights(t *testing.T) { + t.Parallel() w := RankingWeights{ Recency: 2.0, Relevance: 3.0, @@ -118,6 +122,7 @@ func TestNormalizeWeights(t *testing.T) { } func TestNormalizeWeights_ZeroTotal(t *testing.T) { + t.Parallel() w := RankingWeights{} n := normalizeWeights(w) // Should fall back to defaults @@ -127,6 +132,7 @@ func TestNormalizeWeights_ZeroTotal(t *testing.T) { } func TestRecencyScore(t *testing.T) { + t.Parallel() now := time.Now() // Recent node @@ -152,6 +158,7 @@ func TestRecencyScore(t *testing.T) { } func TestFrequencyScore(t *testing.T) { + t.Parallel() // No accesses s := frequencyScore(&storage.Node{AccessCount: 0}) if s != 0 { @@ -166,6 +173,7 @@ func TestFrequencyScore(t *testing.T) { } func TestTierLevelScore(t *testing.T) { + t.Parallel() if tierLevelScore(1) != 1.0 { t.Error("tier 1 should score 1.0") } @@ -181,6 +189,7 @@ func TestTierLevelScore(t *testing.T) { } func TestPinnedScore(t *testing.T) { + t.Parallel() if pinnedScore(true) != 1.0 { t.Error("pinned should score 1.0") } @@ -190,6 +199,7 @@ func TestPinnedScore(t *testing.T) { } func TestRankedNodesToNodes(t *testing.T) { + t.Parallel() ranked := []*RankedNode{ {Node: &storage.Node{ID: "a"}, Score: 1.0}, {Node: &storage.Node{ID: "b"}, Score: 0.5}, diff --git a/engine/pagerank_test.go b/engine/pagerank_test.go index 4e2d845..599e867 100644 --- a/engine/pagerank_test.go +++ b/engine/pagerank_test.go @@ -38,6 +38,7 @@ func eqPath(a, b []string) bool { } func TestShortestPath(t *testing.T) { + t.Parallel() ctx := context.Background() t.Run("same node", func(t *testing.T) { diff --git a/engine/profile_test.go b/engine/profile_test.go index a2a20da..92ee8de 100644 --- a/engine/profile_test.go +++ b/engine/profile_test.go @@ -6,6 +6,7 @@ import ( ) func TestGetUserProfile_Empty(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx := context.Background() p, err := eng.GetUserProfile(ctx, "myproject") @@ -18,6 +19,7 @@ func TestGetUserProfile_Empty(t *testing.T) { } func TestUpdateAndGetUserPreference(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx := context.Background() @@ -41,6 +43,7 @@ func TestUpdateAndGetUserPreference(t *testing.T) { } func TestUpdateUserPreference_Upsert(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx := context.Background() @@ -61,6 +64,7 @@ func TestUpdateUserPreference_Upsert(t *testing.T) { } func TestUpdateUserPreference_EmptyKey(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx := context.Background() if err := eng.UpdateUserPreference(ctx, "proj", "", "val"); err == nil { diff --git a/engine/query_keygen_test.go b/engine/query_keygen_test.go index 46b5c04..15d469f 100644 --- a/engine/query_keygen_test.go +++ b/engine/query_keygen_test.go @@ -17,6 +17,7 @@ func (f fakeKeygen) GenerateKeywords(_ context.Context, _ string) (string, error } func TestRewriteQuery_NilLLMUsesSynonyms(t *testing.T) { + t.Parallel() got := RewriteQuery(context.Background(), nil, KeygenLLMThenSynonyms, "auth bug") // ExpandQuery expands "auth" → adds authentication/authorize/login. if !strings.Contains(got, "auth") || !strings.Contains(got, "authentication") { @@ -25,12 +26,14 @@ func TestRewriteQuery_NilLLMUsesSynonyms(t *testing.T) { } func TestRewriteQuery_EmptyQuery(t *testing.T) { + t.Parallel() if got := RewriteQuery(context.Background(), fakeKeygen{out: "x"}, KeygenLLMOnly, " "); got != "" { t.Errorf("empty query should rewrite to empty, got %q", got) } } func TestRewriteQuery_LLMOnly(t *testing.T) { + t.Parallel() got := RewriteQuery(context.Background(), fakeKeygen{out: "login session cookie"}, KeygenLLMOnly, "why am I logged out?") if got != "login session cookie" { t.Errorf("LLMOnly should return raw keywords, got %q", got) @@ -38,6 +41,7 @@ func TestRewriteQuery_LLMOnly(t *testing.T) { } func TestRewriteQuery_LLMErrorFallsBack(t *testing.T) { + t.Parallel() got := RewriteQuery(context.Background(), fakeKeygen{err: errors.New("boom")}, KeygenLLMOnly, "db config") // Falls back to synonym expansion of the original query. if !strings.Contains(got, "database") || !strings.Contains(got, "configuration") { @@ -46,6 +50,7 @@ func TestRewriteQuery_LLMErrorFallsBack(t *testing.T) { } func TestRewriteQuery_LLMThenSynonymsUnionDedup(t *testing.T) { + t.Parallel() // LLM returns "auth token"; synonym expansion of "auth" also yields auth/... got := RewriteQuery(context.Background(), fakeKeygen{out: "auth token"}, KeygenLLMThenSynonyms, "auth") fields := strings.Fields(got) @@ -68,6 +73,7 @@ func TestRewriteQuery_LLMThenSynonymsUnionDedup(t *testing.T) { } func TestRewriteQuery_SynonymsStrategyIgnoresLLM(t *testing.T) { + t.Parallel() got := RewriteQuery(context.Background(), fakeKeygen{out: "SHOULD_NOT_APPEAR"}, KeygenSynonyms, "config") if strings.Contains(got, "SHOULD_NOT_APPEAR") { t.Errorf("KeygenSynonyms must not call the LLM, got %q", got) diff --git a/engine/query_test.go b/engine/query_test.go index 03cd972..729354c 100644 --- a/engine/query_test.go +++ b/engine/query_test.go @@ -12,6 +12,7 @@ import ( // TestQueryEmptyDatabase verifies Query on an empty store returns a no-results // answer with zero confidence, not an error. func TestQueryEmptyDatabase(t *testing.T) { + t.Parallel() eng := newTestEngine() result, err := eng.Query(context.Background(), "What conventions do we follow?", "empty-proj") @@ -34,6 +35,7 @@ func TestQueryEmptyDatabase(t *testing.T) { // TestQueryEmptyQuestion verifies that an empty question returns an error. func TestQueryEmptyQuestion(t *testing.T) { + t.Parallel() eng := newTestEngine() _, err := eng.Query(context.Background(), "", "proj") @@ -50,6 +52,7 @@ func TestQueryEmptyQuestion(t *testing.T) { // TestQueryBasicRetrieval verifies that Query retrieves relevant memories // and formats them into a coherent answer. func TestQueryBasicRetrieval(t *testing.T) { + t.Parallel() eng := newTestEngine() _, err := eng.Remember(context.Background(), RememberInput{ @@ -111,6 +114,7 @@ func TestQueryBasicRetrieval(t *testing.T) { // TestQueryConfidenceCalculation verifies that the confidence score is the // average of the source nodes' confidence values. func TestQueryConfidenceCalculation(t *testing.T) { + t.Parallel() eng := newTestEngine() n1, _ := eng.Remember(context.Background(), RememberInput{ @@ -154,6 +158,7 @@ func TestQueryConfidenceCalculation(t *testing.T) { // TestQueryFiltersBelowThreshold verifies that nodes with confidence below // the threshold (0.3) are excluded from query results. func TestQueryFiltersBelowThreshold(t *testing.T) { + t.Parallel() eng := newTestEngine() n1, _ := eng.Remember(context.Background(), RememberInput{ @@ -193,6 +198,7 @@ func TestQueryFiltersBelowThreshold(t *testing.T) { // TestQueryWhatIntent verifies the "What" intent produces grouped output. func TestQueryWhatIntent(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -217,6 +223,7 @@ func TestQueryWhatIntent(t *testing.T) { // TestQueryWhyIntent verifies the "Why" intent shows causal reasoning. func TestQueryWhyIntent(t *testing.T) { + t.Parallel() eng := newTestEngine() n1, _ := eng.Remember(context.Background(), RememberInput{ @@ -244,6 +251,7 @@ func TestQueryWhyIntent(t *testing.T) { // TestQueryWhenIntent verifies the "When" intent shows a timeline. func TestQueryWhenIntent(t *testing.T) { + t.Parallel() eng := newTestEngine() n1, _ := eng.Remember(context.Background(), RememberInput{ @@ -276,6 +284,7 @@ func TestQueryWhenIntent(t *testing.T) { // TestQueryHowIntent verifies the "How" intent lists steps and procedures. func TestQueryHowIntent(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -301,6 +310,7 @@ func TestQueryHowIntent(t *testing.T) { // TestQueryProjectScoping verifies that Query only returns memories from // the specified project. func TestQueryProjectScoping(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -324,6 +334,7 @@ func TestQueryProjectScoping(t *testing.T) { // TestQueryCancelledContext verifies that Query respects context cancellation. func TestQueryCancelledContext(t *testing.T) { + t.Parallel() eng := newTestEngine() ctx, cancel := context.WithCancel(context.Background()) @@ -338,6 +349,7 @@ func TestQueryCancelledContext(t *testing.T) { // TestQueryUsesNodeSummary verifies that the answer prefers Summary over Content // when formatting nodes. func TestQueryUsesNodeSummary(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -363,6 +375,7 @@ func TestQueryUsesNodeSummary(t *testing.T) { // TestQueryGeneralIntent verifies the general/default intent path works. func TestQueryGeneralIntent(t *testing.T) { + t.Parallel() eng := newTestEngine() _, _ = eng.Remember(context.Background(), RememberInput{ @@ -385,6 +398,7 @@ func TestQueryGeneralIntent(t *testing.T) { // TestAverageConfidence verifies the helper function directly. func TestAverageConfidence(t *testing.T) { + t.Parallel() nodes := []*storage.Node{ {Confidence: 1.0}, {Confidence: 0.8}, @@ -404,6 +418,7 @@ func TestAverageConfidence(t *testing.T) { // TestNodeSummary verifies the nodeSummary helper. func TestNodeSummary(t *testing.T) { + t.Parallel() // Node with summary n1 := &storage.Node{Summary: "short summary", Content: "long content here"} if s := nodeSummary(n1); s != "short summary" { diff --git a/engine/rules_test.go b/engine/rules_test.go index 9ef287e..2f0b98f 100644 --- a/engine/rules_test.go +++ b/engine/rules_test.go @@ -7,6 +7,7 @@ import ( ) func TestRememberRule_StoresConventionNode(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.RememberRule(context.Background(), RuleInput{ @@ -32,6 +33,7 @@ func TestRememberRule_StoresConventionNode(t *testing.T) { } func TestRememberRule_WithGlobs(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.RememberRule(context.Background(), RuleInput{ @@ -57,6 +59,7 @@ func TestRememberRule_WithGlobs(t *testing.T) { } func TestRememberRule_Upsert(t *testing.T) { + t.Parallel() eng := newTestEngine() // First insert @@ -85,6 +88,7 @@ func TestRememberRule_Upsert(t *testing.T) { } func TestRememberRule_ContentIncludesDescription(t *testing.T) { + t.Parallel() eng := newTestEngine() node, err := eng.RememberRule(context.Background(), RuleInput{ diff --git a/engine/scoring_test.go b/engine/scoring_test.go index 1ad05d9..2763df1 100644 --- a/engine/scoring_test.go +++ b/engine/scoring_test.go @@ -7,6 +7,7 @@ import ( ) func TestNormalizeBM25(t *testing.T) { + t.Parallel() // Short query: midpoint=5, steepness=0.7 score1 := NormalizeBM25(10.0, 2) // high raw score, short query if score1 < 0.9 { @@ -36,6 +37,7 @@ func TestNormalizeBM25(t *testing.T) { } func TestQueryTermCount(t *testing.T) { + t.Parallel() tests := []struct { query string want int @@ -54,6 +56,7 @@ func TestQueryTermCount(t *testing.T) { } func TestSpreadAttenuatedBoost(t *testing.T) { + t.Parallel() // Single link: no spread penalty boost1 := SpreadAttenuatedBoost(1.0, 1, 0.001) if boost1 < 0.49 || boost1 > 0.51 { @@ -74,6 +77,7 @@ func TestSpreadAttenuatedBoost(t *testing.T) { } func TestMMRRerank(t *testing.T) { + t.Parallel() nodes := []*storage.Node{ {ID: "n1", Content: "Use jose library for JWT authentication tokens"}, {ID: "n2", Content: "Use jose library for JWT auth (duplicate-ish)"}, @@ -108,6 +112,7 @@ func TestMMRRerank(t *testing.T) { } func TestMMRRerank_SingleNode(t *testing.T) { + t.Parallel() nodes := []*storage.Node{{ID: "only", Content: "test"}} scores := map[string]float64{"only": 1.0} @@ -118,6 +123,7 @@ func TestMMRRerank_SingleNode(t *testing.T) { } func TestMMRRerank_EmptyInput(t *testing.T) { + t.Parallel() result := MMRRerank(nil, nil, 0.7, 5) if result != nil { t.Error("nil input should return nil") diff --git a/engine/search_decay_test.go b/engine/search_decay_test.go index 72471ba..de2c0ed 100644 --- a/engine/search_decay_test.go +++ b/engine/search_decay_test.go @@ -12,6 +12,7 @@ import ( // TestSearchTimeDecayHalfLifeFormula verifies the core half-life math: // score * exp(-ln(2)/halfLife * age). func TestSearchTimeDecayHalfLifeFormula(t *testing.T) { + t.Parallel() halfLife := 30 * 24 * time.Hour // 30 days d := SearchTimeDecay{HalfLife: halfLife} now := time.Now() @@ -69,6 +70,7 @@ func TestSearchTimeDecayHalfLifeFormula(t *testing.T) { // TestSearchTimeDecayPrefersAccessedAt verifies that AccessedAt is used as // the reference time when it is more recent than UpdatedAt. func TestSearchTimeDecayPrefersAccessedAt(t *testing.T) { + t.Parallel() halfLife := 30 * 24 * time.Hour d := SearchTimeDecay{HalfLife: halfLife} now := time.Now() @@ -92,6 +94,7 @@ func TestSearchTimeDecayPrefersAccessedAt(t *testing.T) { // TestSearchTimeDecayZeroConfidence verifies zero-confidence nodes get score=0. func TestSearchTimeDecayZeroConfidence(t *testing.T) { + t.Parallel() d := SearchTimeDecay{HalfLife: 30 * 24 * time.Hour} now := time.Now() @@ -108,6 +111,7 @@ func TestSearchTimeDecayZeroConfidence(t *testing.T) { // TestSearchTimeDecayNoHalfLife verifies that a zero half-life passes through // raw confidence without applying decay. func TestSearchTimeDecayNoHalfLife(t *testing.T) { + t.Parallel() d := SearchTimeDecay{HalfLife: 0} now := time.Now() @@ -124,6 +128,7 @@ func TestSearchTimeDecayNoHalfLife(t *testing.T) { // TestSearchTimeDecayFutureTimestamp verifies that nodes with a future // reference time (clock skew) are not penalized. func TestSearchTimeDecayFutureTimestamp(t *testing.T) { + t.Parallel() d := SearchTimeDecay{HalfLife: 30 * 24 * time.Hour} now := time.Now() @@ -140,6 +145,7 @@ func TestSearchTimeDecayFutureTimestamp(t *testing.T) { // TestSearchTimeDecayPartialConfidence verifies decay is applied to // non-unit confidence values correctly. func TestSearchTimeDecayPartialConfidence(t *testing.T) { + t.Parallel() halfLife := 10 * 24 * time.Hour d := SearchTimeDecay{HalfLife: halfLife} now := time.Now() @@ -157,6 +163,7 @@ func TestSearchTimeDecayPartialConfidence(t *testing.T) { // TestSearchTimeDecayEmptySlice verifies graceful handling of an empty input. func TestSearchTimeDecayEmptySlice(t *testing.T) { + t.Parallel() d := SearchTimeDecay{HalfLife: 30 * 24 * time.Hour} results := d.ApplySearchTimeDecay(nil, time.Now()) if len(results) != 0 { @@ -166,6 +173,7 @@ func TestSearchTimeDecayEmptySlice(t *testing.T) { // TestSearchTimeDecayDefaultConfig verifies the default 30-day half-life. func TestSearchTimeDecayDefaultConfig(t *testing.T) { + t.Parallel() d := DefaultSearchTimeDecay() if d.HalfLife != 30*24*time.Hour { t.Errorf("expected 30-day half-life, got %v", d.HalfLife) @@ -175,6 +183,7 @@ func TestSearchTimeDecayDefaultConfig(t *testing.T) { // TestSearchTimeDecayIntegration verifies search-time decay is applied as a // post-fusion re-ranking step in FusedRecall without modifying stored data. func TestSearchTimeDecayIntegration(t *testing.T) { + t.Parallel() eng := newTestEngine() // Enable search-time decay with a very short half-life so the effect is visible. eng.WithSearchDecay(1 * time.Hour) @@ -243,6 +252,7 @@ func TestSearchTimeDecayIntegration(t *testing.T) { // TestSearchTimeDecayDisabledByDefault verifies FusedRecall does not apply // decay when WithSearchDecay has not been called. func TestSearchTimeDecayDisabledByDefault(t *testing.T) { + t.Parallel() eng := newTestEngine() // Do NOT call WithSearchDecay. @@ -271,6 +281,7 @@ func TestSearchTimeDecayDisabledByDefault(t *testing.T) { // TestWithSearchDecayReturnsEngine verifies the fluent API. func TestWithSearchDecayReturnsEngine(t *testing.T) { + t.Parallel() eng := newTestEngine() result := eng.WithSearchDecay(7 * 24 * time.Hour) if result != eng { @@ -287,6 +298,7 @@ func TestWithSearchDecayReturnsEngine(t *testing.T) { // TestSearchDecayAccessorNilByDefault verifies SearchDecay() is nil when // WithSearchDecay has not been called. func TestSearchDecayAccessorNilByDefault(t *testing.T) { + t.Parallel() eng := newTestEngine() if eng.SearchDecay() != nil { t.Error("expected SearchDecay() to be nil by default") diff --git a/engine/sparsify_test.go b/engine/sparsify_test.go index e27182d..52f17e6 100644 --- a/engine/sparsify_test.go +++ b/engine/sparsify_test.go @@ -9,6 +9,7 @@ import ( ) func TestSparsifier_MergeNearDuplicates(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -33,6 +34,7 @@ func TestSparsifier_MergeNearDuplicates(t *testing.T) { } func TestSparsifier_PruneOrphans(t *testing.T) { + t.Parallel() store := setupTestStore(t) defer func() { _ = store.Close() }() @@ -72,6 +74,7 @@ func TestSparsifier_PruneOrphans(t *testing.T) { } func TestContentSimilarity(t *testing.T) { + t.Parallel() tests := []struct { a, b string minSim float64 diff --git a/engine/topic_consolidation_test.go b/engine/topic_consolidation_test.go index 8bfbd49..809fcfc 100644 --- a/engine/topic_consolidation_test.go +++ b/engine/topic_consolidation_test.go @@ -20,6 +20,7 @@ func setupConsolidationStore(t *testing.T) *storage.Store { } func TestTopicConsolidator_Consolidate(t *testing.T) { + t.Parallel() store := setupConsolidationStore(t) ctx := context.Background() @@ -65,6 +66,7 @@ func TestTopicConsolidator_Consolidate(t *testing.T) { } func TestTopicConsolidator_Disabled(t *testing.T) { + t.Parallel() store := setupConsolidationStore(t) cfg := DefaultConsolidationConfig() cfg.Enabled = false @@ -80,6 +82,7 @@ func TestTopicConsolidator_Disabled(t *testing.T) { } func TestKeywordOverlap(t *testing.T) { + t.Parallel() a := map[string]bool{"hello": true, "world": true, "test": true} b := map[string]bool{"hello": true, "world": true, "other": true} @@ -96,6 +99,7 @@ func TestKeywordOverlap(t *testing.T) { } func TestExtractClusterKeywords(t *testing.T) { + t.Parallel() kw := extractClusterKeywords("Use PostgreSQL for the database with proper indexing") if len(kw) == 0 { t.Error("expected keywords") @@ -111,6 +115,7 @@ func TestExtractClusterKeywords(t *testing.T) { } func TestUnionFind(t *testing.T) { + t.Parallel() uf := newUnionFind(5) uf.union(0, 1) uf.union(2, 3) diff --git a/exportimport/export_test.go b/exportimport/export_test.go index 96c7ea7..6031a28 100644 --- a/exportimport/export_test.go +++ b/exportimport/export_test.go @@ -24,6 +24,7 @@ func setupStore(t *testing.T) storage.Storage { } func TestExportJSON_EmptyProject(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -45,6 +46,7 @@ func TestExportJSON_EmptyProject(t *testing.T) { } func TestExportJSON_WithNodes(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -80,6 +82,7 @@ func TestExportJSON_WithNodes(t *testing.T) { } func TestImportJSON_RoundTrip(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -122,6 +125,7 @@ func TestImportJSON_RoundTrip(t *testing.T) { } func TestImportJSON_InvalidJSON(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -132,6 +136,7 @@ func TestImportJSON_InvalidJSON(t *testing.T) { } func TestImportJSON_DuplicateSkipped(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -159,6 +164,7 @@ func TestImportJSON_DuplicateSkipped(t *testing.T) { } func TestExportMarkdown_EmptyProject(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -175,6 +181,7 @@ func TestExportMarkdown_EmptyProject(t *testing.T) { } func TestExportMarkdown_WithNodes(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -206,6 +213,7 @@ func TestExportMarkdown_WithNodes(t *testing.T) { } func TestExportObsidian_CreatesFiles(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -240,6 +248,7 @@ func TestExportObsidian_CreatesFiles(t *testing.T) { } func TestExportObsidian_RelativePathError(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -250,6 +259,7 @@ func TestExportObsidian_RelativePathError(t *testing.T) { } func TestExportObsidian_EmptyProject(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() diff --git a/exportimport/langgraph_test.go b/exportimport/langgraph_test.go index c9bc891..ce0d372 100644 --- a/exportimport/langgraph_test.go +++ b/exportimport/langgraph_test.go @@ -7,6 +7,7 @@ import ( ) func TestImportLangGraph_Basic(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -46,6 +47,7 @@ func TestImportLangGraph_Basic(t *testing.T) { } func TestImportLangGraph_EmptyEntries(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -66,6 +68,7 @@ func TestImportLangGraph_EmptyEntries(t *testing.T) { } func TestImportLangGraph_InvalidJSON(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -76,6 +79,7 @@ func TestImportLangGraph_InvalidJSON(t *testing.T) { } func TestImportLangGraph_Duplicates(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -97,6 +101,7 @@ func TestImportLangGraph_Duplicates(t *testing.T) { } func TestExportForLangGraph_Basic(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -152,6 +157,7 @@ func TestExportForLangGraph_Basic(t *testing.T) { } func TestExportForLangGraph_EmptyProject(t *testing.T) { + t.Parallel() store := setupStore(t) ctx := context.Background() @@ -170,6 +176,7 @@ func TestExportForLangGraph_EmptyProject(t *testing.T) { } func TestExtractRole(t *testing.T) { + t.Parallel() tests := []struct { tags string expected string diff --git a/git/watcher_test.go b/git/watcher_test.go index 6fd6510..0ccb310 100644 --- a/git/watcher_test.go +++ b/git/watcher_test.go @@ -53,6 +53,7 @@ func setupTestRepo(t *testing.T) (string, storage.Storage, graph.Graph) { } func TestNew_ValidDirectory(t *testing.T) { + t.Parallel() dir, store, g := setupTestRepo(t) w, err := New(store, g, dir) @@ -65,6 +66,7 @@ func TestNew_ValidDirectory(t *testing.T) { } func TestNew_NonExistentDirectory(t *testing.T) { + t.Parallel() dir := t.TempDir() store, _ := storage.NewStore(filepath.Join(dir, "test.db")) defer func() { store.Close() }() @@ -77,6 +79,7 @@ func TestNew_NonExistentDirectory(t *testing.T) { } func TestNew_FileNotDirectory(t *testing.T) { + t.Parallel() dir := t.TempDir() filePath := filepath.Join(dir, "file.txt") _ = os.WriteFile(filePath, []byte("hello"), 0o644) @@ -92,6 +95,7 @@ func TestNew_FileNotDirectory(t *testing.T) { } func TestCurrentHash_ValidRepo(t *testing.T) { + t.Parallel() dir, _, _ := setupTestRepo(t) hash := CurrentHash(dir) @@ -104,6 +108,7 @@ func TestCurrentHash_ValidRepo(t *testing.T) { } func TestCurrentHash_NonGitDir(t *testing.T) { + t.Parallel() dir := t.TempDir() hash := CurrentHash(dir) if hash != "" { @@ -112,6 +117,7 @@ func TestCurrentHash_NonGitDir(t *testing.T) { } func TestWatchFile(t *testing.T) { + t.Parallel() dir, store, g := setupTestRepo(t) w, err := New(store, g, dir) @@ -138,6 +144,7 @@ func TestWatchFile(t *testing.T) { } func TestStalesSince_NoChanges(t *testing.T) { + t.Parallel() dir, store, g := setupTestRepo(t) w, err := New(store, g, dir) @@ -157,6 +164,7 @@ func TestStalesSince_NoChanges(t *testing.T) { } func TestStalesSince_WithRecentChange(t *testing.T) { + t.Parallel() dir, store, g := setupTestRepo(t) ctx := context.Background() diff --git a/graph/community_test.go b/graph/community_test.go index 94134f6..5bfd2ce 100644 --- a/graph/community_test.go +++ b/graph/community_test.go @@ -49,6 +49,7 @@ func buildThreeClusterGraph() ([]*storage.Node, []*storage.Edge) { } func TestDetectThreeClusters(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() @@ -81,6 +82,7 @@ func TestDetectThreeClusters(t *testing.T) { } func TestDetectNoEdges(t *testing.T) { + t.Parallel() nodes := []*storage.Node{ {ID: "x1", Type: "decision", Content: "isolated node 1"}, {ID: "x2", Type: "decision", Content: "isolated node 2"}, @@ -97,6 +99,7 @@ func TestDetectNoEdges(t *testing.T) { } func TestDetectEmptyGraph(t *testing.T) { + t.Parallel() cd := NewCommunityDetector() communities := cd.Detect(nil, nil) if communities != nil { @@ -105,6 +108,7 @@ func TestDetectEmptyGraph(t *testing.T) { } func TestModularityPositiveForGoodPartition(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() communities := cd.Detect(nodes, edges) @@ -123,6 +127,7 @@ func TestModularityPositiveForGoodPartition(t *testing.T) { } func TestModularityBadPartitionLower(t *testing.T) { + t.Parallel() _, edges := buildThreeClusterGraph() // A bad partition: put all nodes in one community. @@ -138,6 +143,7 @@ func TestModularityBadPartitionLower(t *testing.T) { } func TestHierarchicalCommunities(t *testing.T) { + t.Parallel() // Build a graph with moderate cross-links so hierarchical merging can occur. // Two sub-clusters within cluster A, two within cluster B, connected moderately. nodes := []*storage.Node{ @@ -205,6 +211,7 @@ func TestHierarchicalCommunities(t *testing.T) { } func TestSearchByCommunityRelevance(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() communities := cd.Detect(nodes, edges) @@ -259,6 +266,7 @@ func TestSearchByCommunityRelevance(t *testing.T) { } func TestCommunitySummaryTokenBudget(t *testing.T) { + t.Parallel() nodes, _ := buildThreeClusterGraph() communities := []Community{ @@ -308,6 +316,7 @@ func TestCommunitySummaryTokenBudget(t *testing.T) { } func TestExpandCommunity(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() communities := cd.Detect(nodes, edges) @@ -332,6 +341,7 @@ func TestExpandCommunity(t *testing.T) { } func TestDriftSearch(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() @@ -396,6 +406,7 @@ func TestDriftSearch(t *testing.T) { } func TestDriftSearchEmptyQuery(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() hierarchy := cd.HierarchicalCommunities(nodes, edges, 2) @@ -408,6 +419,7 @@ func TestDriftSearchEmptyQuery(t *testing.T) { } func TestDriftSearchEmptyHierarchy(t *testing.T) { + t.Parallel() nodes, _ := buildThreeClusterGraph() ds := NewDriftSearcher(nodes, 10) results := ds.DriftSearch("test", nil) @@ -417,6 +429,7 @@ func TestDriftSearchEmptyHierarchy(t *testing.T) { } func TestRankCommunitiesByRelevanceBM25(t *testing.T) { + t.Parallel() nodes, _ := buildThreeClusterGraph() cs := NewCommunitySearcher(nodes) @@ -461,6 +474,7 @@ func TestRankCommunitiesByRelevanceBM25(t *testing.T) { } func TestCommunityStrength(t *testing.T) { + t.Parallel() nodes, edges := buildThreeClusterGraph() cd := NewCommunityDetector() communities := cd.Detect(nodes, edges) diff --git a/graph/graph_test.go b/graph/graph_test.go index 7b72060..281ad8d 100644 --- a/graph/graph_test.go +++ b/graph/graph_test.go @@ -22,6 +22,7 @@ func setupGraph(t *testing.T) (Graph, storage.Storage, func()) { } func TestAddNode(t *testing.T) { + t.Parallel() g, store, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -37,6 +38,7 @@ func TestAddNode(t *testing.T) { } func TestAddEdgeCycleDetection(t *testing.T) { + t.Parallel() g, _, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -67,6 +69,7 @@ func TestAddEdgeCycleDetection(t *testing.T) { } func TestBFSRespectsDirectionality(t *testing.T) { + t.Parallel() g, _, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -110,6 +113,7 @@ func TestBFSRespectsDirectionality(t *testing.T) { } func TestExtractSubgraph(t *testing.T) { + t.Parallel() g, _, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -134,6 +138,7 @@ func TestExtractSubgraph(t *testing.T) { } func TestAncestorsAndDescendants(t *testing.T) { + t.Parallel() g, _, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -170,6 +175,7 @@ func TestAncestorsAndDescendants(t *testing.T) { } func TestIntentBFS(t *testing.T) { + t.Parallel() g, _, cleanup := setupGraph(t) defer cleanup() ctx := context.Background() @@ -199,6 +205,7 @@ func TestIntentBFS(t *testing.T) { } func TestIsAcyclic(t *testing.T) { + t.Parallel() tests := []struct { edgeType string want bool diff --git a/hooks/conversation_test.go b/hooks/conversation_test.go index c7d7dcf..cdb3b8d 100644 --- a/hooks/conversation_test.go +++ b/hooks/conversation_test.go @@ -5,6 +5,7 @@ import ( ) func TestExtractMemory_Decision(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "user", @@ -20,6 +21,7 @@ func TestExtractMemory_Decision(t *testing.T) { } func TestExtractMemory_Convention(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "assistant", @@ -32,6 +34,7 @@ func TestExtractMemory_Convention(t *testing.T) { } func TestExtractMemory_Bug(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "assistant", @@ -44,6 +47,7 @@ func TestExtractMemory_Bug(t *testing.T) { } func TestExtractMemory_Task(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "user", @@ -56,6 +60,7 @@ func TestExtractMemory_Task(t *testing.T) { } func TestExtractMemory_Preference(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "user", @@ -68,6 +73,7 @@ func TestExtractMemory_Preference(t *testing.T) { } func TestExtractMemory_Spec(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "user", @@ -80,6 +86,7 @@ func TestExtractMemory_Spec(t *testing.T) { } func TestExtractMemory_ShortMessage(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "user", @@ -92,6 +99,7 @@ func TestExtractMemory_ShortMessage(t *testing.T) { } func TestExtractMemory_SystemMessage(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "system", @@ -104,6 +112,7 @@ func TestExtractMemory_SystemMessage(t *testing.T) { } func TestExtractMemory_NoSignal(t *testing.T) { + t.Parallel() cc := &ConversationCapture{} msg := ConversationMessage{ Role: "assistant", @@ -116,6 +125,7 @@ func TestExtractMemory_NoSignal(t *testing.T) { } func TestContainsAny(t *testing.T) { + t.Parallel() if !containsAny("hello world", "hello", "foo") { t.Error("expected true for matching keyword") } @@ -125,6 +135,7 @@ func TestContainsAny(t *testing.T) { } func TestConversationCaptureSummary_FormatSummary(t *testing.T) { + t.Parallel() s := ConversationCaptureSummary{ TotalMessages: 10, MemoriesStored: 3, @@ -137,6 +148,7 @@ func TestConversationCaptureSummary_FormatSummary(t *testing.T) { } func TestConversationCaptureSummary_NoMemories(t *testing.T) { + t.Parallel() s := ConversationCaptureSummary{ TotalMessages: 5, ByType: map[string]int{}, diff --git a/hooks/relevance_test.go b/hooks/relevance_test.go index eb955ff..58c57a0 100644 --- a/hooks/relevance_test.go +++ b/hooks/relevance_test.go @@ -3,6 +3,7 @@ package hooks import "testing" func TestScoreRelevance_Errors(t *testing.T) { + t.Parallel() score := ScoreRelevance("Bash", "npm install", "", "exit code 1") if score < 0.9 { t.Errorf("errors should score 0.9, got %f", score) @@ -10,6 +11,7 @@ func TestScoreRelevance_Errors(t *testing.T) { } func TestScoreRelevance_FileModifications(t *testing.T) { + t.Parallel() score := ScoreRelevance("Write", "src/components/auth/main.go", "file written successfully to disk", "") if score < 0.7 { t.Errorf("Write tool should score >= 0.7, got %f", score) @@ -17,6 +19,7 @@ func TestScoreRelevance_FileModifications(t *testing.T) { } func TestScoreRelevance_ReadLowSignal(t *testing.T) { + t.Parallel() score := ScoreRelevance("Read", "src/main.go", "package main...", "") if score > 0.5 { t.Errorf("Read tool should be low signal, got %f", score) @@ -24,6 +27,7 @@ func TestScoreRelevance_ReadLowSignal(t *testing.T) { } func TestScoreRelevance_BashInstall(t *testing.T) { + t.Parallel() score := ScoreRelevance("Bash", "npm install express morgan helmet", "added 50 packages in 3.2s", "") if score < 0.7 { t.Errorf("install commands should score >= 0.7, got %f", score) @@ -31,6 +35,7 @@ func TestScoreRelevance_BashInstall(t *testing.T) { } func TestScoreRelevance_BashNavigation(t *testing.T) { + t.Parallel() score := ScoreRelevance("Bash", "ls src/", "main.go utils.go", "") if score > 0.3 { t.Errorf("navigation commands should be low signal, got %f", score) @@ -38,6 +43,7 @@ func TestScoreRelevance_BashNavigation(t *testing.T) { } func TestScoreRelevance_DecisionSignal(t *testing.T) { + t.Parallel() score := ScoreRelevance("Bash", "decided to use jose", "switched to jose library", "") if score < 0.5 { t.Errorf("decision signals should boost score, got %f", score) @@ -45,18 +51,21 @@ func TestScoreRelevance_DecisionSignal(t *testing.T) { } func TestShouldCapture_HighSignal(t *testing.T) { + t.Parallel() if !ShouldCapture("Write", "writing config", "done", "") { t.Error("Write tool should pass capture threshold") } } func TestShouldCapture_LowSignal(t *testing.T) { + t.Parallel() if ShouldCapture("Read", "x", "y", "") { t.Error("short Read output should not pass capture threshold") } } func TestScoreRelevance_CappedAt1(t *testing.T) { + t.Parallel() score := ScoreRelevance("Write", "decided to always enforce convention required", "written pattern", "") if score > 1.0 { t.Errorf("score should never exceed 1.0, got %f", score) @@ -64,6 +73,7 @@ func TestScoreRelevance_CappedAt1(t *testing.T) { } func TestContainsDecisionSignal(t *testing.T) { + t.Parallel() if !containsDecisionSignal("we decided to use postgres") { t.Error("should detect 'decided'") } @@ -73,6 +83,7 @@ func TestContainsDecisionSignal(t *testing.T) { } func TestContainsConventionSignal(t *testing.T) { + t.Parallel() if !containsConventionSignal("always use camelCase") { t.Error("should detect 'always'") } diff --git a/hooks/runner_test.go b/hooks/runner_test.go index 8890866..fedb209 100644 --- a/hooks/runner_test.go +++ b/hooks/runner_test.go @@ -31,6 +31,7 @@ func setupRunner(t *testing.T) (*Runner, *storage.Store, string) { } func TestReadInput_DecodesJSON(t *testing.T) { + t.Parallel() r := strings.NewReader(`{"session_id":"s1","project":"p1","agent":"a1","tool_name":"Write","tool_input":"main.go"}`) in, err := ReadInput(r) if err != nil { @@ -54,6 +55,7 @@ func TestReadInput_DecodesJSON(t *testing.T) { } func TestReadInput_Empty(t *testing.T) { + t.Parallel() in, err := ReadInput(strings.NewReader("")) if err != nil { t.Fatalf("ReadInput on empty reader: %v", err) @@ -67,6 +69,7 @@ func TestReadInput_Empty(t *testing.T) { } func TestReadInput_InvalidJSON(t *testing.T) { + t.Parallel() in, err := ReadInput(strings.NewReader(`{"session_id": `)) if err == nil { t.Fatal("expected error decoding malformed JSON") @@ -80,6 +83,7 @@ func TestReadInput_InvalidJSON(t *testing.T) { } func TestNew_SetsFields(t *testing.T) { + t.Parallel() r, _, project := setupRunner(t) if r.eng == nil { t.Error("expected non-nil engine") @@ -90,6 +94,7 @@ func TestNew_SetsFields(t *testing.T) { } func TestNew_EmptyProjectDefaultsToCwd(t *testing.T) { + t.Parallel() store, err := storage.NewStore(filepath.Join(t.TempDir(), "t.db")) if err != nil { t.Fatalf("NewStore: %v", err) @@ -105,6 +110,7 @@ func TestNew_EmptyProjectDefaultsToCwd(t *testing.T) { } func TestSessionStart_CreatesSessionAndFile(t *testing.T) { + t.Parallel() r, store, project := setupRunner(t) ctx := context.Background() @@ -132,6 +138,7 @@ func TestSessionStart_CreatesSessionAndFile(t *testing.T) { } func TestPostToolUse_StoresObservation(t *testing.T) { + t.Parallel() r, store, project := setupRunner(t) ctx := context.Background() @@ -163,6 +170,7 @@ func TestPostToolUse_StoresObservation(t *testing.T) { } func TestPostToolUse_EmptyToolNameNoop(t *testing.T) { + t.Parallel() r, store, _ := setupRunner(t) ctx := context.Background() @@ -176,6 +184,7 @@ func TestPostToolUse_EmptyToolNameNoop(t *testing.T) { } func TestPostToolUse_LowSignalReadFiltered(t *testing.T) { + t.Parallel() r, store, _ := setupRunner(t) ctx := context.Background() @@ -196,6 +205,7 @@ func TestPostToolUse_LowSignalReadFiltered(t *testing.T) { } func TestSessionEnd_StoresSummaryAndRemovesFile(t *testing.T) { + t.Parallel() r, store, project := setupRunner(t) ctx := context.Background() @@ -226,6 +236,7 @@ func TestSessionEnd_StoresSummaryAndRemovesFile(t *testing.T) { } func TestSessionEnd_NoSessionNoop(t *testing.T) { + t.Parallel() r, store, _ := setupRunner(t) ctx := context.Background() @@ -240,6 +251,7 @@ func TestSessionEnd_NoSessionNoop(t *testing.T) { } func TestCaptureMessages_StoresMemories(t *testing.T) { + t.Parallel() r, store, project := setupRunner(t) ctx := context.Background() @@ -274,6 +286,7 @@ func TestCaptureMessages_StoresMemories(t *testing.T) { } func TestCaptureMessages_Empty(t *testing.T) { + t.Parallel() r, _, project := setupRunner(t) cc := NewConversationCapture(r.eng, project) if n := cc.CaptureMessages(context.Background(), nil, "sess-1", "agent-a"); n != 0 { diff --git a/ingest/chunker_test.go b/ingest/chunker_test.go index d59e7bc..4af59d3 100644 --- a/ingest/chunker_test.go +++ b/ingest/chunker_test.go @@ -6,6 +6,7 @@ import ( ) func TestChunkGoFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `package main @@ -78,6 +79,7 @@ func main() { } func TestChunkGoFileSingleFunction(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `package util @@ -108,6 +110,7 @@ func Add(a, b int) int { } func TestChunkPythonFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `import os import sys @@ -163,6 +166,7 @@ def helper(): } func TestChunkPythonClassSplit(t *testing.T) { + t.Parallel() // Create a class that exceeds MaxChunkTokens chunker := NewChunker() chunker.MaxChunkTokens = 100 // deliberately low to trigger splitting @@ -197,6 +201,7 @@ func TestChunkPythonClassSplit(t *testing.T) { } func TestChunkTypeScriptFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `import { Request, Response } from 'express'; import { User } from './models'; @@ -265,6 +270,7 @@ export const DEFAULT_PORT = 3000; } func TestChunkTypeScriptExports(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `export function greet(name: string): string { return "Hello " + name; @@ -291,6 +297,7 @@ export function farewell(name: string): string { } func TestChunkGenericFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `first block line 1 first block line 2 @@ -320,6 +327,7 @@ third block line 1 } func TestChunkRustFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `use std::collections::HashMap; @@ -365,6 +373,7 @@ pub fn distance(a: &Point, b: &Point) -> f64 { } func TestChunkJavaFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `package com.example; @@ -398,6 +407,7 @@ public class Calculator { } func TestChunkCppFile(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `#include @@ -428,6 +438,7 @@ int sum(const std::vector& xs) { } func TestChunkBraceLang_AllmanBraces(t *testing.T) { + t.Parallel() chunker := NewChunker() // Allman style: opening brace on its own line — idiomatic in Java/C/C++. src := `package com.example; @@ -464,6 +475,7 @@ class Helper } func TestChunkBraceLang_RustLifetimes(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `use std::fmt; @@ -498,6 +510,7 @@ pub fn build<'a, T>(x: &'a T) -> Wrapper<'a, T> { } func TestChunkBraceLang_ExtensionRouting(t *testing.T) { + t.Parallel() chunker := NewChunker() cases := []struct { file string @@ -531,6 +544,7 @@ func TestChunkBraceLang_ExtensionRouting(t *testing.T) { } func TestDetectLanguage_BraceExtensions(t *testing.T) { + t.Parallel() want := map[string]string{ "a.rs": "rust", "A.java": "java", "a.c": "c", "a.h": "c", "a.cpp": "cpp", "a.hh": "cpp", "a.hxx": "cpp", "a.cppm": "cpp", "a.tcc": "cpp", @@ -552,6 +566,7 @@ func TestDetectLanguage_BraceExtensions(t *testing.T) { } func TestMergeSmallChunks(t *testing.T) { + t.Parallel() chunker := NewChunker() chunker.MinChunkTokens = 50 @@ -582,6 +597,7 @@ func TestMergeSmallChunks(t *testing.T) { } func TestMergeSmallChunksRespectTypeBoundaries(t *testing.T) { + t.Parallel() chunker := NewChunker() chunker.MinChunkTokens = 50 @@ -599,6 +615,7 @@ func TestMergeSmallChunksRespectTypeBoundaries(t *testing.T) { } func TestMaxChunkTokensSplitsLargeFunctions(t *testing.T) { + t.Parallel() chunker := NewChunker() chunker.MaxChunkTokens = 100 @@ -625,6 +642,7 @@ func TestMaxChunkTokensSplitsLargeFunctions(t *testing.T) { } func TestAddOverlap(t *testing.T) { + t.Parallel() chunker := NewChunker() chunks := []Chunk{ { @@ -675,6 +693,7 @@ func TestAddOverlap(t *testing.T) { } func TestEmptyFileHandling(t *testing.T) { + t.Parallel() chunker := NewChunker() chunks, err := chunker.ChunkFile("empty.go", "") @@ -687,6 +706,7 @@ func TestEmptyFileHandling(t *testing.T) { } func TestLanguageDetection(t *testing.T) { + t.Parallel() cases := []struct { path string expected string @@ -714,6 +734,7 @@ func TestLanguageDetection(t *testing.T) { } func TestEstimateTokens(t *testing.T) { + t.Parallel() // 100 chars of 'a' — BPE compresses repeated chars efficiently content := strings.Repeat("a", 100) est := EstimateTokens(content) @@ -728,6 +749,7 @@ func TestEstimateTokens(t *testing.T) { } func TestChunkIDDeterministic(t *testing.T) { + t.Parallel() id1 := chunkID("main.go", 1, 10) id2 := chunkID("main.go", 1, 10) id3 := chunkID("main.go", 1, 11) @@ -744,6 +766,7 @@ func TestChunkIDDeterministic(t *testing.T) { } func TestChunkGoConstants(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `package config @@ -774,6 +797,7 @@ var ( } func TestChunkGoMethodParentChunk(t *testing.T) { + t.Parallel() chunker := NewChunker() src := `package main @@ -801,6 +825,7 @@ func (h *Handler) Close() {} } func TestAddOverlapWithZeroLines(t *testing.T) { + t.Parallel() chunker := NewChunker() chunks := []Chunk{ {Content: "a", StartLine: 1, EndLine: 1}, @@ -813,6 +838,7 @@ func TestAddOverlapWithZeroLines(t *testing.T) { } func TestAddOverlapSingleChunk(t *testing.T) { + t.Parallel() chunker := NewChunker() chunks := []Chunk{ {Content: "only one", StartLine: 1, EndLine: 1}, @@ -824,6 +850,7 @@ func TestAddOverlapSingleChunk(t *testing.T) { } func TestGenericChunkingLargeBlock(t *testing.T) { + t.Parallel() chunker := NewChunker() chunker.MaxChunkTokens = 50 @@ -853,6 +880,7 @@ func TestGenericChunkingLargeBlock(t *testing.T) { } func TestNewChunkerDefaults(t *testing.T) { + t.Parallel() c := NewChunker() if c.MaxChunkTokens != 500 { t.Errorf("expected MaxChunkTokens=500, got %d", c.MaxChunkTokens) diff --git a/ingest/dual_stream_test.go b/ingest/dual_stream_test.go index 21d4fe4..fd47712 100644 --- a/ingest/dual_stream_test.go +++ b/ingest/dual_stream_test.go @@ -27,6 +27,7 @@ func setupEngine(t *testing.T) (*engine.Engine, storage.Storage) { } func TestNew_CreatesStream(t *testing.T) { + t.Parallel() eng, _ := setupEngine(t) ds := New(eng) if ds == nil { @@ -36,6 +37,7 @@ func TestNew_CreatesStream(t *testing.T) { } func TestRemember_FastPath(t *testing.T) { + t.Parallel() eng, store := setupEngine(t) ds := New(eng) defer ds.Stop() @@ -68,6 +70,7 @@ func TestRemember_FastPath(t *testing.T) { } func TestRemember_TemporalEdge(t *testing.T) { + t.Parallel() eng, store := setupEngine(t) ds := New(eng) defer ds.Stop() @@ -115,6 +118,7 @@ func TestRemember_TemporalEdge(t *testing.T) { } func TestRemember_MultipleProjects(t *testing.T) { + t.Parallel() eng, _ := setupEngine(t) ds := New(eng) defer ds.Stop() @@ -151,6 +155,7 @@ func TestRemember_MultipleProjects(t *testing.T) { } func TestStop_GracefulShutdown(t *testing.T) { + t.Parallel() eng, _ := setupEngine(t) ds := New(eng) @@ -176,6 +181,7 @@ func TestStop_GracefulShutdown(t *testing.T) { } func TestRemember_EmptyContent(t *testing.T) { + t.Parallel() eng, _ := setupEngine(t) ds := New(eng) defer ds.Stop() diff --git a/intent/intent_test.go b/intent/intent_test.go index 0dc48d4..7a7aa84 100644 --- a/intent/intent_test.go +++ b/intent/intent_test.go @@ -3,6 +3,7 @@ package intent import "testing" func TestClassify(t *testing.T) { + t.Parallel() tests := []struct { query string expect Intent @@ -21,7 +22,9 @@ func TestClassify(t *testing.T) { {"just a random lookup on this thing", IntentGeneral}, } for _, tt := range tests { + tt := tt t.Run(tt.query, func(t *testing.T) { + t.Parallel() got := Classify(tt.query) if got != tt.expect { t.Errorf("Classify(%q) = %v, want %v", tt.query, got, tt.expect) @@ -31,6 +34,7 @@ func TestClassify(t *testing.T) { } func TestWeights_IntentWhy(t *testing.T) { + t.Parallel() w := Weights(IntentWhy) if w.CausedBy <= w.Touches { t.Error("Why intent should boost CausedBy over Touches") @@ -41,6 +45,7 @@ func TestWeights_IntentWhy(t *testing.T) { } func TestWeights_IntentGeneral(t *testing.T) { + t.Parallel() w := Weights(IntentGeneral) if w.CausedBy != 1.0 || w.LedTo != 1.0 || w.PartOf != 1.0 { t.Error("General intent should have all weights at 1.0") @@ -48,6 +53,7 @@ func TestWeights_IntentGeneral(t *testing.T) { } func TestEdgeWeight(t *testing.T) { + t.Parallel() w := Weights(IntentHow) tests := []struct { @@ -59,14 +65,19 @@ func TestEdgeWeight(t *testing.T) { {"unknown_type", 1.0}, } for _, tt := range tests { - got := w.EdgeWeight(tt.edgeType) - if got < tt.min { - t.Errorf("EdgeWeight(%q) = %v, expected >= %v", tt.edgeType, got, tt.min) - } + tt := tt + t.Run(tt.edgeType, func(t *testing.T) { + t.Parallel() + got := w.EdgeWeight(tt.edgeType) + if got < tt.min { + t.Errorf("EdgeWeight(%q) = %v, expected >= %v", tt.edgeType, got, tt.min) + } + }) } } func TestIntent_String(t *testing.T) { + t.Parallel() tests := []struct { intent Intent expect string @@ -79,8 +90,12 @@ func TestIntent_String(t *testing.T) { {IntentWhat, "What"}, } for _, tt := range tests { - if got := tt.intent.String(); got != tt.expect { - t.Errorf("%v.String() = %q, want %q", tt.intent, got, tt.expect) - } + tt := tt + t.Run(tt.expect, func(t *testing.T) { + t.Parallel() + if got := tt.intent.String(); got != tt.expect { + t.Errorf("%v.String() = %q, want %q", tt.intent, got, tt.expect) + } + }) } } diff --git a/internal/daemon/daemon_test.go b/internal/daemon/daemon_test.go index d638350..6871dc4 100644 --- a/internal/daemon/daemon_test.go +++ b/internal/daemon/daemon_test.go @@ -9,6 +9,7 @@ import ( ) func TestPIDFileRoundTrip(t *testing.T) { + t.Parallel() dir := t.TempDir() _ = os.MkdirAll(filepath.Join(dir, ".yaad"), 0o755) @@ -32,6 +33,7 @@ func TestPIDFileRoundTrip(t *testing.T) { } func TestHealthCheck(t *testing.T) { + t.Parallel() // Healthy server srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) @@ -51,6 +53,7 @@ func TestHealthCheck(t *testing.T) { } func TestNormalizeAddr(t *testing.T) { + t.Parallel() tests := []struct{ in, want string }{ {":3456", ":3456"}, {"3456", ":3456"}, diff --git a/internal/proactive/preload_test.go b/internal/proactive/preload_test.go index 2f39fd4..fe52d1a 100644 --- a/internal/proactive/preload_test.go +++ b/internal/proactive/preload_test.go @@ -43,6 +43,7 @@ func newMockSearcher() *mockSearcher { } func TestPreloadFileOpen(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerFileOpen, @@ -67,6 +68,7 @@ func TestPreloadFileOpen(t *testing.T) { } func TestPreloadGitCheckout(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerGitCheckout, @@ -96,6 +98,7 @@ func TestPreloadGitCheckout(t *testing.T) { } func TestPreloadSessionStart(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerSessionStart, @@ -114,6 +117,7 @@ func TestPreloadSessionStart(t *testing.T) { } func TestPreloadEmptyTrigger(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerFileOpen, @@ -132,6 +136,7 @@ func TestPreloadEmptyTrigger(t *testing.T) { } func TestPreloadLimit(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerSessionStart, @@ -150,6 +155,7 @@ func TestPreloadLimit(t *testing.T) { } func TestPreloadDirChange(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerDirChange, @@ -168,6 +174,7 @@ func TestPreloadDirChange(t *testing.T) { } func TestPreloadQueryPrefix(t *testing.T) { + t.Parallel() searcher := newMockSearcher() trigger := PreloadTrigger{ Kind: TriggerQuery, @@ -186,6 +193,7 @@ func TestPreloadQueryPrefix(t *testing.T) { } func TestPreloadDeduplication(t *testing.T) { + t.Parallel() searcher := newMockSearcher() // "internal/search/intent.go" will fire queries for the full path, // the filename "intent.go", and the directory "internal/search". @@ -214,6 +222,7 @@ func TestPreloadDeduplication(t *testing.T) { } func TestPreloadCancellation(t *testing.T) { + t.Parallel() searcher := newMockSearcher() ctx, cancel := context.WithCancel(context.Background()) cancel() // cancel immediately @@ -234,6 +243,7 @@ func TestPreloadCancellation(t *testing.T) { } func TestTriggerKindString(t *testing.T) { + t.Parallel() tests := []struct { kind TriggerKind want string diff --git a/internal/search/intent_test.go b/internal/search/intent_test.go index 9e9d939..62e1042 100644 --- a/internal/search/intent_test.go +++ b/internal/search/intent_test.go @@ -5,6 +5,7 @@ import ( ) func TestClassifyIntent(t *testing.T) { + t.Parallel() tests := []struct { query string want QueryIntent @@ -59,6 +60,7 @@ func TestClassifyIntent(t *testing.T) { } func TestIntentString(t *testing.T) { + t.Parallel() tests := []struct { intent QueryIntent want string @@ -79,6 +81,7 @@ func TestIntentString(t *testing.T) { } func TestIntentWeightsKeys(t *testing.T) { + t.Parallel() expectedEdges := []string{ "caused_by", "led_to", "supersedes", "learned_in", "part_of", "relates_to", "depends_on", "touches", @@ -100,6 +103,7 @@ func TestIntentWeightsKeys(t *testing.T) { } func TestIntentWeightsBoost(t *testing.T) { + t.Parallel() // Why queries should strongly boost causal edges. whyWeights := IntentWeights(IntentWhy) if whyWeights["caused_by"] <= whyWeights["touches"] { diff --git a/internal/server/dashboard_test.go b/internal/server/dashboard_test.go index 690df7d..07e800b 100644 --- a/internal/server/dashboard_test.go +++ b/internal/server/dashboard_test.go @@ -8,6 +8,7 @@ import ( ) func TestServeDashboardReturnsHTML(t *testing.T) { + t.Parallel() mux := http.NewServeMux() ServeDashboard(mux) @@ -31,6 +32,7 @@ func TestServeDashboardReturnsHTML(t *testing.T) { } func TestServeDashboardCharset(t *testing.T) { + t.Parallel() mux := http.NewServeMux() ServeDashboard(mux) @@ -45,6 +47,7 @@ func TestServeDashboardCharset(t *testing.T) { } func TestServeDashboardEmbedNotEmpty(t *testing.T) { + t.Parallel() // The embedded HTML should not be empty if len(dashboardHTML) == 0 { t.Error("dashboardHTML embed is empty") @@ -52,6 +55,7 @@ func TestServeDashboardEmbedNotEmpty(t *testing.T) { } func TestServeDashboardContainsHTML(t *testing.T) { + t.Parallel() // The embedded content should look like HTML html := string(dashboardHTML) if !strings.Contains(html, "<") { @@ -60,6 +64,7 @@ func TestServeDashboardContainsHTML(t *testing.T) { } func TestServeDashboardMethodNotAllowed(t *testing.T) { + t.Parallel() mux := http.NewServeMux() ServeDashboard(mux) diff --git a/internal/server/handlers_extra_test.go b/internal/server/handlers_extra_test.go index 9925734..d59f951 100644 --- a/internal/server/handlers_extra_test.go +++ b/internal/server/handlers_extra_test.go @@ -22,6 +22,7 @@ func newMux(t *testing.T) (*RESTServer, *engine.Engine, *http.ServeMux, func()) } func TestHandleGetNode(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -63,6 +64,7 @@ func TestHandleGetNode(t *testing.T) { } func TestHandleUpdateNode(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -116,6 +118,7 @@ func TestHandleUpdateNode(t *testing.T) { } func TestHandleForget(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -160,6 +163,7 @@ func TestHandleForget(t *testing.T) { } func TestHandleStats(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -206,6 +210,7 @@ func TestHandleStats(t *testing.T) { } func TestHandleVersions(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -264,6 +269,7 @@ func TestHandleVersions(t *testing.T) { } func TestHandleRollback(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -328,6 +334,7 @@ func TestHandleRollback(t *testing.T) { } func TestHandleContext(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -351,6 +358,7 @@ func TestHandleContext(t *testing.T) { } func TestHandleRecallSeeded(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() @@ -396,6 +404,7 @@ func TestHandleRecallSeeded(t *testing.T) { } func TestHandleImpact(t *testing.T) { + t.Parallel() _, eng, mux, cleanup := newMux(t) defer cleanup() ctx := context.Background() diff --git a/internal/server/mcp_concurrency_rest_test.go b/internal/server/mcp_concurrency_rest_test.go index 7a7cf5a..072cae7 100644 --- a/internal/server/mcp_concurrency_rest_test.go +++ b/internal/server/mcp_concurrency_rest_test.go @@ -21,6 +21,7 @@ import ( ) func TestMCPConcurrentRemember(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -80,6 +81,7 @@ func TestMCPConcurrentRemember(t *testing.T) { } func TestMCPConcurrentRememberAndForget(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -140,6 +142,7 @@ func TestMCPConcurrentRememberAndForget(t *testing.T) { } func TestMCPConcurrentLinkAndRecall(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -199,6 +202,7 @@ func TestMCPConcurrentLinkAndRecall(t *testing.T) { // --------------------------------------------------------------------------- func TestRESTAPIKeyRequired(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -222,6 +226,7 @@ func TestRESTAPIKeyRequired(t *testing.T) { } func TestRESTAPIKeyBearerAuth(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -246,6 +251,7 @@ func TestRESTAPIKeyBearerAuth(t *testing.T) { } func TestRESTAPIKeyXAPIKeyHeader(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -270,6 +276,7 @@ func TestRESTAPIKeyXAPIKeyHeader(t *testing.T) { } func TestRESTAPIKeyWrongKey(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -293,6 +300,7 @@ func TestRESTAPIKeyWrongKey(t *testing.T) { } func TestRESTHealthSkipsAuth(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -314,6 +322,7 @@ func TestRESTHealthSkipsAuth(t *testing.T) { } func TestRESTNoAPIKeyAllowsAll(t *testing.T) { + t.Parallel() _, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -339,6 +348,7 @@ func TestRESTNoAPIKeyAllowsAll(t *testing.T) { // --------------------------------------------------------------------------- func TestMCPSessionRecapNoSessions(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -355,6 +365,7 @@ func TestMCPSessionRecapNoSessions(t *testing.T) { } func TestMCPCompact(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -371,6 +382,7 @@ func TestMCPCompact(t *testing.T) { } func TestMCPProactive(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -388,6 +400,7 @@ func TestMCPProactive(t *testing.T) { } func TestMCPMentalModel(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -405,6 +418,7 @@ func TestMCPMentalModel(t *testing.T) { } func TestMCPProfile(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -424,6 +438,7 @@ func TestMCPProfile(t *testing.T) { // TestMCPToolRegistration verifies that all expected tools are registered // and that the tool count matches expectations. func TestMCPToolRegistration(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -441,6 +456,7 @@ func TestMCPToolRegistration(t *testing.T) { // TestMCPRoundTripRememberRecall stores a memory and verifies it can be found // via recall, testing the full create-search pipeline. func TestMCPRoundTripRememberRecall(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() diff --git a/internal/server/mcp_graph_test.go b/internal/server/mcp_graph_test.go index 1c80228..f39bacb 100644 --- a/internal/server/mcp_graph_test.go +++ b/internal/server/mcp_graph_test.go @@ -17,6 +17,7 @@ import ( ) func TestMCPLinkAndUnlink(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -57,6 +58,7 @@ func TestMCPLinkAndUnlink(t *testing.T) { } func TestMCPLinkInvalidEdgeType(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -81,6 +83,7 @@ func TestMCPLinkInvalidEdgeType(t *testing.T) { } func TestMCPLinkMissingEdgeType(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -101,6 +104,7 @@ func TestMCPLinkMissingEdgeType(t *testing.T) { } func TestMCPSubgraph(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -135,6 +139,7 @@ func TestMCPSubgraph(t *testing.T) { } func TestMCPStatus(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -153,6 +158,7 @@ func TestMCPStatus(t *testing.T) { } func TestMCPSessions(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -168,6 +174,7 @@ func TestMCPSessions(t *testing.T) { } func TestMCPSkillStoreAndGet(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -191,6 +198,7 @@ func TestMCPSkillStoreAndGet(t *testing.T) { } func TestMCPSkillStoreInvalidSteps(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -210,6 +218,7 @@ func TestMCPSkillStoreInvalidSteps(t *testing.T) { } func TestMCPFeedbackApprove(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -230,6 +239,7 @@ func TestMCPFeedbackApprove(t *testing.T) { } func TestMCPFeedbackEdit(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -251,6 +261,7 @@ func TestMCPFeedbackEdit(t *testing.T) { } func TestMCPFeedbackDiscard(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -271,6 +282,7 @@ func TestMCPFeedbackDiscard(t *testing.T) { } func TestMCPFeedbackInvalidAction(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -292,6 +304,7 @@ func TestMCPFeedbackInvalidAction(t *testing.T) { // --------------------------------------------------------------------------- func TestMCPRecallEmptyQuery(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -311,6 +324,7 @@ func TestMCPRecallEmptyQuery(t *testing.T) { } func TestMCPContext(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -328,6 +342,7 @@ func TestMCPContext(t *testing.T) { } func TestMCPContextCanceled(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -342,6 +357,7 @@ func TestMCPContextCanceled(t *testing.T) { } func TestMCPRecallCanceledContext(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -356,6 +372,7 @@ func TestMCPRecallCanceledContext(t *testing.T) { } func TestMCPRememberCanceledContext(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -370,6 +387,7 @@ func TestMCPRememberCanceledContext(t *testing.T) { } func TestMCPForgetCanceledContext(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -384,6 +402,7 @@ func TestMCPForgetCanceledContext(t *testing.T) { } func TestMCPImpactCanceledContext(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -398,6 +417,7 @@ func TestMCPImpactCanceledContext(t *testing.T) { } func TestMCPSubgraphDepthClamp(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -419,6 +439,7 @@ func TestMCPSubgraphDepthClamp(t *testing.T) { } func TestMCPImpactDepthClamp(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -438,6 +459,7 @@ func TestMCPImpactDepthClamp(t *testing.T) { } func TestMCPRememberContentTooLong(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -456,6 +478,7 @@ func TestMCPRememberContentTooLong(t *testing.T) { } func TestMCPVerifyWithoutIntegrity(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() diff --git a/internal/server/mcp_test.go b/internal/server/mcp_test.go index 1bc9457..9bef3b0 100644 --- a/internal/server/mcp_test.go +++ b/internal/server/mcp_test.go @@ -93,6 +93,7 @@ func rememberAndID(t *testing.T, srv *MCPServer, content, typ string) string { // test helpers plus the remember/forget/pin/recall test groups. func TestMCPRememberCreatesNode(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -128,6 +129,7 @@ func TestMCPRememberCreatesNode(t *testing.T) { } func TestMCPRememberDefaultType(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -148,6 +150,7 @@ func TestMCPRememberDefaultType(t *testing.T) { } func TestMCPRememberInvalidType(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -167,6 +170,7 @@ func TestMCPRememberInvalidType(t *testing.T) { } func TestMCPRememberEmptyContent(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -185,6 +189,7 @@ func TestMCPRememberEmptyContent(t *testing.T) { } func TestMCPForget(t *testing.T) { + t.Parallel() srv, eng, cleanup := setupMCPServer(t) defer cleanup() @@ -216,6 +221,7 @@ func TestMCPForget(t *testing.T) { } func TestMCPForgetNodeNotFound(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -228,6 +234,7 @@ func TestMCPForgetNodeNotFound(t *testing.T) { } func TestMCPTaskUpdate(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -254,6 +261,7 @@ func TestMCPTaskUpdate(t *testing.T) { } func TestMCPPinToggle(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -282,6 +290,7 @@ func TestMCPPinToggle(t *testing.T) { } func TestMCPPinToggleDefault(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -304,6 +313,7 @@ func TestMCPPinToggleDefault(t *testing.T) { // --------------------------------------------------------------------------- func TestMCPRecall(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -332,6 +342,7 @@ func TestMCPRecall(t *testing.T) { } func TestMCPRecallDepthLimitClamp(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -352,6 +363,7 @@ func TestMCPRecallDepthLimitClamp(t *testing.T) { } func TestMCPRecallZeroDepthClamp(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -370,6 +382,7 @@ func TestMCPRecallZeroDepthClamp(t *testing.T) { } func TestMCPRecallLimitClamp(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -389,6 +402,7 @@ func TestMCPRecallLimitClamp(t *testing.T) { } func TestMCPIntent(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() @@ -417,6 +431,7 @@ func TestMCPIntent(t *testing.T) { } func TestMCPHybridRecall(t *testing.T) { + t.Parallel() srv, _, cleanup := setupMCPServer(t) defer cleanup() diff --git a/internal/server/rest_test.go b/internal/server/rest_test.go index c2f8beb..b6a2a77 100644 --- a/internal/server/rest_test.go +++ b/internal/server/rest_test.go @@ -39,6 +39,7 @@ func settleSelfLink() { } func TestHandleRememberValidation(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() @@ -76,6 +77,7 @@ func TestHandleRememberValidation(t *testing.T) { } func TestHandleRecallDepthLimit(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() @@ -104,6 +106,7 @@ func TestHandleRecallDepthLimit(t *testing.T) { } func TestHandleLinkEdgeTypeValidation(t *testing.T) { + t.Parallel() srv, eng, cleanup := setupTestServer(t) defer cleanup() @@ -149,6 +152,7 @@ func TestHandleLinkEdgeTypeValidation(t *testing.T) { } func TestHandleSubgraphDepthLimit(t *testing.T) { + t.Parallel() srv, eng, cleanup := setupTestServer(t) defer cleanup() @@ -174,6 +178,7 @@ func TestHandleSubgraphDepthLimit(t *testing.T) { } func TestHandleHealth(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() @@ -199,6 +204,7 @@ func TestHandleHealth(t *testing.T) { } func TestRequestBodyLimit(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() @@ -218,6 +224,7 @@ func TestRequestBodyLimit(t *testing.T) { } func TestShutdown(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() @@ -230,6 +237,7 @@ func TestShutdown(t *testing.T) { } func TestIsLocalOrigin(t *testing.T) { + t.Parallel() cases := []struct { origin string want bool diff --git a/internal/server/streaming_test.go b/internal/server/streaming_test.go index fc034cd..b1eda67 100644 --- a/internal/server/streaming_test.go +++ b/internal/server/streaming_test.go @@ -36,6 +36,7 @@ func readSSEEvent(t *testing.T, r *bufio.Reader) MemoryEvent { } func TestWatchMemoriesSSE(t *testing.T) { + t.Parallel() srv, eng, cleanup := setupTestServer(t) defer cleanup() @@ -103,6 +104,7 @@ func TestWatchMemoriesSSE(t *testing.T) { } func TestWatchMemoriesDisabled(t *testing.T) { + t.Parallel() srv, _, cleanup := setupTestServer(t) defer cleanup() diff --git a/internal/telemetry/metrics_test.go b/internal/telemetry/metrics_test.go index 8776b12..ab164e8 100644 --- a/internal/telemetry/metrics_test.go +++ b/internal/telemetry/metrics_test.go @@ -53,6 +53,7 @@ func collectMetricNames(t *testing.T) map[string]struct{} { // This exercises the instrument declarations and confirms they are bound to a // live meter via the global delegating provider. func TestInstrumentsRecord(t *testing.T) { + t.Parallel() ctx := context.Background() histograms := []struct { @@ -107,6 +108,7 @@ func TestInstrumentsRecord(t *testing.T) { // confirming the counter instrument is wired to a real aggregator (not the // no-op meter). func TestCounterAccumulates(t *testing.T) { + t.Parallel() ctx := context.Background() HNSWSearchCount.Add(ctx, 2) @@ -148,6 +150,7 @@ func TestCounterAccumulates(t *testing.T) { // TestScopeName asserts the package meter is registered under the expected // instrumentation scope name from metrics.go. func TestScopeName(t *testing.T) { + t.Parallel() ctx := context.Background() // Ensure at least one instrument has recorded so a scope exists. HTTPRequestCount.Add(ctx, 1) diff --git a/internal/temporal/temporal_test.go b/internal/temporal/temporal_test.go index d70f429..695bb3e 100644 --- a/internal/temporal/temporal_test.go +++ b/internal/temporal/temporal_test.go @@ -7,6 +7,7 @@ import ( ) func TestNewWindow(t *testing.T) { + t.Parallel() w := NewWindow(0.9, "abc123") if !w.IsValid() { t.Fatal("new window should be valid") @@ -20,6 +21,7 @@ func TestNewWindow(t *testing.T) { } func TestClampConfidence(t *testing.T) { + t.Parallel() w := NewWindow(1.5, "") if w.Confidence != 1.0 { t.Fatalf("confidence > 1 should be clamped to 1, got %f", w.Confidence) @@ -31,6 +33,7 @@ func TestClampConfidence(t *testing.T) { } func TestIsValidAt(t *testing.T) { + t.Parallel() start := time.Date(2025, 6, 1, 0, 0, 0, 0, time.UTC) w := NewWindowAt(start, 0.8, "def456") @@ -65,6 +68,7 @@ func TestIsValidAt(t *testing.T) { } func TestInvalidate(t *testing.T) { + t.Parallel() w := NewWindow(1.0, "") if !w.IsValid() { t.Fatal("should start valid") @@ -76,6 +80,7 @@ func TestInvalidate(t *testing.T) { } func TestAge(t *testing.T) { + t.Parallel() past := time.Now().Add(-2 * time.Hour) w := NewWindowAt(past, 0.9, "") age := w.Age() @@ -86,6 +91,7 @@ func TestAge(t *testing.T) { } func TestDuration(t *testing.T) { + t.Parallel() start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC) w := NewWindowAt(start, 0.8, "") w.InvalidateAt(start.Add(10 * 24 * time.Hour)) @@ -96,6 +102,7 @@ func TestDuration(t *testing.T) { } func TestDecayedConfidence(t *testing.T) { + t.Parallel() start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC) w := NewWindowAt(start, 1.0, "") @@ -119,6 +126,7 @@ func TestDecayedConfidence(t *testing.T) { } func TestCustomHalfLife(t *testing.T) { + t.Parallel() start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC) w := NewWindowAt(start, 1.0, "") w.SetHalfLife(7 * 24 * time.Hour) // 7-day half-life @@ -137,6 +145,7 @@ func TestCustomHalfLife(t *testing.T) { } func TestDecayBeforeCreation(t *testing.T) { + t.Parallel() start := time.Date(2025, 6, 1, 0, 0, 0, 0, time.UTC) w := NewWindowAt(start, 0.8, "") @@ -148,6 +157,7 @@ func TestDecayBeforeCreation(t *testing.T) { } func TestConcurrentAccess(t *testing.T) { + t.Parallel() w := NewWindow(0.9, "abc") done := make(chan struct{}) go func() { diff --git a/internal/tls/tls_test.go b/internal/tls/tls_test.go index ca7d717..3e6ff34 100644 --- a/internal/tls/tls_test.go +++ b/internal/tls/tls_test.go @@ -10,6 +10,7 @@ import ( ) func TestTLSConfigGeneratesSelfSignedCert(t *testing.T) { + t.Parallel() dir := t.TempDir() cfg := Config{Enabled: true} @@ -45,6 +46,7 @@ func TestTLSConfigGeneratesSelfSignedCert(t *testing.T) { } func TestTLSConfigUsesExistingCerts(t *testing.T) { + t.Parallel() dir := t.TempDir() // Generate certs first time @@ -66,6 +68,7 @@ func TestTLSConfigUsesExistingCerts(t *testing.T) { } func TestTLSConfigCustomCertPaths(t *testing.T) { + t.Parallel() dir := t.TempDir() certPath := filepath.Join(dir, "custom-cert.pem") keyPath := filepath.Join(dir, "custom-key.pem") @@ -89,6 +92,7 @@ func TestTLSConfigCustomCertPaths(t *testing.T) { } func TestSelfSignedCertProperties(t *testing.T) { + t.Parallel() dir := t.TempDir() certPath := filepath.Join(dir, "cert.pem") keyPath := filepath.Join(dir, "key.pem") @@ -153,6 +157,7 @@ func TestSelfSignedCertProperties(t *testing.T) { } func TestSelfSignedCertPEMBlocks(t *testing.T) { + t.Parallel() dir := t.TempDir() certPath := filepath.Join(dir, "cert.pem") keyPath := filepath.Join(dir, "key.pem") @@ -187,6 +192,7 @@ func TestSelfSignedCertPEMBlocks(t *testing.T) { } func TestCertFilePermissions(t *testing.T) { + t.Parallel() dir := t.TempDir() certPath := filepath.Join(dir, "cert.pem") keyPath := filepath.Join(dir, "key.pem") diff --git a/internal/tui/tui_test.go b/internal/tui/tui_test.go index 462ce7b..643202a 100644 --- a/internal/tui/tui_test.go +++ b/internal/tui/tui_test.go @@ -9,6 +9,7 @@ import ( ) func TestScreenConstants(t *testing.T) { + t.Parallel() // Verify screen constants have distinct values if ScreenDashboard == ScreenSearch { t.Error("ScreenDashboard and ScreenSearch should differ") @@ -32,6 +33,7 @@ func TestScreenConstants(t *testing.T) { } func TestTypeColorsCoverage(t *testing.T) { + t.Parallel() // Every known node type should have a color knownTypes := []string{ "convention", "decision", "bug", "spec", "task", @@ -45,6 +47,7 @@ func TestTypeColorsCoverage(t *testing.T) { } func TestTruncate(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -70,6 +73,7 @@ func TestTruncate(t *testing.T) { } func TestTruncateNewlineReplacement(t *testing.T) { + t.Parallel() got := truncate("line1\nline2\nline3", 50) if got != "line1 line2 line3" { t.Errorf("truncate with newlines = %q, want %q", got, "line1 line2 line3") @@ -77,6 +81,7 @@ func TestTruncateNewlineReplacement(t *testing.T) { } func TestModelDefaultScreen(t *testing.T) { + t.Parallel() // Model with nil engine (just testing struct defaults) m := Model{} if m.screen != ScreenDashboard { @@ -100,6 +105,7 @@ func TestModelDefaultScreen(t *testing.T) { } func TestViewDashboardNoStats(t *testing.T) { + t.Parallel() m := Model{screen: ScreenDashboard, width: 80, height: 24} v := m.viewDashboard() if v == "" { @@ -116,6 +122,7 @@ func TestViewDashboardNoStats(t *testing.T) { } func TestViewDashboardWithStats(t *testing.T) { + t.Parallel() m := Model{ screen: ScreenDashboard, width: 80, @@ -139,6 +146,7 @@ func TestViewDashboardWithStats(t *testing.T) { } func TestViewDashboardWithHotNodes(t *testing.T) { + t.Parallel() m := Model{ screen: ScreenDashboard, width: 80, @@ -158,6 +166,7 @@ func TestViewDashboardWithHotNodes(t *testing.T) { } func TestViewSearchEmpty(t *testing.T) { + t.Parallel() m := Model{screen: ScreenSearch, width: 80, height: 24} v := m.viewSearch() if !strings.Contains(v, "Search") { @@ -166,6 +175,7 @@ func TestViewSearchEmpty(t *testing.T) { } func TestViewSearchNoResults(t *testing.T) { + t.Parallel() m := Model{screen: ScreenSearch, width: 80, height: 24, searched: true} v := m.viewSearch() if !strings.Contains(v, "No results found") { @@ -174,6 +184,7 @@ func TestViewSearchNoResults(t *testing.T) { } func TestViewDetailNil(t *testing.T) { + t.Parallel() m := Model{screen: ScreenDetail, width: 80, height: 24} v := m.viewDetail() if v != "" { @@ -182,6 +193,7 @@ func TestViewDetailNil(t *testing.T) { } func TestViewDetailWithNode(t *testing.T) { + t.Parallel() m := Model{ screen: ScreenDetail, width: 80, @@ -211,6 +223,7 @@ func TestViewDetailWithNode(t *testing.T) { } func TestViewDetailWithEdges(t *testing.T) { + t.Parallel() m := Model{ screen: ScreenDetail, width: 80, @@ -236,6 +249,7 @@ func TestViewDetailWithEdges(t *testing.T) { } func TestViewReturnsCorrectScreen(t *testing.T) { + t.Parallel() // Test that View() dispatches to the right sub-view m := Model{screen: ScreenDashboard, width: 80, height: 24} v := m.View() diff --git a/internal/version/version_test.go b/internal/version/version_test.go index b505b74..d2c9df6 100644 --- a/internal/version/version_test.go +++ b/internal/version/version_test.go @@ -7,6 +7,7 @@ import ( ) func TestStringReturnsVersion(t *testing.T) { + t.Parallel() got := String() if got != Version { t.Errorf("String() = %q, want %q", got, Version) @@ -14,6 +15,7 @@ func TestStringReturnsVersion(t *testing.T) { } func TestStringDefault(t *testing.T) { + t.Parallel() // When built without ldflags, Version defaults to "dev". // We only check it's non-empty. if s := String(); s == "" { @@ -22,6 +24,7 @@ func TestStringDefault(t *testing.T) { } func TestFullFormat(t *testing.T) { + t.Parallel() got := Full() // Should start with "yaad " @@ -54,6 +57,7 @@ func TestFullFormat(t *testing.T) { } func TestFullContainsCommitLabel(t *testing.T) { + t.Parallel() got := Full() if !strings.Contains(got, "commit:") { t.Errorf("Full() should contain 'commit:' label, got %q", got) @@ -64,6 +68,7 @@ func TestFullContainsCommitLabel(t *testing.T) { } func TestDefaultValues(t *testing.T) { + t.Parallel() // Verify the default ldflags values are present when not overridden. // These tests work for both dev and release builds because we check // the variable values directly rather than hardcoding expected strings. diff --git a/memory_export_test.go b/memory_export_test.go index 6c19198..bcbaf23 100644 --- a/memory_export_test.go +++ b/memory_export_test.go @@ -9,6 +9,7 @@ import ( ) func TestNewMemoryExport(t *testing.T) { + t.Parallel() t.Run("creates export with version and timestamp", func(t *testing.T) { now := time.Now().UTC() me := &MemoryExport{ @@ -28,6 +29,7 @@ func TestNewMemoryExport(t *testing.T) { } func TestMemoryExportWriteTo(t *testing.T) { + t.Parallel() t.Run("writes valid JSON", func(t *testing.T) { me := &MemoryExport{ Version: "1.0", @@ -129,6 +131,7 @@ func TestMemoryExportWriteTo(t *testing.T) { } func TestReadMemoryExport(t *testing.T) { + t.Parallel() t.Run("reads valid JSON", func(t *testing.T) { jsonData := `{ "version": "1.0", @@ -195,6 +198,7 @@ func TestReadMemoryExport(t *testing.T) { } func TestExportMemory(t *testing.T) { + t.Parallel() t.Run("exports all tiers by default", func(t *testing.T) { sm := NewSpatialMemory(1000, 1000, 1000) now := time.Now().UTC() @@ -392,6 +396,7 @@ func TestExportMemory(t *testing.T) { } func TestImportMemory(t *testing.T) { + t.Parallel() t.Run("imports entries into empty spatial memory", func(t *testing.T) { sm := NewSpatialMemory(1000, 1000, 1000) @@ -538,6 +543,7 @@ func TestImportMemory(t *testing.T) { } func TestMemoryExportRoundTrip(t *testing.T) { + t.Parallel() t.Run("export and import preserves data", func(t *testing.T) { // Create source spatial memory sm1 := NewSpatialMemory(1000, 1000, 1000) @@ -608,6 +614,7 @@ func TestMemoryExportRoundTrip(t *testing.T) { } func TestMemoryExportSummary(t *testing.T) { + t.Parallel() t.Run("generates summary for non-empty export", func(t *testing.T) { me := &MemoryExport{ Version: "1.0", diff --git a/mental/model_test.go b/mental/model_test.go index 09ea139..2ffe321 100644 --- a/mental/model_test.go +++ b/mental/model_test.go @@ -6,6 +6,7 @@ import ( ) func TestModel_Format_Empty(t *testing.T) { + t.Parallel() m := &Model{Project: "test"} out := m.Format() if !strings.Contains(out, "## Project Mental Model") { @@ -14,6 +15,7 @@ func TestModel_Format_Empty(t *testing.T) { } func TestModel_Format_WithData(t *testing.T) { + t.Parallel() m := &Model{ Project: "myapp", Summary: "Stack: Go, PostgreSQL. 2 conventions.", @@ -34,6 +36,7 @@ func TestModel_Format_WithData(t *testing.T) { } func TestBuildSummary_Empty(t *testing.T) { + t.Parallel() m := &Model{} s := buildSummary(m) if s != "No memories yet." { @@ -42,6 +45,7 @@ func TestBuildSummary_Empty(t *testing.T) { } func TestBuildSummary_WithData(t *testing.T) { + t.Parallel() m := &Model{ Stack: []string{"Go", "Redis"}, Conventions: []string{"a", "b"}, @@ -64,6 +68,7 @@ func TestBuildSummary_WithData(t *testing.T) { } func TestIsStackTech(t *testing.T) { + t.Parallel() tests := []struct { name string expect bool @@ -77,8 +82,12 @@ func TestIsStackTech(t *testing.T) { {"MyCustomPkg", false}, } for _, tt := range tests { - if got := isStackTech(tt.name); got != tt.expect { - t.Errorf("isStackTech(%q) = %v, want %v", tt.name, got, tt.expect) - } + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if got := isStackTech(tt.name); got != tt.expect { + t.Errorf("isStackTech(%q) = %v, want %v", tt.name, got, tt.expect) + } + }) } } diff --git a/privacy/filter_test.go b/privacy/filter_test.go index 9198e6d..76b8786 100644 --- a/privacy/filter_test.go +++ b/privacy/filter_test.go @@ -6,6 +6,7 @@ import ( ) func TestFilter_APIKeys(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -19,7 +20,9 @@ func TestFilter_APIKeys(t *testing.T) { {"npm token", "npm_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl"}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := Filter(tt.input) if !strings.Contains(result, "[REDACTED]") { t.Errorf("expected redaction for %s, got: %s", tt.name, result) @@ -29,6 +32,7 @@ func TestFilter_APIKeys(t *testing.T) { } func TestFilter_JWT(t *testing.T) { + t.Parallel() jwt := "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U" result := Filter("token: " + jwt) if !strings.Contains(result, "[REDACTED]") { @@ -37,6 +41,7 @@ func TestFilter_JWT(t *testing.T) { } func TestFilter_PrivateKeys(t *testing.T) { + t.Parallel() key := "-----BEGIN RSA PRIVATE KEY-----\nMIIBogIBAAJ...\n-----END RSA PRIVATE KEY-----" result := Filter("my key: " + key) if !strings.Contains(result, "[REDACTED]") { @@ -45,6 +50,7 @@ func TestFilter_PrivateKeys(t *testing.T) { } func TestFilter_PII(t *testing.T) { + t.Parallel() tests := []struct { name string input string @@ -53,7 +59,9 @@ func TestFilter_PII(t *testing.T) { {"phone", "call 555-123-4567"}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := Filter(tt.input) if !strings.Contains(result, "[REDACTED]") { t.Errorf("expected PII redaction for %s, got: %s", tt.name, result) @@ -63,6 +71,7 @@ func TestFilter_PII(t *testing.T) { } func TestFilter_Strict(t *testing.T) { + t.Parallel() // Strict mode strips emails and all IPs result := FilterWithLevel("contact user@example.com for help", Strict) if !strings.Contains(result, "[REDACTED]") { @@ -75,6 +84,7 @@ func TestFilter_Strict(t *testing.T) { } func TestFilter_Moderate(t *testing.T) { + t.Parallel() // Moderate keeps work-related emails and infrastructure IPs result := FilterWithLevel("contact user@example.com for help", Moderate) if strings.Contains(result, "[REDACTED]") { @@ -92,6 +102,7 @@ func TestFilter_Moderate(t *testing.T) { } func TestFilter_Minimal(t *testing.T) { + t.Parallel() // Minimal only strips high-entropy secrets and explicit API keys result := FilterWithLevel("my key is sk-abcdefghijklmnopqrstuvwxyz", Minimal) if !strings.Contains(result, "[REDACTED]") { @@ -105,6 +116,7 @@ func TestFilter_Minimal(t *testing.T) { } func TestFilter_ConnectionStrings(t *testing.T) { + t.Parallel() input := "db url: postgres://admin:s3cret@db.example.com:5432/mydb" result := Filter(input) if !strings.Contains(result, "[REDACTED]") { @@ -113,6 +125,7 @@ func TestFilter_ConnectionStrings(t *testing.T) { } func TestFilter_SafeContent(t *testing.T) { + t.Parallel() safe := "This is normal code with no secrets. func main() { fmt.Println(hello) }" result := Filter(safe) if strings.Contains(result, "[REDACTED]") { @@ -121,6 +134,7 @@ func TestFilter_SafeContent(t *testing.T) { } func TestIsLikelySecret(t *testing.T) { + t.Parallel() tests := []struct { token string expect bool @@ -140,7 +154,9 @@ func TestIsLikelySecret(t *testing.T) { {"averylongbutrepetitiveaaaaaaaaaaaaaaa", false}, // low entropy } for _, tt := range tests { + tt := tt t.Run(tt.token, func(t *testing.T) { + t.Parallel() got := IsLikelySecret(tt.token) if got != tt.expect { t.Errorf("IsLikelySecret(%q) = %v, want %v", tt.token, got, tt.expect) @@ -153,6 +169,7 @@ func TestIsLikelySecret(t *testing.T) { // high-entropy tokens that no explicit regex matches — the case that previously // silently leaked. Guards confirm ordinary prose is not over-redacted. func TestFilter_HighEntropySecrets(t *testing.T) { + t.Parallel() redact := []struct { name string input string @@ -162,7 +179,9 @@ func TestFilter_HighEntropySecrets(t *testing.T) { {"base64 no padding", "secret YjY3ZmEwMjE5OGE0NjVkZWZmMTIzNDU2Nzg5YWJjZGVm"}, } for _, tt := range redact { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() if got := Filter(tt.input); !strings.Contains(got, "[REDACTED]") { t.Errorf("expected redaction for %s, got: %s", tt.name, got) } @@ -177,7 +196,9 @@ func TestFilter_HighEntropySecrets(t *testing.T) { {"identifier", "func calculateTotalRevenueForQuarterlyReport() error { return nil }"}, } for _, tt := range keep { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() if got := Filter(tt.input); strings.Contains(got, "[REDACTED]") { t.Errorf("over-redacted safe content %s, got: %s", tt.name, got) } @@ -186,6 +207,7 @@ func TestFilter_HighEntropySecrets(t *testing.T) { } func TestIsUpperSnakeCase(t *testing.T) { + t.Parallel() tests := []struct { input string expect bool @@ -197,7 +219,9 @@ func TestIsUpperSnakeCase(t *testing.T) { {"SINGLEWORD", false}, } for _, tt := range tests { + tt := tt t.Run(tt.input, func(t *testing.T) { + t.Parallel() got := isUpperSnakeCase(tt.input) if got != tt.expect { t.Errorf("isUpperSnakeCase(%q) = %v, want %v", tt.input, got, tt.expect) diff --git a/profile/profile_test.go b/profile/profile_test.go index 0a2dcf4..a72ba73 100644 --- a/profile/profile_test.go +++ b/profile/profile_test.go @@ -18,6 +18,7 @@ func seed(t *testing.T, store *storage.MockStorage, n *storage.Node) { } func TestBuild_CollectsStaticDynamicAndStack(t *testing.T) { + t.Parallel() store := storage.NewMockStorage() ctx := context.Background() now := time.Now() @@ -72,6 +73,7 @@ func TestBuild_CollectsStaticDynamicAndStack(t *testing.T) { } func TestBuild_CanceledContext(t *testing.T) { + t.Parallel() store := storage.NewMockStorage() ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -81,6 +83,7 @@ func TestBuild_CanceledContext(t *testing.T) { } func TestBuild_EmptyGraph(t *testing.T) { + t.Parallel() store := storage.NewMockStorage() p, err := Build(context.Background(), store, "empty") if err != nil { @@ -96,6 +99,7 @@ func TestBuild_EmptyGraph(t *testing.T) { } func TestBuild_PropagatesStorageError(t *testing.T) { + t.Parallel() store := storage.NewMockStorage() store.SetError(errors.New("boom")) // Build ignores per-call errors (uses _), so it should still succeed but be empty. @@ -109,6 +113,7 @@ func TestBuild_PropagatesStorageError(t *testing.T) { } func TestFormat(t *testing.T) { + t.Parallel() p := &Profile{ Project: "proj", Summary: "Stack: go · 2 facts", @@ -131,6 +136,7 @@ func TestFormat(t *testing.T) { } func TestFormat_EmptyProfileOmitsSections(t *testing.T) { + t.Parallel() p := &Profile{Project: "proj"} out := p.Format() if strings.Contains(out, "What I Know") || strings.Contains(out, "What's Happening") { @@ -139,6 +145,7 @@ func TestFormat_EmptyProfileOmitsSections(t *testing.T) { } func TestFormat_CapsLists(t *testing.T) { + t.Parallel() var static []string for i := 0; i < 20; i++ { static = append(static, "fact") @@ -152,6 +159,7 @@ func TestFormat_CapsLists(t *testing.T) { } func TestMerge(t *testing.T) { + t.Parallel() a := &Profile{Project: "proj", Static: []string{"x"}, Dynamic: []string{"d1"}, Stack: []string{"go"}, Summary: "A"} b := &Profile{Project: "global", Static: []string{"x", "y"}, Dynamic: []string{"d2"}, Stack: []string{"go", "rust"}, Summary: "B"} m := Merge(a, b) @@ -173,6 +181,7 @@ func TestMerge(t *testing.T) { } func TestIsTech(t *testing.T) { + t.Parallel() for _, tech := range []string{"go", "Go", "TYPESCRIPT", "PostgreSQL", "react"} { if !isTech(tech) { t.Errorf("isTech(%q) = false, want true", tech) @@ -186,6 +195,7 @@ func TestIsTech(t *testing.T) { } func TestDedup(t *testing.T) { + t.Parallel() in := []string{"Go", "go", "GO", "rust", "Rust"} out := dedup(in) if len(out) != 2 { diff --git a/skill/skill_test.go b/skill/skill_test.go index 165a96e..7e3970e 100644 --- a/skill/skill_test.go +++ b/skill/skill_test.go @@ -27,6 +27,7 @@ func setupEngine(t *testing.T) (*engine.Engine, storage.Storage) { } func TestStore_CreatesSkillNode(t *testing.T) { + t.Parallel() eng, store := setupEngine(t) ctx := context.Background() @@ -63,6 +64,7 @@ func TestStore_CreatesSkillNode(t *testing.T) { } func TestLoad_FindsSkillByName(t *testing.T) { + t.Parallel() eng, store := setupEngine(t) ctx := context.Background() @@ -95,6 +97,7 @@ func TestLoad_FindsSkillByName(t *testing.T) { } func TestLoad_NotFound(t *testing.T) { + t.Parallel() _, store := setupEngine(t) ctx := context.Background() @@ -108,6 +111,7 @@ func TestLoad_NotFound(t *testing.T) { } func TestListSkills_Empty(t *testing.T) { + t.Parallel() _, store := setupEngine(t) ctx := context.Background() @@ -121,6 +125,7 @@ func TestListSkills_Empty(t *testing.T) { } func TestListSkills_MultipleSkills(t *testing.T) { + t.Parallel() eng, store := setupEngine(t) ctx := context.Background() @@ -146,6 +151,7 @@ func TestListSkills_MultipleSkills(t *testing.T) { } func TestReplay_FormatsCorrectly(t *testing.T) { + t.Parallel() s := &Skill{ Name: "release", Description: "Release a new version", @@ -172,6 +178,7 @@ func TestReplay_FormatsCorrectly(t *testing.T) { } func TestReplay_EmptySteps(t *testing.T) { + t.Parallel() s := &Skill{ Name: "empty", Description: "No steps", @@ -184,6 +191,7 @@ func TestReplay_EmptySteps(t *testing.T) { } func TestAddTag(t *testing.T) { + t.Parallel() tests := []struct { tags, tag, want string }{ @@ -192,9 +200,13 @@ func TestAddTag(t *testing.T) { {"a,b", "c", "a,b,c"}, } for _, tt := range tests { - got := addTag(tt.tags, tt.tag) - if got != tt.want { - t.Errorf("addTag(%q, %q) = %q, want %q", tt.tags, tt.tag, got, tt.want) - } + tt := tt + t.Run(tt.tags+"_"+tt.tag, func(t *testing.T) { + t.Parallel() + got := addTag(tt.tags, tt.tag) + if got != tt.want { + t.Errorf("addTag(%q, %q) = %q, want %q", tt.tags, tt.tag, got, tt.want) + } + }) } } diff --git a/spatial_memory_test.go b/spatial_memory_test.go index 2337706..1c44641 100644 --- a/spatial_memory_test.go +++ b/spatial_memory_test.go @@ -38,6 +38,7 @@ func withWarmDemoteAfter(d time.Duration) func(*SpatialMemory) { // --------------------------------------------------------------------------- func TestNewSpatialMemoryInitialization(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 200, 300) if sm.hotBudget != 100 { @@ -76,6 +77,7 @@ func TestNewSpatialMemoryInitialization(t *testing.T) { // --------------------------------------------------------------------------- func TestAddEntriesLandInCold(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) cases := []struct { @@ -119,6 +121,7 @@ func TestAddEntriesLandInCold(t *testing.T) { } func TestAddOverwritesExistingEntry(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) sm.Add(MemoryEntry{ID: "dup", Content: "original", TokenCount: 10}) @@ -135,6 +138,7 @@ func TestAddOverwritesExistingEntry(t *testing.T) { } func TestAddSetsCreatedAtIfZero(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) before := time.Now() sm.Add(MemoryEntry{ID: "ts", Content: "ts", TokenCount: 1}) @@ -150,6 +154,7 @@ func TestAddSetsCreatedAtIfZero(t *testing.T) { } func TestAddPreservesCreatedAtIfSet(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) past := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) sm.Add(MemoryEntry{ID: "ts", Content: "ts", TokenCount: 1, CreatedAt: past}) @@ -165,6 +170,7 @@ func TestAddPreservesCreatedAtIfSet(t *testing.T) { // --------------------------------------------------------------------------- func TestAccessPromotesColdToWarm(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) sm.Add(MemoryEntry{ID: "e1", Content: "c", TokenCount: 5}) @@ -182,6 +188,7 @@ func TestAccessPromotesColdToWarm(t *testing.T) { } func TestAccessPromotesWarmToHotAfterThreshold(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(3), @@ -204,6 +211,7 @@ func TestAccessPromotesWarmToHotAfterThreshold(t *testing.T) { } func TestAccessReturnsFalseForMissingID(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) _, ok := sm.Access("nonexistent") if ok { @@ -212,6 +220,7 @@ func TestAccessReturnsFalseForMissingID(t *testing.T) { } func TestAccessDoesNotPromoteWarmToHotBeforeThreshold(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(5), @@ -231,6 +240,7 @@ func TestAccessDoesNotPromoteWarmToHotBeforeThreshold(t *testing.T) { } func TestAccessPromotesWarmToHotRespectsWindow(t *testing.T) { + t.Parallel() // Use a very short window so accesses "expire". sm := newTestSpatialMemory( 1000, 1000, 1000, @@ -255,6 +265,7 @@ func TestAccessPromotesWarmToHotRespectsWindow(t *testing.T) { // --------------------------------------------------------------------------- func TestCompactDemotesHotToWarmAfterInactivity(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(2), @@ -290,6 +301,7 @@ func TestCompactDemotesHotToWarmAfterInactivity(t *testing.T) { } func TestCompactDemotesWarmToColdAfterInactivity(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withWarmDemoteAfter(10*time.Millisecond), @@ -315,6 +327,7 @@ func TestCompactDemotesWarmToColdAfterInactivity(t *testing.T) { } func TestCompactDoesNotDemoteRecentlyAccessed(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(2), @@ -339,6 +352,7 @@ func TestCompactDoesNotDemoteRecentlyAccessed(t *testing.T) { // --------------------------------------------------------------------------- func TestBudgetEnforcementDemotesEntries(t *testing.T) { + t.Parallel() // Hot budget is 50 tokens. Each entry is 20 tokens. // 3 entries = 60 tokens > 50 budget. Oldest should be demoted. sm := NewSpatialMemory(50, 1000, 1000) @@ -371,6 +385,7 @@ func TestBudgetEnforcementDemotesEntries(t *testing.T) { } func TestBudgetEnforcementDemotesOldestFirst(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(30, 1000, 1000) // Add entry "old" first. @@ -415,6 +430,7 @@ func TestBudgetEnforcementDemotesOldestFirst(t *testing.T) { } func TestBudgetZeroDoesNotPanic(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(0, 0, 0) sm.Add(MemoryEntry{ID: "e1", Content: "c", TokenCount: 100}) // Should not panic. @@ -423,6 +439,7 @@ func TestBudgetZeroDoesNotPanic(t *testing.T) { } func TestAddTriggersBudgetEnforcementOnColdTier(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 50) // Add 3 entries with 20 tokens each = 60 > cold budget 50. @@ -447,6 +464,7 @@ func TestAddTriggersBudgetEnforcementOnColdTier(t *testing.T) { // --------------------------------------------------------------------------- func TestTierStatsEmptyMemory(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) stats := sm.TierStats() if len(stats) != 0 { @@ -455,6 +473,7 @@ func TestTierStatsEmptyMemory(t *testing.T) { } func TestTierStatsMixedTiers(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(2), @@ -496,6 +515,7 @@ func TestTierStatsMixedTiers(t *testing.T) { } func TestTierStatsAfterRemove(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) sm.Add(MemoryEntry{ID: "a", Content: "a", TokenCount: 10}) sm.Add(MemoryEntry{ID: "b", Content: "b", TokenCount: 20}) @@ -516,12 +536,14 @@ func TestTierStatsAfterRemove(t *testing.T) { // --------------------------------------------------------------------------- func TestCompactEmptyMemory(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) // Should not panic. sm.Compact() } func TestCompactEnforcesBudgets(t *testing.T) { + t.Parallel() // Hot budget 30, entries are 20 each. sm := newTestSpatialMemory( 30, 1000, 1000, @@ -549,6 +571,7 @@ func TestCompactEnforcesBudgets(t *testing.T) { } func TestCompactDemotesWarmAndEnforcesBudget(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 30, 1000, withWarmDemoteAfter(10*time.Millisecond), @@ -581,6 +604,7 @@ func TestCompactDemotesWarmAndEnforcesBudget(t *testing.T) { // --------------------------------------------------------------------------- func TestConcurrentAddAccessCompact(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(10000, 10000, 10000) const numGoroutines = 50 @@ -661,6 +685,7 @@ func TestConcurrentAddAccessCompact(t *testing.T) { } func TestConcurrentTierStats(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) // Pre-populate. @@ -686,6 +711,7 @@ func TestConcurrentTierStats(t *testing.T) { } func TestConcurrentAddSameID(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) var wg sync.WaitGroup @@ -714,6 +740,7 @@ func TestConcurrentAddSameID(t *testing.T) { // --------------------------------------------------------------------------- func TestEmptyMemoryAccess(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) _, ok := sm.Access("anything") if ok { @@ -722,6 +749,7 @@ func TestEmptyMemoryAccess(t *testing.T) { } func TestEmptyMemoryRemove(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) ok := sm.Remove("anything") if ok { @@ -730,12 +758,14 @@ func TestEmptyMemoryRemove(t *testing.T) { } func TestEmptyMemoryCompact(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) sm.Compact() // Should not panic. } func TestSingleEntryFullLifecycle(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(3), @@ -786,6 +816,7 @@ func TestSingleEntryFullLifecycle(t *testing.T) { } func TestAllEntriesSameTier(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) // All entries stay in Cold (no access). @@ -809,6 +840,7 @@ func TestAllEntriesSameTier(t *testing.T) { } func TestRemoveExistingAndNonExisting(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) sm.Add(MemoryEntry{ID: "exists", Content: "c", TokenCount: 1}) @@ -824,6 +856,7 @@ func TestRemoveExistingAndNonExisting(t *testing.T) { } func TestAddWithZeroTokenCount(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(100, 100, 100) sm.Add(MemoryEntry{ID: "zero", Content: "zero", TokenCount: 0}) @@ -837,6 +870,7 @@ func TestAddWithZeroTokenCount(t *testing.T) { } func TestLargeBudgetDoesNotDemote(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000000, 1000000, 1000000) for i := 0; i < 100; i++ { @@ -857,6 +891,7 @@ func TestLargeBudgetDoesNotDemote(t *testing.T) { } func TestTableDrivenPromotionSequence(t *testing.T) { + t.Parallel() tests := []struct { name string accesses int @@ -909,6 +944,7 @@ func TestTableDrivenPromotionSequence(t *testing.T) { } func TestTableDrivenBudgetEnforcement(t *testing.T) { + t.Parallel() tests := []struct { name string hotBudget int @@ -953,6 +989,7 @@ func TestTableDrivenBudgetEnforcement(t *testing.T) { } func TestAccessUpdatesLastAccessedTime(t *testing.T) { + t.Parallel() sm := NewSpatialMemory(1000, 1000, 1000) sm.Add(MemoryEntry{ID: "e1", Content: "c", TokenCount: 5}) @@ -969,6 +1006,7 @@ func TestAccessUpdatesLastAccessedTime(t *testing.T) { } func TestPromoteAlreadyHotIsNoop(t *testing.T) { + t.Parallel() sm := newTestSpatialMemory( 1000, 1000, 1000, withHotThreshold(2), diff --git a/temporal/backbone_test.go b/temporal/backbone_test.go index e7811ce..3292b45 100644 --- a/temporal/backbone_test.go +++ b/temporal/backbone_test.go @@ -40,6 +40,7 @@ func createNode(t *testing.T, store storage.Storage, project string) *storage.No } func TestNew(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) if b == nil { @@ -48,6 +49,7 @@ func TestNew(t *testing.T) { } func TestLink_FirstNode(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -72,6 +74,7 @@ func TestLink_FirstNode(t *testing.T) { } func TestLink_ChainCreatesEdges(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -116,6 +119,7 @@ func TestLink_ChainCreatesEdges(t *testing.T) { } func TestLink_IndependentProjects(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -149,6 +153,7 @@ func TestLink_IndependentProjects(t *testing.T) { } func TestLink_CancelledContext(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx, cancel := context.WithCancel(context.Background()) @@ -161,6 +166,7 @@ func TestLink_CancelledContext(t *testing.T) { } func TestTimeline_Forward(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -187,6 +193,7 @@ func TestTimeline_Forward(t *testing.T) { } func TestTimeline_Backward(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -212,6 +219,7 @@ func TestTimeline_Backward(t *testing.T) { } func TestTimeline_NonexistentNode(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() @@ -226,6 +234,7 @@ func TestTimeline_NonexistentNode(t *testing.T) { } func TestTimeline_DefaultLimit(t *testing.T) { + t.Parallel() store := setupStore(t) b := New(store) ctx := context.Background() diff --git a/utils/utils_test.go b/utils/utils_test.go index cd5d8ca..614642e 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -3,6 +3,7 @@ package utils import "testing" func TestShortID(t *testing.T) { + t.Parallel() tests := []struct { input string expect string @@ -15,9 +16,13 @@ func TestShortID(t *testing.T) { {"123456789", "12345678"}, } for _, tt := range tests { - got := ShortID(tt.input) - if got != tt.expect { - t.Errorf("ShortID(%q) = %q, want %q", tt.input, got, tt.expect) - } + tt := tt + t.Run(tt.input, func(t *testing.T) { + t.Parallel() + got := ShortID(tt.input) + if got != tt.expect { + t.Errorf("ShortID(%q) = %q, want %q", tt.input, got, tt.expect) + } + }) } } diff --git a/yaad_test.go b/yaad_test.go index 0f4d7c2..4ab111a 100644 --- a/yaad_test.go +++ b/yaad_test.go @@ -23,6 +23,7 @@ import ( // --- Full Hawk Session Lifecycle --- func TestHawkFullSessionLifecycle(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -77,6 +78,7 @@ func TestHawkFullSessionLifecycle(t *testing.T) { } func TestHawkSessionRecap(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -119,6 +121,7 @@ func TestHawkSessionRecap(t *testing.T) { // --- Auto-Decay on Session Start --- func TestAutoDecayOnSessionStart(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -151,6 +154,7 @@ func TestAutoDecayOnSessionStart(t *testing.T) { // --- Relevance Filter --- func TestRelevanceFilterScoring(t *testing.T) { + t.Parallel() cases := []struct { tool, input, output, err string shouldCapture bool @@ -180,6 +184,7 @@ func TestRelevanceFilterScoring(t *testing.T) { } func TestRelevanceBoostSignals(t *testing.T) { + t.Parallel() // Decision signals should boost score score := hooks.ScoreRelevance("Bash", "decided to use NATS instead of Redis", "ok", "") if score < 0.5 { @@ -196,6 +201,7 @@ func TestRelevanceBoostSignals(t *testing.T) { // --- Keyed Upsert --- func TestKeyedUpsert(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -236,6 +242,7 @@ func TestKeyedUpsert(t *testing.T) { // --- Pinned Nodes in Context --- func TestPinnedNodesAlwaysInContext(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -274,6 +281,7 @@ func TestPinnedNodesAlwaysInContext(t *testing.T) { } func TestPinToggle(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -302,6 +310,7 @@ func TestPinToggle(t *testing.T) { // --- Skills --- func TestSkillStoreAndReplay(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -350,6 +359,7 @@ func TestSkillStoreAndReplay(t *testing.T) { // --- Stale Detection --- func TestStaleDetectionNoGit(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -368,6 +378,7 @@ func TestStaleDetectionNoGit(t *testing.T) { // --- Config Loading --- func TestConfigLoadDefaults(t *testing.T) { + t.Parallel() cfg := config.Default() if cfg.Server.Port != 3456 { t.Errorf("expected port 3456, got %d", cfg.Server.Port) @@ -384,6 +395,7 @@ func TestConfigLoadDefaults(t *testing.T) { } func TestConfigLoadFromFile(t *testing.T) { + t.Parallel() dir := t.TempDir() yaadDir := filepath.Join(dir, ".yaad") _ = os.MkdirAll(yaadDir, 0o755) @@ -421,6 +433,7 @@ default_limit = 20 // --- Engine DecayConfig Integration --- func TestEngineDecayConfigUsed(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -455,6 +468,7 @@ func TestEngineDecayConfigUsed(t *testing.T) { // --- Feedback Actions --- func TestFeedbackApproveEditDiscard(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -503,6 +517,7 @@ func TestFeedbackApproveEditDiscard(t *testing.T) { // --- Mental Model --- func TestMentalModelGeneration(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -535,6 +550,7 @@ func TestMentalModelGeneration(t *testing.T) { // --- Proactive Context --- func TestProactiveContextPrediction(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -565,6 +581,7 @@ func TestProactiveContextPrediction(t *testing.T) { // --- Token Budget --- func TestTokenBudgetEnforcement(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -597,6 +614,7 @@ func TestTokenBudgetEnforcement(t *testing.T) { // --- Entity Extraction --- func TestEntityExtraction(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -626,6 +644,7 @@ func TestEntityExtraction(t *testing.T) { // --- Self-Linking --- func TestSelfLinkRelatedNodes(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -658,6 +677,7 @@ func TestSelfLinkRelatedNodes(t *testing.T) { // --- Concurrent Access Safety --- func TestConcurrentHawkOperations(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -703,6 +723,7 @@ func TestConcurrentHawkOperations(t *testing.T) { // --- Edge Cases --- func TestRememberMaxContentLength(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -718,6 +739,7 @@ func TestRememberMaxContentLength(t *testing.T) { } func TestRememberInvalidType(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -732,6 +754,7 @@ func TestRememberInvalidType(t *testing.T) { } func TestRememberEmptyContentRejected(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -746,6 +769,7 @@ func TestRememberEmptyContentRejected(t *testing.T) { } func TestForgetPreservesVersion(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -764,6 +788,7 @@ func TestForgetPreservesVersion(t *testing.T) { } func TestRollback(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -791,6 +816,7 @@ func TestRollback(t *testing.T) { // --- Compaction --- func TestCompactionMergesLowConfidence(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() @@ -819,6 +845,7 @@ func TestCompactionMergesLowConfidence(t *testing.T) { // --- Context Formatting (Tiered Output) --- func TestContextFormattingTiered(t *testing.T) { + t.Parallel() eng, cleanup := setup(t) defer cleanup() From 4b3ad1bd753169674e9ec2f92f76ec319b14dcc4 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Fri, 26 Jun 2026 06:35:14 +0530 Subject: [PATCH 2/2] chore: remove dependabot.yml --- .github/dependabot.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 1b614bb..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 -updates: - - package-ecosystem: gomod - directory: / - schedule: - interval: weekly - groups: - go-deps: - patterns: ["*"] - - package-ecosystem: github-actions - directory: / - schedule: - interval: weekly - groups: - actions: - patterns: ["*"]