From a35e76cb36bd1db9ce92e436c796170cedd5f3d6 Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 9 Feb 2026 17:38:21 -0700 Subject: [PATCH] Step 140: constructive coding tests --- PROGRESS.md | 3 +- editor/CMakeLists.txt | 4 ++ editor/tests/step140_test.cpp | 107 ++++++++++++++++++++++++++++++++++ sprint5_plan.md | 2 +- 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 editor/tests/step140_test.cpp diff --git a/PROGRESS.md b/PROGRESS.md index 912b3af..1639075 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -382,7 +382,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi ## What's Next -Sprint 5 in progress. Step 139 (library compatibility matrix) done. Next: Step 140 (constructive coding tests). +Sprint 5 in progress. Step 140 (constructive coding tests) done. Next: Step 141 (Emacs daemon with user config). --- @@ -485,5 +485,6 @@ Sprint 5 in progress. Step 139 (library compatibility matrix) done. Next: Step 1 | 2026-02-09 | Codex | Step 137: Composition builder panel with pipeline generation and code insertion. 4/4 tests pass. | | 2026-02-09 | Codex | Step 138: Type-aware C++ generation via library call mappings. 2/2 tests pass. | | 2026-02-09 | Codex | Step 139: Library compatibility matrix with default mappings. 3/3 tests pass. | +| 2026-02-09 | Codex | Step 140: Constructive coding integration tests covering imports, policy modes, composition, and type-aware generation. 7/7 tests pass. | | 2026-02-09 | Codex | Added FEATURE_REQUESTS.md to track security vulnerability awareness and semantic library annotations for future sprints. | | 2026-02-09 | Codex | Added LLM tooling + MCP bridge feature request to FEATURE_REQUESTS.md. | diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index c86208e..fbe5b18 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -774,6 +774,10 @@ add_executable(step139_test tests/step139_test.cpp) target_include_directories(step139_test PRIVATE src) target_link_libraries(step139_test PRIVATE nlohmann_json::nlohmann_json) +add_executable(step140_test tests/step140_test.cpp) +target_include_directories(step140_test PRIVATE src) +target_link_libraries(step140_test PRIVATE nlohmann_json::nlohmann_json) + find_package(SDL2 CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(glad CONFIG REQUIRED) diff --git a/editor/tests/step140_test.cpp b/editor/tests/step140_test.cpp new file mode 100644 index 0000000..0361159 --- /dev/null +++ b/editor/tests/step140_test.cpp @@ -0,0 +1,107 @@ +// Step 140 TDD Test: Constructive coding tests (integration-style) +#include "CompletionUtils.h" +#include "PrimitivesRegistry.h" +#include "AgentLibraryPolicy.h" +#include "CompositionBuilder.h" +#include "LibraryCompatibility.h" +#include "ast/CppGenerator.h" +#include "ast/Module.h" +#include "ast/Function.h" +#include "ast/Variable.h" +#include "ast/Expression.h" +#include "ast/ExternalModule.h" +#include "ast/TypeSignature.h" +#include + +static void expect(bool cond, const std::string& name, int& passed, int& failed) { + if (cond) { + std::cout << "Test " << (passed + failed + 1) << " PASS: " << name << "\n"; + ++passed; + } else { + std::cout << "Test " << (passed + failed + 1) << " FAIL: " << name << "\n"; + ++failed; + } +} + +static bool containsLabel(const std::vector& items, + const std::string& label) { + for (const auto& item : items) { + if (item.label == label) return true; + } + return false; +} + +int main() { + int passed = 0; + int failed = 0; + + // 1. Import numpy -> completions prioritize numpy + Module mod("m1", "Module", "python"); + auto* ext = new ExternalModule("ext_numpy", "numpy", "python", "1.0"); + ext->addChild("signatures", new TypeSignature("sig_1", "numpy.array")); + mod.addChild("externalModules", ext); + + PrimitivesRegistry reg; + reg.setRoot(&mod); + reg.setLanguage("python"); + auto funcs = reg.getAvailableFunctions("m1"); + std::vector baseItems = {{"foo", 0, "", "foo", ""}}; + auto built = buildLibraryAwareCompletions(baseItems, funcs, ""); + expect(containsLabel(built.items, "numpy.array"), "imported numpy in completions", passed, failed); + + // 2. Remove import -> primitives shrink + Module mod2("m2", "Module", "python"); + PrimitivesRegistry reg2; + reg2.setRoot(&mod2); + reg2.setLanguage("python"); + auto funcs2 = reg2.getAvailableFunctions("m2"); + auto built2 = buildLibraryAwareCompletions(baseItems, funcs2, ""); + expect(!containsLabel(built2.items, "numpy.array"), "numpy removed from completions", passed, failed); + + // 3. preferImports warns on out-of-library usage but doesn't block + auto* callUnknown = new FunctionCall(); + callUnknown->functionName = "mystery"; + auto policyWarn = checkMutationLibraryPolicy(callUnknown, &mod, true, false); + expect(policyWarn.ok && !policyWarn.warning.empty(), + "preferImports warns but allows", passed, failed); + + // 4. strictMode blocks out-of-library usage + auto policyStrict = checkMutationLibraryPolicy(callUnknown, &mod, true, true); + expect(!policyStrict.ok && !policyStrict.error.empty(), + "strictMode blocks unknown", passed, failed); + delete callUnknown; + + // 5. Cross-language projection mapping (library compatibility) + LibraryCompatibility compat; + compat.loadDefaultMappings(); + auto map = compat.getMappings("numpy", "python"); + bool hasEigen = false; + for (const auto& entry : map) { + if (entry.first == "Eigen" && entry.second == "cpp") hasEigen = true; + } + expect(hasEigen, "numpy->Eigen mapping exists", passed, failed); + + // 6. Composition builder generates correct code + std::vector pipeline = { + {"normalize", "string", "string"}, + {"tokenize", "string", "list"} + }; + std::string comp = buildCompositionFunction(pipeline, "pipe", "input"); + expect(comp.find("return tokenize(normalize(input))") != std::string::npos, + "composition output", passed, failed); + + // 7. Type-aware generation produces mapped type + Module mod3("m3", "Module", "cpp"); + auto* var = new Variable("v1", "arr"); + auto* call = new FunctionCall(); + call->functionName = "numpy.array"; + var->setChild("initializer", call); + mod3.addChild("variables", var); + CppGenerator gen; + std::string out = gen.generate(&mod3); + expect(out.find("std::vector arr") != std::string::npos, + "type-aware mapping in C++", passed, failed); + + std::cout << "\n=== Step 140 Results: " << passed << " passed, " << failed << " failed ===\n"; + return failed == 0 ? 0 : 1; +} diff --git a/sprint5_plan.md b/sprint5_plan.md index b2d124d..55a22ff 100644 --- a/sprint5_plan.md +++ b/sprint5_plan.md @@ -154,7 +154,7 @@ what's already available. configurable JSON mapping file. *New:* `LibraryCompatibility.h` -- [ ] **Step 140: Constructive coding tests** +- [x] **Step 140: Constructive coding tests** End-to-end tests verifying: 1. Import numpy → agent prioritizes numpy/builtin functions in suggestions 2. Remove import → agent's prioritized primitives shrink (but arbitrary code still allowed)