#pragma once // Step 480: Multi-Language Project Orchestration // Creates one project workflow with build-ordering and cross-language links. #include "ArchitectBuildAwareness.h" #include #include #include #include #include #include struct CrossLanguageLink { std::string fromModule; std::string toModule; std::string fromLanguage; std::string toLanguage; std::string linkAnnotation; // @Link(...) std::string shimAnnotation; // @Shim(...) bool ffiBoundary = false; bool reviewRequired = false; }; struct OrchestrationTask { std::string taskId; std::string moduleName; std::string language; std::vector dependencies; int buildOrder = 0; bool reviewRequired = false; std::vector annotations; std::vector buildHints; }; struct MultiLanguageWorkflowPlan { std::vector tasks; std::vector links; std::vector notes; bool hasTask(const std::string& moduleName) const { for (const auto& t : tasks) if (t.moduleName == moduleName) return true; return false; } OrchestrationTask getTask(const std::string& moduleName) const { for (const auto& t : tasks) if (t.moduleName == moduleName) return t; return {}; } }; class ArchitectMultiLanguageOrchestrator { public: static MultiLanguageWorkflowPlan createWorkflow( const SkeletonProjectSpec& skeleton, const BuildAwarenessReport& awareness) { MultiLanguageWorkflowPlan out; const auto order = topoOrder(skeleton, out.notes); std::map byName; for (const auto& m : skeleton.modules) byName[m.moduleName] = m; std::set reviewModules; for (const auto& m : skeleton.modules) { for (const auto& dep : m.dependencies) { if (!byName.count(dep)) continue; const auto& to = byName[dep]; if (lower(m.language) == lower(to.language)) continue; CrossLanguageLink link; link.fromModule = m.moduleName; link.toModule = dep; link.fromLanguage = lower(m.language); link.toLanguage = lower(to.language); link.linkAnnotation = "@Link(" + m.moduleName + "->" + dep + ")"; link.shimAnnotation = "@Shim(" + link.fromLanguage + "_to_" + link.toLanguage + ")"; link.ffiBoundary = true; link.reviewRequired = true; out.links.push_back(std::move(link)); reviewModules.insert(m.moduleName); reviewModules.insert(dep); } } for (size_t i = 0; i < order.size(); ++i) { const auto& name = order[i]; if (!byName.count(name)) continue; const auto& m = byName[name]; OrchestrationTask task; task.taskId = "orchestrate-" + std::to_string(i + 1); task.moduleName = name; task.language = lower(m.language); task.dependencies = m.dependencies; task.buildOrder = (int)i + 1; task.reviewRequired = reviewModules.count(name) > 0; task.annotations.push_back("@Intent(orchestrate module " + name + ")"); task.annotations.push_back("@BuildOrder(" + std::to_string(task.buildOrder) + ")"); if (task.reviewRequired) task.annotations.push_back("@Review(ffi-boundary)"); auto hint = awareness.getModule(name); if (!hint.manifestSnippet.empty()) task.buildHints.push_back(hint.manifestSnippet); for (const auto& imp : hint.importHints) task.buildHints.push_back(imp); out.tasks.push_back(std::move(task)); } out.notes.push_back("Workflow spans all modules as a single project plan"); out.notes.push_back("Cross-language links emit @Link/@Shim and require human review"); return out; } private: static std::string lower(const std::string& s) { std::string out = s; std::transform(out.begin(), out.end(), out.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); return out; } static std::vector topoOrder(const SkeletonProjectSpec& skeleton, std::vector& notes) { std::map indeg; std::map> adj; std::set nodes; for (const auto& m : skeleton.modules) { nodes.insert(m.moduleName); if (!indeg.count(m.moduleName)) indeg[m.moduleName] = 0; } for (const auto& m : skeleton.modules) { for (const auto& dep : m.dependencies) { if (!nodes.count(dep)) continue; adj[dep].push_back(m.moduleName); indeg[m.moduleName]++; } } std::vector ready; for (const auto& n : nodes) { if (indeg[n] == 0) ready.push_back(n); } std::sort(ready.begin(), ready.end()); std::vector ordered; while (!ready.empty()) { const std::string current = ready.front(); ready.erase(ready.begin()); ordered.push_back(current); for (const auto& next : adj[current]) { indeg[next]--; if (indeg[next] == 0) { ready.push_back(next); std::sort(ready.begin(), ready.end()); } } } if (ordered.size() < nodes.size()) { std::vector remainder; for (const auto& n : nodes) { if (std::find(ordered.begin(), ordered.end(), n) == ordered.end()) { remainder.push_back(n); } } std::sort(remainder.begin(), remainder.end()); ordered.insert(ordered.end(), remainder.begin(), remainder.end()); notes.push_back("Dependency cycle detected: fallback lexical ordering applied"); } return ordered; } };