Accept messy idea dumps for feedback ranking

This commit is contained in:
OpenClaw Bot
2026-05-27 00:12:09 +02:00
parent 802657b638
commit 602937d9b2
4 changed files with 69 additions and 15 deletions
+43 -9
View File
@@ -428,18 +428,40 @@ function hits(text, words) {
return words.reduce((count, word) => count + (lower.includes(word) ? 1 : 0), 0);
}
function parseOptionsFromText(value) {
function parseOptionsFromText(value, sourceSection = 'optionsText') {
const text = cleanMultiline(value, 12000);
const lines = text.split('\n').map(line => line.replace(/^\s*[-*•\d.)]+\s*/, '').trim()).filter(Boolean);
const optionLines = lines.length >= 2 ? lines : text.split(/[;|]/).map(part => part.trim()).filter(Boolean);
const candidateText = /\b(maybe|possibly|options?|features?|ideas?|next moves?|functionality|backlog)\b[:\s]/i.test(text)
? text.replace(/^[\s\S]*?\b(maybe|possibly|options?|features?|ideas?|next moves?|functionality|backlog)\b[:\s]*/i, '')
: text;
const cleanedLines = candidateText.split('\n').map(line => line.replace(/^\s*[-*•\d.)]+\s*/, '').trim()).filter(Boolean);
const sentenceList = candidateText
.replace(/\b(maybe|possibly|options?|features?|ideas?|next moves?|functionality|backlog)\s*:/gi, '\n')
.split(/\n|;|\|/)
.map(part => part.replace(/^\s*[-*•\d.)]+\s*/, '').trim())
.filter(Boolean);
const commaList = sentenceList.length === 1
? sentenceList[0].split(/,|\s+and\s+|[.!?]\s+/i).map(part => part.trim()).filter(Boolean)
: [];
const optionLines = cleanedLines.length >= 2
? cleanedLines
: sentenceList.length >= 2
? sentenceList
: commaList.length >= 2
? commaList
: candidateText.split(/[;|]/).map(part => part.trim()).filter(Boolean);
return optionLines.slice(0, 24).map((line, index) => {
const [rawTitle, ...rest] = line.split(/\s*[-–—:]\s+/);
const normalized = line
.replace(/^\s*(maybe|possibly|also|plus|and|or|then|later|eventually|build|add|include|some kind of|kind of)\b\s*/i, '')
.replace(/\?+$/, '')
.trim();
const [rawTitle, ...rest] = normalized.split(/\s*[-–—:]\s+/);
return {
id: `option-${index + 1}`,
title: cleanText(rawTitle || line, 140),
title: cleanText(rawTitle || normalized || line, 140),
description: cleanText(rest.join(' — '), 420),
provenance: { sourceSection },
};
}).filter(item => item.title);
}).filter(item => item.title && !/^(i('| a)?m|i am|we are|i only|want|need)\b/i.test(item.title));
}
function objectFrom(value) {
@@ -458,7 +480,7 @@ function cleanProvenance(input = {}) {
artifactId: cleanText(input.artifactId || input.sourceArtifactId || input.referenceCode || input.reference_code || artifact.id || source.artifactId || conceptMap.artifactId || conceptMap.id || conceptMap.referenceCode || conceptMap.reference_code || snapshot.artifactId || snapshot.id || '', 120),
snapshotTitle: cleanText(input.snapshotTitle || input.working_name || input.workingName || artifact.snapshotTitle || snapshot.title || snapshot.name || conceptMap.snapshotTitle || conceptMap.working_name || conceptMap.workingName || input.ideaTitle || '', 160),
conceptMapId: cleanText(input.conceptMapId || artifact.conceptMapId || conceptMap.id || conceptMap.artifactId || input.referenceCode || input.reference_code || conceptMap.referenceCode || conceptMap.reference_code || '', 120),
originalPrompt: cleanMultiline(input.originalPrompt || input.initialPrompt || input.ideaText || input.prompt || artifact.originalPrompt || source.originalPrompt || snapshot.originalPrompt || snapshot.prompt || conceptMap.originalPrompt || conceptMap.ideaText || '', 1200),
originalPrompt: cleanMultiline(input.originalPrompt || input.initialPrompt || input.ideaText || input.prompt || artifact.originalPrompt || source.originalPrompt || snapshot.originalPrompt || snapshot.prompt || conceptMap.originalPrompt || conceptMap.ideaText || input.idea || '', 1200),
};
}
@@ -560,7 +582,11 @@ function nonGoalConflicts(optionText, decisionContext = {}) {
const lower = String(optionText || '').toLowerCase();
return (decisionContext.nonGoals || []).filter(nonGoal => {
const tokens = meaningfulTokens(nonGoal);
return tokens.length > 0 && tokens.some(token => lower.includes(token));
return tokens.length > 0 && tokens.some(token => {
if (lower.includes(token)) return true;
const singular = token.endsWith('ies') ? `${token.slice(0, -3)}y` : token.replace(/(?:es|s)$/, '');
return singular.length >= 4 && lower.includes(singular);
});
});
}
@@ -704,7 +730,15 @@ function optionsFromBody(body = {}) {
if (Array.isArray(body.options)) {
return normalizeOptionIds(body.options.slice(0, 24).map((item, index) => normalizeFeatureOption(item, index, 'option', 'options')).filter(item => item.title));
}
return normalizeOptionIds(parseOptionsFromText(body.optionsText || featureSet.optionsText || conceptMap.optionsText || ''));
const fallbackText = body.optionsText || featureSet.optionsText || conceptMap.optionsText || body.idea || body.ideaText || '';
const fallbackSourceSection = body.optionsText || featureSet.optionsText || conceptMap.optionsText
? 'optionsText'
: body.idea
? 'idea'
: body.ideaText
? 'ideaText'
: 'optionsText';
return normalizeOptionIds(parseOptionsFromText(fallbackText, fallbackSourceSection));
}
function scoreOption(option, mode, context = '', decisionContext = {}) {