From b1551b240c2d17a47b027201d3a3129450dbebb5 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 14 Apr 2026 19:05:57 +0000 Subject: [PATCH] fix(prose): narrow B7 rule to hosted TestKit scope B7 as originally written ("external dependencies faked via ConfigureServices, not stub actors") collapsed two axes from the upstream akka-testing-patterns skill into a single bullet: the service-vs-actor collaborator axis, and the hosted-TestKit-vs-bare- ActorSystem fixture axis. Both distinctions matter. The skill's own Best Practice #4 explicitly endorses TestProbes (which are stub actors) for actor dependencies, and plain non-actor service SUTs with bare ActorSystem fixtures are outside the skill's scope entirely. The collapse produced false positives during the pre-OSS quality audit at DaemonRestartCoordinatorTests.cs:101,166, which tests a non-actor service through an IRequiredActor seam on a bare ActorSystem. Section 6 "Needs Human Review" routing caught them before they hit the main backlog, but the rule text needed fixing. Rewrites B7 to: - only flag stub actors inside hosted TestKit / TestAppBuilderTestKit tests, where the real antipattern lives - explicitly exempt TestProbe and CreateTestProbe usages - explicitly exempt bare ActorSystem fixtures for non-actor SUTs - keep the low-confidence Section 6 routing Also adds a new bullet to AGENTS.md's Continuous Improvement Rule capturing the meta-lesson: compressing a skill into a rule is a retrieval operation, not a memory operation. Open the upstream skill first and preserve the distinctions it draws; rules that collapse orthogonal axes produce false positives that burn trust in the audit. --- .prose/netclaw-quality-audit.prose | 25 ++++++++++++++++++++++--- AGENTS.md | 8 ++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.prose/netclaw-quality-audit.prose b/.prose/netclaw-quality-audit.prose index b508898f7..0fb68cb02 100644 --- a/.prose/netclaw-quality-audit.prose +++ b/.prose/netclaw-quality-audit.prose @@ -187,8 +187,17 @@ parallel (on-fail: "continue"): B4. Async state verified via AwaitAssertAsync or TestProbe acks B5. No .Result / .Wait() in tests B6. Actor tests inherit Akka.Hosting.TestKit, not a custom base - B7. External dependencies faked via ConfigureServices, not - stub actors + B7. Inside hosted Akka.Hosting.TestKit / TestAppBuilderTestKit + tests: SERVICE dependencies of actors are faked via + ConfigureServices; ACTOR collaborators are faked via + TestProbe or a trivial stub actor. Do NOT substitute a + stub actor for a production actor under the same typed + actor key inside a hosted test — that masks DI/wiring + bugs. Bare-ActorSystem fixtures for plain (non-actor) + service SUTs are OUT OF SCOPE for this rule: protocol- + level stubs there are legitimate (see akka-testing- + patterns Best Practice #4: "Use TestProbes for + dependencies"). Regression anchors (EXPECT BASELINED — verify via .slopwatch/baseline.json): B1 — src/Netclaw.Actors.Tests/Memory/SQLiteMemoryStoreTests.cs:263 @@ -208,7 +217,17 @@ parallel (on-fail: "continue"): B5: Grep `\\.Result\\b` and `\\.Wait\\(\\)` in tests. B6: Grep `class\\s+\\w+Tests\\s*:` in tests; report any whose parent is NOT `TestKit` / `TestAppBuilderTestKit`. - B7: `system.ActorOf(.*Stub|Fake|Mock)` patterns (low confidence). + B7: `system.ActorOf(.*Stub|Fake|Mock)` patterns — but ONLY + flag when the enclosing test class inherits `TestKit` / + `TestAppBuilderTestKit` (i.e. a hosted Akka.Hosting test). + Bare `ActorSystem.Create(...)` fixtures are OUT OF SCOPE: + protocol-level stubs on a bare ActorSystem are the + minimum viable fake for a non-actor service SUT whose + only actor collaborator is an `IActorRef` or + `IRequiredActor`. Also exempt `CreateTestProbe(...)` + and `TestProbe` usages entirely (they ARE the upstream + skill's Best Practice #4). Low confidence; route to + Section 6 "Needs Human Review", not the main backlog. Waiver check and 10-per-rule cap apply. """ diff --git a/AGENTS.md b/AGENTS.md index 30bb44586..b41357dc6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -272,3 +272,11 @@ Specialist agents: - If a workflow repeats twice, extract or refine a skill/workflow doc. - Put volatile detail in repo-owned docs, not this constitution. - Keep this file stable and high-signal. +- **Compressing a skill into a rule is a retrieval operation, not a + memory operation.** When distilling a dotnet-skills skill (or any + upstream authority) into an audit rule, review rubric, or one-line + bullet, open the skill first. Preserve the distinctions the skill + draws — not just its headline. Rules that collapse two orthogonal + axes into one sentence produce false positives that burn + trust in the audit. If a rule cannot be written without losing a + distinction the source makes, drop it rather than eliding.