Preserve Scattermind build-order proof signals
This commit is contained in:
@@ -1087,6 +1087,33 @@ try {
|
||||
assert.ok(lensOnly.ranked.find(item => item.id === 'build-order-4').metrics.nonGoalConflicts.length >= 1);
|
||||
assert.deepEqual(lensOnly.handoff.warnings, []);
|
||||
|
||||
const signalLensResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
sourceName: 'Scattermind',
|
||||
reference_code: 'SM-SIGNAL-LENS',
|
||||
working_name: 'Signal-rich Build Order',
|
||||
ideaText: 'A paid Concept Map names the success and failure signal directly in its Build Order lens.',
|
||||
context: 'Solo builder. Manual proof first. Avoid accounts and dashboards until the signal is real.',
|
||||
mode: 'mvp',
|
||||
lenses: {
|
||||
risk: 'Avoid accounts and dashboards until the signal is real.',
|
||||
channel: 'Build first: Manual invite proof - ask five named buyers before building signup UI. Success signal: two people ask for a date. Failure signal: nobody replies with a concrete yes. Test manually: One-page promise - show the offer and collect yes/no replies. Green flag: people ask how to book. Red flag: people only say interesting.',
|
||||
},
|
||||
}),
|
||||
});
|
||||
assert.equal(signalLensResponse.status, 200);
|
||||
const signalLens = await signalLensResponse.json();
|
||||
assert.equal(signalLens.ranked[0].id, 'build-order-1');
|
||||
assert.equal(signalLens.ranked[0].factors.successSignal, 'two people ask for a date');
|
||||
assert.equal(signalLens.ranked[0].factors.killSignal, 'nobody replies with a concrete yes');
|
||||
assert.equal(signalLens.handoff.activeSlice.proof.successSignal, 'two people ask for a date');
|
||||
assert.equal(signalLens.handoff.activeSlice.proof.killSignal, 'nobody replies with a concrete yes');
|
||||
assert.equal(signalLens.ranked.find(item => item.id === 'build-order-2').factors.successSignal, 'people ask how to book');
|
||||
assert.equal(signalLens.ranked.find(item => item.id === 'build-order-2').factors.killSignal, 'people only say interesting');
|
||||
assert.deepEqual(signalLens.handoff.warnings, []);
|
||||
|
||||
const scattermindPaidShapeResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
@@ -1216,7 +1216,7 @@ function normalizeBuildOrderFragment(fragment = '') {
|
||||
function sentenceFragments(text = '') {
|
||||
return cleanMultiline(text, 4000)
|
||||
.replace(new RegExp(`\\s+${buildOrderLabelPattern}${buildOrderLabelSeparator}`, 'gi'), '\n$1: ')
|
||||
.split(/\n|;|\s+[•-]\s+/)
|
||||
.split(/\n|;|\s+•\s+/)
|
||||
.map(part => normalizeBuildOrderFragment(part))
|
||||
.filter(Boolean);
|
||||
}
|
||||
@@ -1240,6 +1240,8 @@ function optionsFromBuildOrderText(text = '', sourceSection = 'concept-map.lense
|
||||
const labelled = fragments.filter(fragment => laneFromBuildOrderLabel(fragment));
|
||||
return labelled.map((fragment, index) => {
|
||||
const lane = laneFromBuildOrderLabel(fragment);
|
||||
const successSignal = signalFromThreadText(fragment, ['success signal', 'green flag', 'working if', 'working when']);
|
||||
const failureSignal = signalFromThreadText(fragment, ['failure signal', 'red flag', 'failing if', 'failing when', 'stop if', 'kill signal']);
|
||||
return {
|
||||
id: `build-order-${index + 1}`,
|
||||
action: titleFromBuildOrderFragment(fragment),
|
||||
@@ -1251,6 +1253,8 @@ function optionsFromBuildOrderText(text = '', sourceSection = 'concept-map.lense
|
||||
: lane === 'validate-next'
|
||||
? 'Collect the smallest real signal before promoting this into the build lane.'
|
||||
: '',
|
||||
successSignal,
|
||||
killSignal: failureSignal,
|
||||
suggestedLane: lane,
|
||||
rankerHints: lane === 'do-first'
|
||||
? { value: 8, effort: 2, confidence: 7, urgency: 7, risk: 2 }
|
||||
|
||||
Reference in New Issue
Block a user