Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo
{
SnapshotInterval = 5,
TitleGenerationInterval = 0,
MemorySidecarsEnabled = false,
}
});
services.AddSingleton<ISystemPromptProvider>(new StaticSystemPromptProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo
{
SnapshotInterval = 5,
TitleGenerationInterval = 0,
MemorySidecarsEnabled = false,
}
});
services.AddSingleton<ISystemPromptProvider>(new StaticSystemPromptProvider(
Expand Down
6 changes: 3 additions & 3 deletions src/Netclaw.Actors.Tests/Memory/MemoryEvalSeedSuiteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ await _store.UpsertDocumentAsync(new SQLiteMemoryDocument(
CreatedAtMs: now,
UpdatedAtMs: now), TestContext.Current.CancellationToken);

var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning());
var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "ops/thread-1",
Query: "router failover",
Expand Down Expand Up @@ -84,7 +84,7 @@ await _store.UpsertDocumentAsync(new SQLiteMemoryDocument(
CreatedAtMs: now,
UpdatedAtMs: now), TestContext.Current.CancellationToken);

var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning());
var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "ops/thread-1",
Query: "token",
Expand Down Expand Up @@ -314,7 +314,7 @@ await _store.UpsertDocumentAsync(new SQLiteMemoryDocument(
UpdatedAtMs: now), TestContext.Current.CancellationToken);
}

var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
var coordinator = new SQLiteMemoryRecallCoordinator(_store, NullLogger<SQLiteMemoryRecallCoordinator>.Instance, sessionTuning: new SessionTuning());
var start = TimeProvider.System.GetTimestamp();
var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "latency/thread-1",
Expand Down
1 change: 0 additions & 1 deletion src/Netclaw.Actors.Tests/Memory/MemoryPolicyGatesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ public void RecallPlanGate_forces_automatic_mode_to_durable_fact_only()
var gate = new RecallPlanGate();
var request = new RecallPlanningRequest(
"slack/thread",
"project:slack",
"automatic",
"What hotel should I stay in there",
["I am speaking at Stir Trek in Ohio"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task Formation_then_auto_recall_surfaces_durable_fact()
var recall = new SQLiteMemoryRecallCoordinator(
_store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
sessionTuning: new SessionTuning());

var result = await recall.RecallAsync(new AutomaticRecallRequest(
"slack/thread-1",
Expand Down Expand Up @@ -122,14 +122,13 @@ public async Task Formation_then_recall_surfaces_travel_origin_and_persists_meta
var recall = new SQLiteMemoryRecallCoordinator(
_store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await recall.RecallAsync(new AutomaticRecallRequest(
"signalr/thread-iah",
"What airport do I usually fly out of?",
["What airport do I usually fly out of?"],
3,
HardScopeOverride: "user:aaron",
ThreadTitle: "Travel preferences"), TestContext.Current.CancellationToken);

Assert.False(result.Degraded);
Expand Down Expand Up @@ -185,14 +184,13 @@ public async Task Formation_then_recall_surfaces_preferred_airline_and_persists_
var recall = new SQLiteMemoryRecallCoordinator(
_store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await recall.RecallAsync(new AutomaticRecallRequest(
"signalr/thread-united",
"What airline do I usually take?",
["What airline do I usually take?"],
3,
HardScopeOverride: "user:aaron",
ThreadTitle: "Travel preferences"), TestContext.Current.CancellationToken);

Assert.False(result.Degraded);
Expand Down Expand Up @@ -256,7 +254,7 @@ await _store.ApplyCurationBatchAsync(
var recall = new SQLiteMemoryRecallCoordinator(
_store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
sessionTuning: new SessionTuning());

var auto = await recall.RecallAsync(new AutomaticRecallRequest(
"slack/thread-2",
Expand Down Expand Up @@ -407,7 +405,7 @@ public async Task Soul_boundary_keeps_project_facts_in_sqlite_memory()
now);

await _store.ApplyCurationBatchAsync("cp-eval-3", accepted, CancellationToken.None);
var items = await _store.SearchByPlanAsync(["deploys", "east-2"], "project:ops", ["durable_fact"], 5, SecurityPolicyDefaults.InferLegacyBoundaryFromDomain("project:ops"), TrustAudience.Public, false, TestContext.Current.CancellationToken);
var items = await _store.SearchAcrossDomainsByPlanAsync(["deploys", "east-2"], ["durable_fact"], 5, SecurityPolicyDefaults.TrustedInstanceBoundary, TrustAudience.Public, false, TestContext.Current.CancellationToken);

Assert.Single(items);
Assert.Equal("Deployment region", items[0].Title);
Expand Down Expand Up @@ -479,7 +477,7 @@ public async Task Eval_reporting_thresholds_meet_smoke_targets_for_current_fixtu
var recall = new SQLiteMemoryRecallCoordinator(
_store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { MemorySidecarsEnabled = true });
sessionTuning: new SessionTuning());

var acceptedFact = proposalGate.Accept(
[
Expand Down
10 changes: 4 additions & 6 deletions src/Netclaw.Actors.Tests/Memory/SQLiteMemoryStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,21 +261,19 @@ await _store.UpsertDocumentAsync(new SQLiteMemoryDocument(
UpdatedAtMs: now,
Audience: TrustAudience.Personal.ToWireValue()), TestContext.Current.CancellationToken);

var publicResults = await _store.SearchByPlanAsync(
var publicResults = await _store.SearchAcrossDomainsByPlanAsync(
["visible"],
"project:test",
[MemoryClass.DurableFact.ToWireValue()],
10,
SecurityPolicyDefaults.InferLegacyBoundaryFromDomain("project:test"),
SecurityPolicyDefaults.TrustedInstanceBoundary,
TrustAudience.Public,
false, TestContext.Current.CancellationToken);

var personalResults = await _store.SearchByPlanAsync(
var personalResults = await _store.SearchAcrossDomainsByPlanAsync(
["visible"],
"project:test",
[MemoryClass.DurableFact.ToWireValue()],
10,
SecurityPolicyDefaults.InferLegacyBoundaryFromDomain("project:test"),
SecurityPolicyDefaults.TrustedInstanceBoundary,
TrustAudience.Personal,
false, TestContext.Current.CancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo
KeepRecentToolResults = 1,
KeepRecentMessages = 0,
TitleGenerationInterval = 0,
MemorySidecarsEnabled = false,
}
});
services.AddSingleton<ISystemPromptProvider>(new StaticSystemPromptProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ namespace Netclaw.Actors.Tests.Sessions;
public sealed class DeterministicCandidateSelectorTests
{
private static DeterministicRetrievalRequestPlan MakePlan(
string hardScope = "project:d0ac6ckbk5k",
IReadOnlyList<string>? lexicalTerms = null,
IReadOnlyList<string>? anchorHints = null,
IReadOnlyList<string>? facets = null,
IReadOnlyList<string>? softScopes = null) => new(
HardScope: hardScope,
SoftScopes: softScopes ?? [],
RetrievalMode: DeterministicRetrievalMode.Ranked,
LexicalTerms: lexicalTerms ?? [],
Expand Down Expand Up @@ -99,7 +97,6 @@ public void Domain_is_not_a_scoring_signal()
// must score identically. Tracked in #584.
var selector = new DeterministicCandidateSelector();
var plan = MakePlan(
hardScope: "project:d0ac6ckbk5k",
lexicalTerms: ["petabridge"]);

var sameDomain = MakeItem("doc-same", "Company: Petabridge", "Petabridge builds Akka.NET.", domain: "project:d0ac6ckbk5k");
Expand All @@ -116,7 +113,6 @@ public void Cross_domain_candidate_not_excluded()
{
var selector = new DeterministicCandidateSelector();
var plan = MakePlan(
hardScope: "project:d0ac6ckbk5k",
lexicalTerms: ["petabridge"]);

var crossDomain = MakeItem("doc-cross", "Company: Petabridge", "Petabridge builds Akka.NET.", domain: "project:signalr");
Expand Down Expand Up @@ -155,8 +151,7 @@ public void Score_geometry_stronger_matches_outrank_weaker_matches()
{
var selector = new DeterministicCandidateSelector();
var plan = MakePlan(
lexicalTerms: ["akka", "stream", "backpressure", "demand"],
hardScope: "project:d0ac6ckbk5k");
lexicalTerms: ["akka", "stream", "backpressure", "demand"]);

var weak = MakeItem(
"doc-weak",
Expand Down Expand Up @@ -196,8 +191,7 @@ public void Score_geometry_facet_match_adds_meaningful_weight()
var selector = new DeterministicCandidateSelector();
var plan = MakePlan(
lexicalTerms: ["stream"],
facets: ["akka-streams"],
hardScope: "project:other");
facets: ["akka-streams"]);

var withoutFacet = MakeItem(
"doc-no-facet",
Expand Down Expand Up @@ -237,8 +231,7 @@ public void Score_geometry_anchor_match_adds_meaningful_weight()
var selector = new DeterministicCandidateSelector();
var plan = MakePlan(
lexicalTerms: ["stream"],
anchorHints: ["Akka Stream Backpressure"],
hardScope: "project:other");
anchorHints: ["Akka Stream Backpressure"]);

var noAnchor = MakeItem(
"doc-no-anchor",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ public void Planner_uses_runtime_hard_scope_and_bundle_mode_for_trip_prompt()
Query: "I'm speaking at Stir Trek 2026 - I fly out of IAH. What's the best flight / hotel combination for me?",
RecentUserMessages: ["I'm speaking at Stir Trek 2026 - I fly out of IAH. What's the best flight / hotel combination for me?"],
MaxItems: 3,
HardScopeOverride: "user:aaron",
ThreadTitle: "Stir Trek 2026 travel planning"));

Assert.Equal("user:aaron", plan.HardScope);
Assert.Equal(DeterministicRetrievalMode.Bundle, plan.RetrievalMode);
Assert.Contains("travel_profile", plan.Facets);
Assert.Contains("trip_planning", plan.Facets);
Expand All @@ -36,28 +34,13 @@ public void Planner_prefers_named_entity_soft_scope_for_project_prompt()
Query: "What's the pricing model for TextForge?",
RecentUserMessages: ["What's the pricing model for TextForge?"],
MaxItems: 3,
HardScopeOverride: "user:aaron",
ThreadTitle: "General DM"));

Assert.Equal("user:aaron", plan.HardScope);
Assert.Equal(DeterministicRetrievalMode.Ranked, plan.RetrievalMode);
Assert.Contains("project_fact", plan.Facets);
Assert.Contains(plan.AnchorHints, x => x.Contains("TextForge", StringComparison.OrdinalIgnoreCase) || x.Contains("textforge", StringComparison.OrdinalIgnoreCase));
}

[Fact]
public void Planner_does_not_turn_transport_session_prefix_into_project_scope()
{
var planner = new DeterministicRetrievalRequestPlanner();
var plan = planner.Plan(new AutomaticRecallRequest(
SessionId: "signalr/thread-transport",
Query: "what is TextForge",
RecentUserMessages: ["what is TextForge"],
MaxItems: 3));

Assert.Equal(SecurityPolicyDefaults.DefaultMemoryDomain, plan.HardScope);
}

[Fact]
public async Task Coordinator_keeps_stage_empty_when_deterministic_planning_succeeds_but_sidecars_are_disabled()
{
Expand All @@ -69,14 +52,13 @@ public async Task Coordinator_keeps_stage_empty_when_deterministic_planning_succ
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "signalr/thread-3",
Query: "What's the pricing model for TextForge?",
RecentUserMessages: ["What's the pricing model for TextForge?"],
MaxItems: 3,
HardScopeOverride: "user:aaron",
ThreadTitle: "General DM"), TestContext.Current.CancellationToken);

Assert.False(result.Degraded);
Expand Down Expand Up @@ -116,14 +98,13 @@ await store.UpsertDocumentAsync(new SQLiteMemoryDocument(
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "signalr/thread-4",
Query: "What's the pricing model for TextForge?",
RecentUserMessages: ["What's the pricing model for TextForge?"],
MaxItems: 3,
HardScopeOverride: "user:aaron",
ThreadTitle: "Product planning"), TestContext.Current.CancellationToken);

Assert.False(result.Degraded);
Expand Down Expand Up @@ -163,14 +144,13 @@ await store.UpsertDocumentAsync(new SQLiteMemoryDocument(
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "signalr/thread-score",
Query: "What's the pricing model for TextForge?",
RecentUserMessages: ["What's the pricing model for TextForge?"],
MaxItems: 3,
HardScopeOverride: "user:aaron",
ThreadTitle: "Product planning"), TestContext.Current.CancellationToken);

var item = Assert.Single(result.Items, x => x.Id == "doc-textforge-pricing-score");
Expand All @@ -190,8 +170,7 @@ public void Planner_caps_lexical_terms_for_long_messages()
SessionId: "signalr/thread-long",
Query: longMessage,
RecentUserMessages: [longMessage],
MaxItems: 3,
HardScopeOverride: "user:aaron"));
MaxItems: 3));

Assert.True(plan.LexicalTerms.Count <= 12,
$"Expected at most 12 lexical terms but got {plan.LexicalTerms.Count}: [{string.Join(", ", plan.LexicalTerms)}]");
Expand Down Expand Up @@ -244,7 +223,7 @@ await store.UpsertDocumentAsync(new SQLiteMemoryDocument(
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "D0AC6CKBK5K/1774371415.126439",
Expand Down Expand Up @@ -290,7 +269,7 @@ await store.UpsertDocumentAsync(new SQLiteMemoryDocument(
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

// Query from a different domain (project:d0ac6ckbk5k — Slack DM)
var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
Expand Down Expand Up @@ -336,7 +315,7 @@ await store.UpsertDocumentAsync(new SQLiteMemoryDocument(
var coordinator = new SQLiteMemoryRecallCoordinator(
store,
NullLogger<SQLiteMemoryRecallCoordinator>.Instance,
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true, MemorySidecarsEnabled = false });
sessionTuning: new SessionTuning { DeterministicRetrievalEnabled = true });

var result = await coordinator.RecallAsync(new AutomaticRecallRequest(
SessionId: "signalr/thread-5",
Expand Down
1 change: 0 additions & 1 deletion src/Netclaw.Actors.Tests/Sessions/ErrorCorrelationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo
{
SnapshotInterval = 5,
TitleGenerationInterval = 0,
MemorySidecarsEnabled = false,
}
});
services.AddSingleton<ISystemPromptProvider>(new StaticSystemPromptProvider("You are a test assistant."));
Expand Down
Loading
Loading