Files
whetstone_DSL/editor/src/ModernizationWorkflow.h
Bill ad6c1eb1f4 Complete Sprint 20: Legacy Code Ingestion (steps 439-448, 124/124 tests)
Phase 20a delivers legacy analysis, safety audit with CWE mapping,
modernization suggestions with effort routing, and RPC/MCP tools.
Phase 20b adds multi-file migration planning, API boundary preservation,
target-language test generation, and progressive migration execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 19:22:15 -07:00

180 lines
6.0 KiB
C++

#pragma once
// Step 441: Modernization Workflow Generation — converts modernization suggestions
// into an ordered workflow with routing (deterministic/LLM/human) and dependencies.
#include "ModernizationSuggester.h"
#include <string>
#include <vector>
enum class WorkItemRouting { Deterministic, LLM, Human };
struct ModernizeWorkItem {
std::string id;
std::string title;
std::string fromPattern;
std::string toReplacement;
std::string annotation;
WorkItemRouting routing = WorkItemRouting::Deterministic;
ModernizeEffort effort = ModernizeEffort::QuickWin;
int priority = 0; // lower = execute first
std::vector<std::string> dependsOn;
};
struct ModernizationSkeleton {
std::string originalSource;
std::string skeletonSource; // modernized structure with placeholders
std::string language;
std::vector<std::string> annotations;
};
struct ModernizationWorkflow {
std::string filePath;
std::string sourceLanguage;
std::string targetLanguage;
std::vector<ModernizeWorkItem> items;
ModernizationSkeleton skeleton;
int countByRouting(WorkItemRouting r) const {
int n = 0;
for (const auto& item : items)
if (item.routing == r) ++n;
return n;
}
bool hasItemFor(const std::string& from) const {
for (const auto& item : items)
if (item.fromPattern == from) return true;
return false;
}
std::vector<ModernizeWorkItem> itemsInOrder() const {
auto sorted = items;
std::sort(sorted.begin(), sorted.end(),
[](const ModernizeWorkItem& a, const ModernizeWorkItem& b) {
return a.priority < b.priority;
});
return sorted;
}
ModernizeWorkItem itemById(const std::string& id) const {
for (const auto& item : items)
if (item.id == id) return item;
return {};
}
};
class ModernizationWorkflowGenerator {
public:
static ModernizationWorkflow generate(const std::string& source,
const ModernizationReport& report) {
ModernizationWorkflow wf;
wf.filePath = report.filePath;
wf.sourceLanguage = report.sourceLanguage;
wf.targetLanguage = report.targetLanguage;
// Convert suggestions to work items with routing and priority
int idx = 0;
for (const auto& s : report.suggestions) {
ModernizeWorkItem item;
item.id = "mod-" + std::to_string(idx++);
item.title = s.fromPattern + " -> " + s.toReplacement;
item.fromPattern = s.fromPattern;
item.toReplacement = s.toReplacement;
item.annotation = s.annotation;
item.effort = s.effort;
item.routing = routeByEffort(s);
item.priority = priorityForEffort(s.effort);
wf.items.push_back(std::move(item));
}
// Set dependencies: deep refactors depend on quick wins completing first
setDependencies(wf);
// Generate skeleton
wf.skeleton = generateSkeleton(source, report);
return wf;
}
private:
static WorkItemRouting routeByEffort(const ModernizeSuggestion& s) {
if (s.effort == ModernizeEffort::QuickWin)
return WorkItemRouting::Deterministic;
if (s.effort == ModernizeEffort::DeepRefactor)
return WorkItemRouting::Human;
// Moderate: depends on risk
if (s.risk == "high")
return WorkItemRouting::Human;
return WorkItemRouting::LLM;
}
static int priorityForEffort(ModernizeEffort e) {
switch (e) {
case ModernizeEffort::QuickWin: return 0;
case ModernizeEffort::Moderate: return 1;
case ModernizeEffort::DeepRefactor: return 2;
}
return 1;
}
static void setDependencies(ModernizationWorkflow& wf) {
// Collect quick-win IDs
std::vector<std::string> quickWinIds;
for (const auto& item : wf.items)
if (item.effort == ModernizeEffort::QuickWin)
quickWinIds.push_back(item.id);
// Deep refactors depend on all quick wins
for (auto& item : wf.items) {
if (item.effort == ModernizeEffort::DeepRefactor) {
item.dependsOn = quickWinIds;
}
}
}
static ModernizationSkeleton generateSkeleton(const std::string& source,
const ModernizationReport& report) {
ModernizationSkeleton sk;
sk.originalSource = source;
sk.language = report.targetLanguage;
// Collect annotations
for (const auto& s : report.suggestions)
sk.annotations.push_back(s.annotation);
// Build skeleton: replace known patterns with placeholders
std::string skel = source;
for (const auto& s : report.suggestions) {
if (s.fromPattern == "malloc/free") {
replaceAll(skel, "malloc(", "/* @Modernize: smart_ptr */ malloc(");
replaceAll(skel, "free(", "/* @Modernize: remove_free */ free(");
}
if (s.fromPattern == "gets") {
replaceAll(skel, "gets(", "/* @Modernize: fgets */ gets(");
}
if (s.fromPattern == "sprintf") {
replaceAll(skel, "sprintf(", "/* @Modernize: snprintf */ sprintf(");
}
if (s.fromPattern == "strcpy") {
replaceAll(skel, "strcpy(", "/* @Modernize: strncpy */ strcpy(");
}
if (s.fromPattern == "goto") {
replaceAll(skel, "goto ", "/* @Modernize: structured_control */ goto ");
}
}
sk.skeletonSource = skel;
return sk;
}
static void replaceAll(std::string& str, const std::string& from,
const std::string& to) {
size_t pos = 0;
while ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.size(), to);
pos += to.size();
}
}
};