// Step 393: Phase 15c Integration + Sprint 15 Summary (8 tests) #include #include #include #include "RoutingRules.h" #include "CostEstimator.h" #include "WorkflowTemplates.h" #include "DependencyGraph.h" #include "HeadlessEditorState.h" #include "HeadlessAgentRPCHandler.h" #include "WorkflowOrchestrator.h" #include "WorkflowProtocol.h" #include "EventStream.h" static WorkItem makeItem(const std::string& id, const std::string& name = "doWork", const std::string& workerType = "", const std::string& contextWidth = "local", const std::string& priority = "medium", const std::vector& deps = {}) { WorkItem item; item.id = id; item.nodeId = id + "_node"; item.nodeName = name; item.nodeType = "Function"; item.bufferId = "main.py"; item.workerType = workerType; item.contextWidth = contextWidth; item.priority = priority; item.status = WI_READY; item.createdAt = workItemTimestamp(); item.dependencies = deps; return item; } int main() { int passed = 0; // Test 1: Custom routing rules override default to use template for simple functions { RulesEngine engine; // Add custom rule: all local functions → template RoutingRule custom; custom.name = "local-template"; custom.priority = 1; custom.conditions.push_back({"contextWidth", "", "==", "local"}); custom.action.workerType = "template"; engine.addRule(custom); auto item = makeItem("t1", "processData", "", "local"); auto decision = engine.evaluate(item); assert(decision.workerType == "template"); assert(decision.reasoning.find("local-template") != std::string::npos); std::cout << "PASS: test 1 — custom routing rules override\n"; passed++; } // Test 2: Cost estimation for 10-function workflow with optimization suggestions { WorkflowState wf("test"); // 3 getters in project context (should suggest template) wf.queue.enqueue(makeItem("t1", "getName", "", "project")); wf.queue.enqueue(makeItem("t2", "getValue", "", "project")); wf.queue.enqueue(makeItem("t3", "isActive", "", "project")); // 7 normal functions for (int i = 4; i <= 10; ++i) { wf.queue.enqueue(makeItem("t" + std::to_string(i), "func" + std::to_string(i), "", "local")); } RoutingEngine routing; CostEstimator estimator; auto est = estimator.estimate(wf, routing); assert(est.totalContextTokens > 0); assert(est.totalOutputTokens > 0); // Should have use-template suggestion for the getters bool hasTemplateSuggestion = false; for (const auto& s : est.optimizationSuggestions) { if (s.action == "use-template") { hasTemplateSuggestion = true; } } assert(hasTemplateSuggestion); std::cout << "PASS: test 2 — cost estimation with suggestions\n"; passed++; } // Test 3: CRUD template → route → deterministic completes { TemplateParams params; params.entityName = "Task"; auto wf = WorkflowTemplates::applyTemplate("crud-api", params); RoutingEngine routing; WorkerRegistry workers = WorkerRegistry::getDefaultRegistry(); ContextAssembler assembler; ReviewGate gate; WorkflowOrchestrator orchestrator(wf, routing, workers, assembler, gate); auto stats = orchestrator.runToCompletion(); // Template (getTask) and deterministic should auto-complete // LLM/SLM tasks will block at needs-external-model assert(stats.complete > 0 || stats.inProgress > 0); std::cout << "PASS: test 3 — CRUD template workflow execution\n"; passed++; } // Test 4: Dependency graph 5-function chain → critical path = 5 { WorkflowState wf("test"); wf.queue.enqueue(makeItem("t1", "step1")); wf.queue.enqueue(makeItem("t2", "step2", "", "local", "medium", {"t1"})); wf.queue.enqueue(makeItem("t3", "step3", "", "local", "medium", {"t2"})); wf.queue.enqueue(makeItem("t4", "step4", "", "local", "medium", {"t3"})); wf.queue.enqueue(makeItem("t5", "step5", "", "local", "medium", {"t4"})); auto graph = buildDependencyGraph(wf); auto path = getCriticalPath(graph); assert(path.size() == 5); assert(path[0] == "t1"); assert(path[4] == "t5"); std::cout << "PASS: test 4 — dependency graph critical path\n"; passed++; } // Test 5: Event stream captures workflow transitions { WorkflowState wf("test"); wf.queue.enqueue(makeItem("t1", "getName", "template", "local")); RoutingEngine routing; WorkerRegistry workers = WorkerRegistry::getDefaultRegistry(); ContextAssembler assembler; ReviewGate gate; EventStream stream; WorkflowOrchestrator orchestrator(wf, routing, workers, assembler, gate); auto events = orchestrator.advance(); // Emit events to stream for (const auto& ev : events) { stream.emit(ev); } assert(stream.getVersion() > 0); auto recent = stream.getRecent(10); assert(!recent.empty()); // Check that we see routing and execution events bool hasRouted = false, hasExecuted = false; for (const auto& se : recent) { if (se.event.type == "routed") hasRouted = true; if (se.event.type == "executed") hasExecuted = true; } assert(hasRouted); assert(hasExecuted); std::cout << "PASS: test 5 — event stream captures transitions\n"; passed++; } // Test 6: Full MCP client simulation through protocol phases { WorkflowSession session; session.sessionId = "test-session"; session.projectName = "integration-test"; // Phase transitions assert(validateTransition("init", "model")); assert(validateTransition("model", "annotate")); assert(validateTransition("annotate", "plan")); assert(validateTransition("plan", "route")); assert(validateTransition("route", "execute")); assert(validateTransition("execute", "assist")); assert(validateTransition("assist", "review")); assert(validateTransition("review", "complete")); assert(!validateTransition("complete", "init")); // can't go backward // getNextAction suggests correct phase auto action = getNextAction(session); assert(action.phase == "model" || action.phase == "init"); std::cout << "PASS: test 6 — protocol phase validation\n"; passed++; } // Test 7: Optimization: apply suggestion to narrow context → lower cost { WorkflowState wf("test"); // Getter at project width (wasteful) wf.queue.enqueue(makeItem("t1", "getName", "", "project")); RoutingEngine routing; CostEstimator estimator; auto est1 = estimator.estimate(wf, routing); int originalCost = est1.totalContextTokens; // Apply optimization: narrow to local auto item = wf.queue.getItem("t1"); WorkItem updated = item.value(); updated.contextWidth = "local"; wf.queue.updateItem("t1", updated); auto est2 = estimator.estimate(wf, routing); int optimizedCost = est2.totalContextTokens; assert(optimizedCost < originalCost); std::cout << "PASS: test 7 — optimization reduces cost\n"; passed++; } // Test 8: Sprint 15 totals verification { // Verify all new components exist and work together // RoutingRules auto defaults = RulesEngine::getDefaultRules(); assert(defaults.size() >= 5); // CostEstimator CostEstimator estimator; WorkflowState emptyWf("empty"); RoutingEngine routing; auto est = estimator.estimate(emptyWf, routing); assert(est.totalContextTokens == 0); // WorkflowTemplates auto templates = WorkflowTemplates::getTemplates(); assert(templates.size() == 5); // DependencyGraph auto graph = buildDependencyGraph(emptyWf); assert(graph.nodes.empty()); // EventStream EventStream stream; assert(stream.getVersion() == 0); // WorkflowProtocol auto phases = workflowProtocolPhases(); assert(phases.size() == 9); std::cout << "PASS: test 8 — Sprint 15 totals verification\n"; passed++; } std::cout << "\nStep 393 result: " << passed << "/8 tests passed\n"; return (passed == 8) ? 0 : 1; }