From 379579940c0a2e9936ebf8acdb28c6a165814fd1 Mon Sep 17 00:00:00 2001 From: "d3mlabs-ai-flow[bot]" <305891656+d3mlabs-ai-flow[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:36:39 -0400 Subject: [PATCH] ai-flow /build: capture learnings from the build pass Co-authored-by: JPDuchesne <2636122+JPDuchesne@users.noreply.github.com> --- .cursor/rules/learnings-index.mdc | 4 ++ .../learnings/nested-test-fakes/SKILL.md | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 .cursor/skills/learnings/nested-test-fakes/SKILL.md diff --git a/.cursor/rules/learnings-index.mdc b/.cursor/rules/learnings-index.mdc index 6ff67a0..e338036 100644 --- a/.cursor/rules/learnings-index.mdc +++ b/.cursor/rules/learnings-index.mdc @@ -24,6 +24,10 @@ propose a retirement, a consolidation, or a glob-scoped sub-index split. class they silently assert nothing. → .agents/skills/gem-rspock--rspock/ (ships in the rspock gem; linked by `dev up` / `dev install-deps`) +- [testing/nested-test-fakes] Test fake classes nest inside the test class + they serve — never at file top level with prefixed names and + `unless defined?` guards. + → .cursor/skills/learnings/nested-test-fakes/ ## process diff --git a/.cursor/skills/learnings/nested-test-fakes/SKILL.md b/.cursor/skills/learnings/nested-test-fakes/SKILL.md new file mode 100644 index 0000000..615b932 --- /dev/null +++ b/.cursor/skills/learnings/nested-test-fakes/SKILL.md @@ -0,0 +1,40 @@ +--- +name: nested-test-fakes +description: >- + MUST be used when a test needs a fake or stub class (e.g. a + Dev::BuiltinCommand fake): nest it inside the test class it serves, + never at file top level. +--- + +# Test fakes nest inside their test class + +A fake class belongs inside the test class that uses it: the constant is +namespaced (`Dev::FooTest::FakeBuiltin`), so cross-file collisions are +impossible and the `unless defined?` guard plus unique name prefixes +(`ServiceFakeBuiltin`, `DispatchFakeBuiltin`, …) become dead weight. +Nesting inside an rspock `transform!`-ed class is safe — the +transformation only rewrites `test "..." do` blocks (plain nested classes +merely gain a harmless `extend RSpock::Declarative`). + +Wrong — top-level fake with prefix and guard: + + class ServiceFakeBuiltin < Dev::BuiltinCommand + def desc = "a builtin" + def call(args:, context:); end + end unless defined?(ServiceFakeBuiltin) + + transform!(RSpock::AST::Transformation) + class Dev::CommandServiceTest < Minitest::Test + +Right — nested, short name, no guard: + + transform!(RSpock::AST::Transformation) + class Dev::CommandServiceTest < Minitest::Test + class FakeBuiltin < Dev::BuiltinCommand + def desc = "a builtin" + def call(args:, context:); end + end + +learned-from: dev#122 review (threads on builtin_executor_test.rb and +overridden_executor_test.rb: "move the fake to be inside the test class") +date: 2026-08-18