// Step 319: Phase 11e Integration + Sprint Summary (8 tests) // Full workflow annotation pipeline and sprint verification. #include "HeadlessEditorState.h" #include "HeadlessAgentRPCHandler.h" #include "MCPServer.h" #include "SemannoFormat.h" #include #include #include using json = nlohmann::json; static int passed = 0, failed = 0; #define TEST(name) { std::cout << " " << #name << "... "; } #define PASS() { std::cout << "PASS\n"; ++passed; } #define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; } #define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {} static json rpcCall(HeadlessEditorState& state, const std::string& method, const json& params = json::object()) { json req = {{"jsonrpc", "2.0"}, {"id", 1}, {"method", method}}; if (!params.empty()) req["params"] = params; return handleHeadlessAgentRequest(state, req, "test-session"); } // 1. Parse Python → infer annotations across all 8 subjects → verify suggestions void test_infer_all_subjects() { TEST(infer_all_subjects); HeadlessEditorState state; state.defaultLanguage = "python"; state.openBuffer("test", "def pure_fn():\n return 42\n\n" "async def fetch():\n data = await get_data()\n return data\n\n" "def complex():\n" " for i in range(n):\n" " for j in range(m):\n" " process(i, j)\n" " return result\n", "python"); auto* ast = state.activeAST(); CHECK(ast != nullptr, "Has AST"); AnnotationInference inf; auto all = inf.inferAll(ast); CHECK(!all.empty(), "Has suggestions"); // Check annotation types cover multiple subjects std::set types; for (const auto& a : all) types.insert(a.annotationType); // Should have at least exec (async), complexity, pure annotations CHECK(types.size() >= 3, "3+ annotation types, got: " + std::to_string(types.size())); PASS(); } // 2. Create skeleton → add annotated functions → get project model → verify task list void test_skeleton_workflow() { TEST(skeleton_workflow); HeadlessEditorState state; state.agent.defaultRole = AgentRole::Refactor; rpcCall(state, "createSkeleton", {{"name", "webapp"}, {"language", "python"}}); rpcCall(state, "addSkeletonNode", { {"name", "auth_handler"}, {"contextWidth", "file"}, {"automatability", "llm"}, {"priority", "critical"}}); rpcCall(state, "addSkeletonNode", { {"name", "data_validator"}, {"contextWidth", "local"}, {"automatability", "template"}, {"priority", "high"}}); auto resp = rpcCall(state, "getProjectModel"); CHECK(resp.contains("result"), "Has result"); auto& r = resp["result"]; CHECK(r["totalNodes"].get() == 2, "2 nodes"); CHECK(r["tasks"].is_array(), "Has tasks"); CHECK(r["tasks"].size() == 2, "2 tasks"); // Verify task fields auto& t0 = r["tasks"][0]; CHECK(t0.contains("contextWidth"), "Task has contextWidth"); CHECK(t0.contains("automatability"), "Task has automatability"); CHECK(t0.contains("priority"), "Task has priority"); PASS(); } // 3. Infer routing: simple → deterministic, complex → llm void test_routing_inference() { TEST(routing_inference); // Simple getter auto* simpleFn = new Function(); simpleFn->id = "simple_1"; simpleFn->name = "get_value"; auto* ret = new Return(); ret->id = "ret_1"; simpleFn->addChild("body", ret); // Complex function with nested loops auto* complexFn = new Function(); complexFn->id = "complex_1"; complexFn->name = "analyze"; auto* inner = new ForLoop(); inner->id = "inner_1"; auto* fc = new FunctionCall(); fc->id = "fc_1"; fc->functionName = "process"; inner->addChild("body", fc); auto* outer = new ForLoop(); outer->id = "outer_1"; outer->addChild("body", inner); complexFn->addChild("body", outer); auto* mod = new Module("root", "test", "python"); mod->addChild("functions", simpleFn); mod->addChild("functions", complexFn); AnnotationInference inf; auto simpleRouting = inf.inferRoutingAnnotations(simpleFn); auto complexRouting = inf.inferRoutingAnnotations(complexFn); bool simpleDet = false, complexLlm = false; for (const auto& r : simpleRouting) if (r.annotationType == "AutomatabilityAnnotation" && r.value == "deterministic") simpleDet = true; for (const auto& r : complexRouting) if (r.annotationType == "AutomatabilityAnnotation" && r.value == "llm") complexLlm = true; CHECK(simpleDet, "Simple → deterministic"); CHECK(complexLlm, "Complex → llm"); delete mod; PASS(); } // 4. Skeleton task list respects dependency ordering from @Priority.blockedBy void test_dependency_ordering() { TEST(dependency_ordering); HeadlessEditorState state; state.agent.defaultRole = AgentRole::Refactor; rpcCall(state, "createSkeleton", {{"name", "pipeline"}, {"language", "python"}}); rpcCall(state, "addSkeletonNode", { {"name", "step_a"}, {"priority", "high"}}); rpcCall(state, "addSkeletonNode", { {"name", "step_b"}, {"priority", "medium"}, {"blockedBy", json::array({"step_a"})}}); rpcCall(state, "addSkeletonNode", { {"name", "step_c"}, {"priority", "low"}, {"blockedBy", json::array({"step_b"})}}); auto resp = rpcCall(state, "getProjectModel"); auto& tasks = resp["result"]["tasks"]; CHECK(tasks.size() == 3, "3 tasks"); // Find step_b and step_c, verify dependencies bool bHasDep = false, cHasDep = false; for (const auto& t : tasks) { if (t["nodeName"] == "step_b" && t.contains("dependencies")) bHasDep = t["dependencies"].size() == 1; if (t["nodeName"] == "step_c" && t.contains("dependencies")) cHasDep = t["dependencies"].size() == 1; } CHECK(bHasDep, "step_b blocked by step_a"); CHECK(cHasDep, "step_c blocked by step_b"); PASS(); } // 5. MCP tools/list returns 42+ tools with 4 workflow tools present void test_mcp_tool_inventory() { TEST(mcp_tool_inventory); MCPServer server; json initReq = {{"jsonrpc", "2.0"}, {"id", 1}, {"method", "initialize"}, {"params", {{"protocolVersion", "2024-11-05"}, {"capabilities", json::object()}, {"clientInfo", {{"name", "test"}}}}}}; server.handleRequest(initReq); json listReq = {{"jsonrpc", "2.0"}, {"id", 2}, {"method", "tools/list"}}; json resp = server.handleRequest(listReq); auto& tools = resp["result"]["tools"]; int count = (int)tools.size(); CHECK(count >= 42, "42+ tools, got: " + std::to_string(count)); // Verify all 4 workflow tools std::set names; for (const auto& t : tools) names.insert(t["name"].get()); CHECK(names.count("whetstone_create_skeleton"), "Has create_skeleton"); CHECK(names.count("whetstone_add_skeleton_node"), "Has add_skeleton_node"); CHECK(names.count("whetstone_get_project_model"), "Has get_project_model"); CHECK(names.count("whetstone_infer_annotations"), "Has infer_annotations"); PASS(); } // 6. Sprint totals: 10 parsers, 10 generators, 42+ MCP tools void test_sprint_totals() { TEST(sprint_totals); // 10 parsers: python, cpp, rust, go, java, js, ts, elisp, kotlin, csharp Pipeline pipeline; std::vector langs = { "python", "cpp", "rust", "go", "java", "javascript", "typescript", "elisp", "kotlin", "csharp" }; int parseCount = 0; for (const auto& lang : langs) { std::vector diags; auto mod = pipeline.parse("x = 1", lang, diags); if (mod) parseCount++; } CHECK(parseCount == 10, "10 parsers, got: " + std::to_string(parseCount)); // 10 generators (same languages) int genCount = 0; for (const auto& lang : langs) { auto mod = std::make_unique("root", "test", lang); std::string code = pipeline.generate(mod.get(), lang); genCount++; // generate always returns something } CHECK(genCount == 10, "10 generators"); // 42+ MCP tools MCPServer server; CHECK((int)server.getTools().size() >= 42, "42+ MCP tools, got: " + std::to_string(server.getTools().size())); // Verify no annotation types dropped — check Subject 9 types exist auto* cw = new ContextWidthAnnotation(); auto* rv = new ReviewAnnotation(); auto* aa = new AutomatabilityAnnotation(); auto* pa = new PriorityAnnotation(); auto* is = new ImplementationStatusAnnotation(); CHECK(cw->conceptType == "ContextWidthAnnotation", "ContextWidth type"); CHECK(rv->conceptType == "ReviewAnnotation", "Review type"); CHECK(aa->conceptType == "AutomatabilityAnnotation", "Automatability type"); CHECK(pa->conceptType == "PriorityAnnotation", "Priority type"); CHECK(is->conceptType == "ImplementationStatusAnnotation", "ImplStatus type"); delete cw; delete rv; delete aa; delete pa; delete is; PASS(); } // 7. Inference + routing + skeleton combined void test_combined_workflow() { TEST(combined_workflow); HeadlessEditorState state; state.agent.defaultRole = AgentRole::Refactor; // Create skeleton rpcCall(state, "createSkeleton", {{"name", "myservice"}, {"language", "python"}}); rpcCall(state, "addSkeletonNode", { {"name", "handle_request"}, {"contextWidth", "file"}, {"automatability", "llm"}, {"priority", "critical"}}); rpcCall(state, "addSkeletonNode", { {"name", "validate_input"}, {"contextWidth", "local"}, {"automatability", "deterministic"}, {"priority", "high"}}); // Get project model auto modelResp = rpcCall(state, "getProjectModel"); CHECK(modelResp.contains("result"), "Has project model"); CHECK(modelResp["result"]["totalNodes"].get() == 2, "2 nodes"); // Now open a different buffer with actual code and infer state.openBuffer("impl", "def handle_request(req):\n" " validated = validate_input(req)\n" " result = process(validated)\n" " return result\n", "python"); state.setActiveBuffer("impl"); auto inferResp = rpcCall(state, "inferAnnotations"); CHECK(inferResp.contains("result"), "Has infer result"); CHECK(inferResp["result"]["suggestions"].is_array(), "Has suggestions"); // Infer routing on parsed functions auto* ast = state.activeAST(); CHECK(ast != nullptr, "Has AST"); auto fns = ast->getChildren("functions"); if (!fns.empty()) { AnnotationInference inf; auto routing = inf.inferRoutingAnnotations(fns[0]); CHECK(!routing.empty(), "Has routing annotations"); std::string worker = inf.suggestWorkerType(routing); CHECK(!worker.empty(), "Has worker suggestion"); } PASS(); } // 8. Semanno roundtrip includes workflow annotations (Subject 9) void test_semanno_workflow_roundtrip() { TEST(semanno_workflow_roundtrip); auto* fn = new Function(); fn->id = "fn_rt_1"; fn->name = "routed_function"; // Add Subject 9 annotations auto* cw = new ContextWidthAnnotation(); cw->id = "cw_rt_1"; cw->width = "file"; fn->addChild("annotations", cw); auto* aa = new AutomatabilityAnnotation(); aa->id = "aa_rt_1"; aa->strategy = "llm"; aa->confidence = 0.85; fn->addChild("annotations", aa); auto* pa = new PriorityAnnotation(); pa->id = "pa_rt_1"; pa->level = "critical"; fn->addChild("annotations", pa); auto* rv = new ReviewAnnotation(); rv->id = "rv_rt_1"; rv->required = true; rv->reason = "production code"; fn->addChild("annotations", rv); auto* mod = new Module("root", "test", "python"); mod->addChild("functions", fn); // Emit to Semanno format SemannoEmitter emitter; std::string semanno = emitter.emit(mod); // Verify Subject 9 annotations appear in output CHECK(semanno.find("contextwidth") != std::string::npos || semanno.find("ContextWidth") != std::string::npos, "Semanno contains contextwidth"); CHECK(semanno.find("automatability") != std::string::npos || semanno.find("Automatability") != std::string::npos, "Semanno contains automatability"); CHECK(semanno.find("priority") != std::string::npos || semanno.find("Priority") != std::string::npos, "Semanno contains priority"); CHECK(semanno.find("review") != std::string::npos || semanno.find("Review") != std::string::npos, "Semanno contains review"); // Verify serialization roundtrip json astJson = toJson(mod); std::string serialized = astJson.dump(); CHECK(serialized.find("ContextWidthAnnotation") != std::string::npos, "JSON serialization includes ContextWidth"); CHECK(serialized.find("AutomatabilityAnnotation") != std::string::npos, "JSON serialization includes Automatability"); delete mod; PASS(); } int main() { std::cout << "Step 319: Phase 11e Integration + Sprint Summary\n"; try { test_infer_all_subjects(); test_skeleton_workflow(); test_routing_inference(); test_dependency_ordering(); test_mcp_tool_inventory(); test_sprint_totals(); test_combined_workflow(); test_semanno_workflow_roundtrip(); } catch (const std::exception& e) { std::cout << "\nFATAL: " << e.what() << "\n"; return 1; } std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n"; return failed > 0 ? 1 : 0; }