scai
Version:
> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with ❤️.
88 lines (87 loc) • 3.69 kB
JavaScript
import { logInputOutput } from "../utils/promptLogHelper.js";
export const validationAnalysisStep = {
name: "validationAnalysis",
description: "Validate semantic analysis results and verify that focused working files were correctly synced into plan.targetFiles.",
groups: ["analysis"],
run: async (input) => {
const ctx = input.context;
if (!ctx) {
throw new Error("[validationAnalysisStep] StructuredContext is required but was not provided.");
}
const notes = [];
const warnings = [];
// -----------------------------
// Focus validation
// -----------------------------
const focusFiles = ctx.analysis?.focus?.relevantFiles ?? [];
if (!focusFiles.length) {
warnings.push("No relevant files found in analysis.focus.");
}
// -----------------------------
// Semantic understanding validation
// -----------------------------
const understanding = ctx.analysis?.understanding;
if (!understanding) {
notes.push("No semantic understanding produced by analysis.");
}
else {
if (!understanding.risks?.length) {
notes.push("No risks recorded in analysis.understanding.");
}
if (!understanding.assumptions?.length) {
notes.push("No assumptions recorded in analysis.understanding.");
}
}
// -----------------------------
// Intent presence & shape validation
// (Produced by understandIntent step)
// -----------------------------
const intent = ctx.analysis?.intent;
if (!intent) {
warnings.push("No intent found in context (expected from understandIntent step).");
}
else {
if (!intent.intent || !intent.intentCategory) {
warnings.push("Intent is missing required fields (intent/intentCategory).");
}
if (typeof intent.confidence !== "number") {
warnings.push("Intent confidence not set or invalid.");
}
}
// -----------------------------
// Plan.targetFiles consistency validation
// -----------------------------
const plan = ctx.plan;
const workingFiles = new Set(ctx.workingFiles?.map(f => f.path) ?? []);
const targetFiles = new Set(plan?.targetFiles ?? []);
if (!plan) {
warnings.push("No plan found in context; target files were not validated.");
}
else {
// Only focused files that are also working files are expected to be in the plan
const expectedTargetFiles = focusFiles.filter(f => workingFiles.has(f));
const missing = expectedTargetFiles.filter(f => !targetFiles.has(f));
if (missing.length > 0) {
warnings.push(`Some focused working files were not added to plan.targetFiles: ${missing.join(", ")}`);
}
}
const output = {
query: input.query,
data: {
notes,
warnings,
summary: {
focusValid: focusFiles.length > 0,
semanticValid: !!understanding,
intentValid: !!intent,
planFilesValid: !!plan &&
focusFiles
.filter(f => workingFiles.has(f))
.every(f => targetFiles.has(f)),
},
},
};
logInputOutput("validationAnalysis", "output", output.data);
return output;
},
};