Carry Scattermind proof lens into ranking

This commit is contained in:
OpenClaw Bot
2026-05-27 18:50:34 +02:00
parent e463f4bc2a
commit 7ed035af82
2 changed files with 55 additions and 2 deletions
+49 -1
View File
@@ -1059,6 +1059,41 @@ function optionsFromBuildOrderText(text = '', sourceSection = 'concept-map.lense
}).filter(item => item.action);
}
function proofStepFragments(text = '') {
return cleanMultiline(text, 2600)
.replace(/\b(proof steps?|test manually|validate|evidence to collect|next proof)\s*:/gi, '\n')
.split(/\n|;|\s+[•-]\s+|\.\s+/)
.map(part => part.replace(/^\s*[-*•\d.)]+\s*/, '').trim())
.filter(Boolean)
.filter(part => /\b(run|ask|show|send|test|validate|prototype|mock|observe|interview|collect|measure|prove|disprove|manual|concierge|offer|script|reply|signal)\b/i.test(part))
.filter(part => !/^\s*(avoid|no|do not|don't|defer|probably noise|park|hold for later)\b/i.test(part))
.slice(0, 3);
}
function proofTitleFromFragment(fragment = '') {
const cleaned = cleanText(fragment
.replace(/^(run|ask|show|send|test|validate|prototype|mock|observe|interview|collect|measure)\b\s*/i, match => match.trim()[0].toUpperCase() + match.trim().slice(1).toLowerCase() + ' ')
.replace(/\s+before\s+.*$/i, '')
.replace(/\s+and\s+record\s+.*$/i, ''), 180);
return cleanText(cleaned.split(/\s[-–—:]\s/)[0] || cleaned, 120);
}
function optionsFromProofLensText(text = '', sourceSection = 'concept-map.lenses.question', sourceTitle = 'Proof Steps') {
return proofStepFragments(text).map((fragment, index) => ({
id: `proof-step-${index + 1}`,
action: proofTitleFromFragment(fragment),
why: 'Scattermind named this as proof to collect before promoting more build surface.',
evidence: fragment,
validationSteps: [fragment],
suggestedLane: 'validate-next',
rankerHints: { value: 7, effort: 2, confidence: 6, urgency: 6, risk: 3 },
sourceSection,
sourceItemId: `${sourceSection}#${index + 1}`,
sourceTitle,
sourceExcerpt: fragment,
})).filter(item => item.action);
}
function laneFromActionThread(text = '') {
if (/\b(probably noise|set aside|park|parking lot|do not build|don't build|not worth|distraction)\b/i.test(text)) return 'park';
if (/\b(defer|not yet|later|hold for later|after proof|wait until)\b/i.test(text)) return 'defer';
@@ -1283,7 +1318,20 @@ function optionsFromBody(body = {}) {
140
);
const buildOrderOptions = optionsFromBuildOrderText(buildOrderText, 'concept-map.lenses.channel', buildOrderSourceTitle);
if (buildOrderOptions.length) return normalizeCandidateGroup([{ items: buildOrderOptions, sourceSection: 'concept-map.lenses.channel' }]);
if (buildOrderOptions.length) {
const proofLens = objectFrom(conceptMapLenses.question || conceptMapLenses.proof || conceptMapLenses.validation || conceptMapLenses.evidence);
const proofLensText = lensContent(conceptMapLenses.question)
|| lensContent(conceptMapLenses.proof)
|| lensContent(conceptMapLenses.validation)
|| lensContent(conceptMapLenses.evidence)
|| '';
const proofSourceTitle = cleanText(proofLens.title || 'Proof Steps', 140);
const proofOptions = optionsFromProofLensText(proofLensText, 'concept-map.lenses.question', proofSourceTitle);
return normalizeCandidateGroup([
{ items: buildOrderOptions, sourceSection: 'concept-map.lenses.channel' },
...(proofOptions.length ? [{ items: proofOptions, sourceSection: 'concept-map.lenses.question', defaultLane: 'validate-next' }] : []),
]);
}
const actionThreadSource = firstArraySource([
{ items: conceptMap.threads_to_hold || conceptMap.threadsToHold || conceptMap.actionThreads || conceptMap.action_threads, sourceSection: 'concept-map.threadsToHold' },
{ items: snapshot.threads_to_hold || snapshot.threadsToHold || snapshot.actionThreads || snapshot.action_threads, sourceSection: 'snapshot.threadsToHold' },