UNPKG

@autobe/agent

Version:

AI backend server code generator

105 lines 3.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildFileDecisionConflictMap = exports.detectDecisionConflicts = void 0; // ─── Main Detection ─── /** * Detect decision-level conflicts across all files. * * Groups all extracted decisions by `topic + decision` key, then finds cases * where different files assign different values to the same key. * * This catches prose-level contradictions like: * * - File A: "password change requires current password" (yes) * - File B: "password change does not require current password" (no) */ const detectDecisionConflicts = (props) => { // Group by topic+decision const groups = new Map(); for (const { filename, decisions } of props.fileDecisions) { for (const d of decisions) { const key = `${normalizeKey(d.topic)}::${normalizeKey(d.decision)}`; if (!groups.has(key)) groups.set(key, []); groups.get(key).push({ value: normalizeValue(d.value), filename, evidence: d.evidence, }); } } // Find conflicts: same key, different values const conflicts = []; for (const [key, entries] of groups) { // Group entries by value const byValue = new Map(); for (const entry of entries) { if (!byValue.has(entry.value)) byValue.set(entry.value, []); byValue.get(entry.value).push({ filename: entry.filename, evidence: entry.evidence, }); } // If more than one distinct value exists → conflict if (byValue.size <= 1) continue; const [topic, decision] = key.split("::"); conflicts.push({ topic: topic, decision: decision, values: [...byValue.entries()].map(([value, sources]) => { var _a, _b; return ({ value, files: sources.map((s) => s.filename), evidence: (_b = (_a = sources[0]) === null || _a === void 0 ? void 0 : _a.evidence) !== null && _b !== void 0 ? _b : "", }); }), }); } return conflicts; }; exports.detectDecisionConflicts = detectDecisionConflicts; /** * Build a map from filename → list of decision conflict feedback strings. * * Each file involved in a conflict gets feedback describing the contradiction. */ const buildFileDecisionConflictMap = (conflicts) => { const map = new Map(); for (const conflict of conflicts) { const valueSummary = conflict.values .map((v) => `"${v.value}" in [${v.files.join(", ")}]`) .join(" vs "); const feedback = `Decision conflict: ${conflict.topic}.${conflict.decision}${valueSummary}. ` + `Files must agree on this decision. Align with the canonical source.`; // Add feedback to ALL files involved in this conflict for (const valueGroup of conflict.values) { for (const filename of valueGroup.files) { if (!map.has(filename)) map.set(filename, []); map.get(filename).push(feedback); } } } return map; }; exports.buildFileDecisionConflictMap = buildFileDecisionConflictMap; // ─── Helpers ─── /** * Normalize a key string for grouping: lowercase, replace whitespace/special * chars with underscore, trim. */ function normalizeKey(s) { return s .toLowerCase() .trim() .replace(/[\s\-\.]+/g, "_") .replace(/[^a-z0-9_]/g, ""); } /** Normalize a value for comparison: lowercase, trim, collapse whitespace. */ function normalizeValue(s) { return s.toLowerCase().trim().replace(/\s+/g, " "); } //# sourceMappingURL=detectDecisionConflicts.js.map