Accept messy idea dumps for feedback ranking
This commit is contained in:
@@ -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 = {}) {
|
||||
|
||||
Reference in New Issue
Block a user