Sprint 42-45: stabilize modeling tools and implement context, validation, and metrics MCP tooling (Steps 669-688)
This commit is contained in:
82
editor/src/SelfContainmentScorer.h
Normal file
82
editor/src/SelfContainmentScorer.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
// Step 680: Score taskitem self-containment quality.
|
||||
|
||||
#include "PrerequisiteOpResolver.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ScoredTaskitem {
|
||||
std::string taskId;
|
||||
int score = 0;
|
||||
bool selfContained = false;
|
||||
std::vector<std::string> issues;
|
||||
};
|
||||
|
||||
struct TaskitemInput {
|
||||
std::string taskId;
|
||||
std::string title;
|
||||
std::vector<std::string> prerequisiteOps;
|
||||
std::vector<std::string> reasons;
|
||||
int confidence = 0;
|
||||
std::vector<std::string> dependencyTaskIds;
|
||||
};
|
||||
|
||||
class SelfContainmentScorer {
|
||||
public:
|
||||
static ScoredTaskitem score(const TaskitemInput& item,
|
||||
const std::string& workspaceRoot) {
|
||||
ScoredTaskitem out;
|
||||
out.taskId = item.taskId;
|
||||
int scoreValue = 100;
|
||||
|
||||
if (item.prerequisiteOps.empty()) {
|
||||
scoreValue -= 30;
|
||||
out.issues.push_back("prerequisiteOps missing or empty");
|
||||
}
|
||||
|
||||
int unresolvedDeduction = 0;
|
||||
if (!item.prerequisiteOps.empty()) {
|
||||
auto resolved = PrerequisiteOpResolver::resolveAll(item.prerequisiteOps, workspaceRoot);
|
||||
for (const auto& op : resolved) {
|
||||
if (op.kind == OpKind::ReadFile && !op.fileExists) {
|
||||
unresolvedDeduction += 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
unresolvedDeduction = std::min(unresolvedDeduction, 30);
|
||||
if (unresolvedDeduction > 0) {
|
||||
scoreValue -= unresolvedDeduction;
|
||||
out.issues.push_back("prerequisiteOps include unresolved file paths");
|
||||
}
|
||||
|
||||
if (item.reasons.empty()) {
|
||||
scoreValue -= 20;
|
||||
out.issues.push_back("reasons missing or empty");
|
||||
} else if (item.reasons.size() < 3) {
|
||||
scoreValue -= 10;
|
||||
out.issues.push_back("reasons has fewer than 3 entries");
|
||||
}
|
||||
|
||||
if (item.confidence == 0) {
|
||||
scoreValue -= 10;
|
||||
out.issues.push_back("confidence not set");
|
||||
}
|
||||
|
||||
if (item.title.empty()) {
|
||||
scoreValue -= 20;
|
||||
out.issues.push_back("title empty");
|
||||
}
|
||||
|
||||
if (!item.dependencyTaskIds.empty()) {
|
||||
scoreValue -= 5;
|
||||
out.issues.push_back("dependencyTaskIds not empty");
|
||||
}
|
||||
|
||||
out.score = std::clamp(scoreValue, 0, 100);
|
||||
out.selfContained = out.score >= 80;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user